Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more info in setWindowOpenHandler details (#28518) #29277

Merged
merged 1 commit into from May 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/browser-window.md
Expand Up @@ -1382,7 +1382,7 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer URL.
* `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n"
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
* `baseURLForDataURL` String (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specified `url` is a data URL and needs to load other files.

Returns `Promise<void>` - the promise will resolve when the page has finished loading
Expand Down
2 changes: 1 addition & 1 deletion docs/api/structures/post-body.md
@@ -1,6 +1,6 @@
# PostBody Object

* `data` Array<[PostData](./post-data.md)> - The post data to be sent to the
* `data` ([UploadRawData](upload-raw-data.md) | [UploadFile](upload-file.md))[] - The post data to be sent to the
new window.
* `contentType` String - The `content-type` header used for the data. One of
`application/x-www-form-urlencoded` or `multipart/form-data`. Corresponds to
Expand Down
21 changes: 0 additions & 21 deletions docs/api/structures/post-data.md

This file was deleted.

11 changes: 10 additions & 1 deletion docs/api/web-contents.md
Expand Up @@ -914,7 +914,7 @@ in `webPreferences`.
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
* `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n".
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.

Returns `Promise<void>` - the promise will resolve when the page has finished loading
Expand Down Expand Up @@ -1184,6 +1184,15 @@ Ignore application menu shortcuts while this web contents is focused.
* `url` String - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
* `frameName` String - Name of the window provided in `window.open()`
* `features` String - Comma separated list of window features provided to `window.open()`.
* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`,
`new-window`, `save-to-disk` or `other`.
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
passed to the new window. May or may not result in the `Referer` header being
sent, depending on the referrer policy.
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data that
will be sent to the new window, along with the appropriate headers that will
be set. If no post data is to be sent, the value will be `null`. Only defined
when the window is being created by a form that set `target=_blank`.

Returns `{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
Expand Down
2 changes: 1 addition & 1 deletion docs/api/webview-tag.md
Expand Up @@ -274,7 +274,7 @@ webview.addEventListener('dom-ready', () => {
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
* `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n"
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.

Returns `Promise<void>` - The promise will resolve when the page has finished loading
Expand Down
1 change: 0 additions & 1 deletion filenames.auto.gni
Expand Up @@ -103,7 +103,6 @@ auto_filenames = {
"docs/api/structures/notification-response.md",
"docs/api/structures/point.md",
"docs/api/structures/post-body.md",
"docs/api/structures/post-data.md",
"docs/api/structures/printer-info.md",
"docs/api/structures/process-memory-info.md",
"docs/api/structures/process-metric.md",
Expand Down
44 changes: 32 additions & 12 deletions lib/browser/api/web-contents.ts
Expand Up @@ -3,7 +3,7 @@ import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/m

import * as url from 'url';
import * as path from 'path';
import { openGuestWindow, makeWebPreferences } from '@electron/internal/browser/guest-window-manager';
import { openGuestWindow, makeWebPreferences, parseContentTypeFormat } from '@electron/internal/browser/guest-window-manager';
import { NavigationController } from '@electron/internal/browser/navigation-controller';
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
Expand Down Expand Up @@ -411,11 +411,11 @@ WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electr
this._windowOpenHandler = handler;
};

WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, url: string, frameName: string, rawFeatures: string): BrowserWindowConstructorOptions | null {
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): BrowserWindowConstructorOptions | null {
if (!this._windowOpenHandler) {
return null;
}
const response = this._windowOpenHandler({ url, frameName, features: rawFeatures });
const response = this._windowOpenHandler(details);

if (typeof response !== 'object') {
event.preventDefault();
Expand Down Expand Up @@ -571,9 +571,21 @@ WebContents.prototype._init = function () {

if (this.getType() !== 'remote') {
// Make new windows requested by links behave like "window.open".
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: string,
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: Electron.HandlerDetails['disposition'],
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
const options = this._callWindowOpenHandler(event, url, frameName, rawFeatures);
const postBody = postData ? {
data: postData,
...parseContentTypeFormat(postData)
} : undefined;
const details: Electron.HandlerDetails = {
url,
frameName,
features: rawFeatures,
referrer,
postBody,
disposition
};
const options = this._callWindowOpenHandler(event, details);
if (!event.defaultPrevented) {
openGuestWindow({
event,
Expand All @@ -582,18 +594,26 @@ WebContents.prototype._init = function () {
referrer,
postData,
overrideBrowserWindowOptions: options || {},
windowOpenArgs: {
url,
frameName,
features: rawFeatures
}
windowOpenArgs: details
});
}
});

let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string) => {
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, url, frameName, rawFeatures);
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
const postBody = postData ? {
data: postData,
...parseContentTypeFormat(postData)
} : undefined;
const details: Electron.HandlerDetails = {
url,
frameName,
features: rawFeatures,
disposition,
referrer,
postBody
};
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
if (!event.defaultPrevented) {
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
// Allow setting of backgroundColor as a webPreference even though
Expand Down
2 changes: 1 addition & 1 deletion lib/browser/guest-window-manager.ts
Expand Up @@ -292,7 +292,7 @@ const MULTIPART_CONTENT_TYPE = 'multipart/form-data';
const URL_ENCODED_CONTENT_TYPE = 'application/x-www-form-urlencoded';

// Figure out appropriate headers for post data.
const parseContentTypeFormat = function (postData: Exclude<PostData, undefined>) {
export const parseContentTypeFormat = function (postData: Exclude<PostData, undefined>) {
if (postData.length) {
if (postData[0].type === 'rawData') {
// For multipart forms, the first element will start with the boundary
Expand Down
5 changes: 3 additions & 2 deletions lib/browser/guest-window-proxy.ts
Expand Up @@ -73,14 +73,15 @@ ipcMainInternal.on(
);
}

const browserWindowOptions = event.sender._callWindowOpenHandler(event, url, frameName, features);
const referrer: Electron.Referrer = { url: '', policy: 'strict-origin-when-cross-origin' };
const browserWindowOptions = event.sender._callWindowOpenHandler(event, { url, frameName, features, disposition: 'new-window', referrer });
if (event.defaultPrevented) {
return;
}
const guest = openGuestWindow({
event,
embedder: event.sender,
referrer: { url: '', policy: 'default' },
referrer,
disposition: 'new-window',
overrideBrowserWindowOptions: browserWindowOptions!,
windowOpenArgs: {
Expand Down
5 changes: 3 additions & 2 deletions shell/browser/api/electron_api_web_contents.cc
Expand Up @@ -1013,8 +1013,9 @@ bool WebContents::IsWebContentsCreationOverridden(
content::mojom::WindowContainerType window_container_type,
const GURL& opener_url,
const content::mojom::CreateNewWindowParams& params) {
bool default_prevented = Emit("-will-add-new-contents", params.target_url,
params.frame_name, params.raw_features);
bool default_prevented = Emit(
"-will-add-new-contents", params.target_url, params.frame_name,
params.raw_features, params.disposition, *params.referrer, params.body);
// If the app prevented the default, redirect to CreateCustomWebContents,
// which always returns nullptr, which will result in the window open being
// prevented (window.open() will return null in the renderer).
Expand Down
29 changes: 29 additions & 0 deletions shell/common/gin_converters/blink_converter.cc
Expand Up @@ -13,6 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "gin/converter.h"
#include "shell/common/gin_converters/gfx_converter.h"
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/keyboard_util.h"
Expand All @@ -23,6 +24,7 @@
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "third_party/blink/public/common/widget/device_emulation_params.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
Expand Down Expand Up @@ -481,6 +483,33 @@ bool Converter<network::mojom::ReferrerPolicy>::FromV8(
return true;
}

// static
v8::Local<v8::Value> Converter<blink::mojom::Referrer>::ToV8(
v8::Isolate* isolate,
const blink::mojom::Referrer& val) {
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
dict.Set("url", ConvertToV8(isolate, val.url));
dict.Set("policy", ConvertToV8(isolate, val.policy));
return gin::ConvertToV8(isolate, dict);
}
//
// static
bool Converter<blink::mojom::Referrer>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::mojom::Referrer* out) {
gin_helper::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;

if (!dict.Get("url", &out->url))
return false;

if (!dict.Get("policy", &out->policy))
return false;

return true;
}

v8::Local<v8::Value> Converter<blink::CloneableMessage>::ToV8(
v8::Isolate* isolate,
const blink::CloneableMessage& in) {
Expand Down
10 changes: 10 additions & 0 deletions shell/common/gin_converters/blink_converter.h
Expand Up @@ -10,6 +10,7 @@
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/messaging/cloneable_message.h"
#include "third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom-forward.h"

namespace blink {
class WebMouseEvent;
Expand Down Expand Up @@ -95,6 +96,15 @@ struct Converter<network::mojom::ReferrerPolicy> {
network::mojom::ReferrerPolicy* out);
};

template <>
struct Converter<blink::mojom::Referrer> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const blink::mojom::Referrer& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::mojom::Referrer* out);
};

template <>
struct Converter<blink::CloneableMessage> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Expand Down
2 changes: 1 addition & 1 deletion spec-main/api-browser-window-spec.ts
Expand Up @@ -3249,7 +3249,7 @@ describe('BrowserWindow module', () => {
expect(additionalFeatures).to.deep.equal([]);
expect(postBody.data).to.have.length(1);
expect(postBody.data[0].type).to.equal('rawData');
expect(postBody.data[0].bytes).to.deep.equal(Buffer.from('post-test-key=post-test-value'));
expect((postBody.data[0] as any).bytes).to.deep.equal(Buffer.from('post-test-key=post-test-value'));
expect(postBody.contentType).to.equal('application/x-www-form-urlencoded');
});
});
Expand Down
10 changes: 5 additions & 5 deletions spec-main/fixtures/snapshots/proxy-window-open.snapshot.txt
Expand Up @@ -30,7 +30,7 @@
[],
{
"url": "",
"policy": "default"
"policy": "strict-origin-when-cross-origin"
},
null
],
Expand Down Expand Up @@ -64,7 +64,7 @@
[],
{
"url": "",
"policy": "default"
"policy": "strict-origin-when-cross-origin"
},
null
],
Expand Down Expand Up @@ -98,7 +98,7 @@
[],
{
"url": "",
"policy": "default"
"policy": "strict-origin-when-cross-origin"
},
null
],
Expand Down Expand Up @@ -131,7 +131,7 @@
[],
{
"url": "",
"policy": "default"
"policy": "strict-origin-when-cross-origin"
},
null
],
Expand Down Expand Up @@ -165,7 +165,7 @@
[],
{
"url": "",
"policy": "default"
"policy": "strict-origin-when-cross-origin"
},
null
]
Expand Down