diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts
index baa446ab91dae..76da71b15abcf 100644
--- a/lib/browser/guest-window-manager.ts
+++ b/lib/browser/guest-window-manager.ts
@@ -78,6 +78,19 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
...browserWindowOptions
});
+ if (!guest) {
+ // When we open a new window from a link (via OpenURLFromTab),
+ // the browser process is responsible for initiating navigation
+ // in the new window.
+ window.loadURL(url, {
+ httpReferrer: referrer,
+ ...(postData && {
+ postData,
+ extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
+ })
+ });
+ }
+
handleWindowLifecycleEvents({ embedder, frameName, guest: window, outlivesOpener });
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
@@ -243,6 +256,15 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
};
}
+function formatPostDataHeaders (postData: PostData) {
+ if (!postData) return;
+
+ const { contentType, boundary } = parseContentTypeFormat(postData);
+ if (boundary != null) { return `content-type: ${contentType}; boundary=${boundary}`; }
+
+ return `content-type: ${contentType}`;
+}
+
const MULTIPART_CONTENT_TYPE = 'multipart/form-data';
const URL_ENCODED_CONTENT_TYPE = 'application/x-www-form-urlencoded';
diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts
index 1b5f4260b8489..6d76851d82b2e 100644
--- a/spec-main/api-browser-window-spec.ts
+++ b/spec-main/api-browser-window-spec.ts
@@ -1937,6 +1937,26 @@ describe('BrowserWindow module', () => {
});
});
+ describe('Opening a BrowserWindow from a link', () => {
+ let appProcess: childProcess.ChildProcessWithoutNullStreams | undefined;
+
+ afterEach(() => {
+ if (appProcess && !appProcess.killed) {
+ appProcess.kill();
+ appProcess = undefined;
+ }
+ });
+
+ it('can properly open and load a new window from a link', async () => {
+ const appPath = path.join(__dirname, 'fixtures', 'apps', 'open-new-window-from-link');
+
+ appProcess = childProcess.spawn(process.execPath, [appPath]);
+
+ const [code] = await emittedOnce(appProcess, 'exit');
+ expect(code).to.equal(0);
+ });
+ });
+
describe('BrowserWindow.fromWebContents(webContents)', () => {
afterEach(closeAllWindows);
diff --git a/spec-main/fixtures/apps/open-new-window-from-link/index.html b/spec-main/fixtures/apps/open-new-window-from-link/index.html
new file mode 100644
index 0000000000000..b7584564e0010
--- /dev/null
+++ b/spec-main/fixtures/apps/open-new-window-from-link/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Hello World!
+
+
+ Open New Window
+
+
diff --git a/spec-main/fixtures/apps/open-new-window-from-link/main.js b/spec-main/fixtures/apps/open-new-window-from-link/main.js
new file mode 100644
index 0000000000000..7d41b3bb29ee5
--- /dev/null
+++ b/spec-main/fixtures/apps/open-new-window-from-link/main.js
@@ -0,0 +1,64 @@
+const { app, BrowserWindow } = require('electron');
+const path = require('path');
+
+async function createWindow () {
+ const mainWindow = new BrowserWindow({
+ width: 800,
+ height: 600,
+ x: 100,
+ y: 100,
+ webPreferences: {
+ preload: path.join(__dirname, 'preload.js'),
+ contextIsolation: false,
+ nodeIntegration: true
+ }
+ });
+
+ await mainWindow.loadFile('index.html');
+
+ const rect = await mainWindow.webContents.executeJavaScript('JSON.parse(JSON.stringify(document.querySelector("a").getBoundingClientRect()))');
+ const x = rect.x + rect.width / 2;
+ const y = rect.y + rect.height / 2;
+
+ function click (x, y, options) {
+ x = Math.floor(x);
+ y = Math.floor(y);
+ mainWindow.webContents.sendInputEvent({
+ type: 'mouseDown',
+ button: 'left',
+ x,
+ y,
+ clickCount: 1,
+ ...options
+ });
+
+ mainWindow.webContents.sendInputEvent({
+ type: 'mouseUp',
+ button: 'left',
+ x,
+ y,
+ clickCount: 1,
+ ...options
+ });
+ }
+
+ click(x, y, { modifiers: ['shift'] });
+}
+
+app.whenReady().then(() => {
+ app.on('web-contents-created', (e, wc) => {
+ wc.on('render-process-gone', (e, details) => {
+ console.error(details);
+ process.exit(1);
+ });
+
+ wc.on('did-finish-load', () => {
+ const title = wc.getTitle();
+ if (title === 'Window From Link') {
+ process.exit(0);
+ }
+ });
+ });
+
+ createWindow();
+});
diff --git a/spec-main/fixtures/apps/open-new-window-from-link/new-window-page.html b/spec-main/fixtures/apps/open-new-window-from-link/new-window-page.html
new file mode 100644
index 0000000000000..ac919774f3b27
--- /dev/null
+++ b/spec-main/fixtures/apps/open-new-window-from-link/new-window-page.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Window From Link
+
+
+ I'm a window opened from a link!
+
+
diff --git a/spec-main/fixtures/apps/open-new-window-from-link/package.json b/spec-main/fixtures/apps/open-new-window-from-link/package.json
new file mode 100644
index 0000000000000..ff9319a62ae99
--- /dev/null
+++ b/spec-main/fixtures/apps/open-new-window-from-link/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "electron-test-open-new-window-from-link",
+ "main": "main.js"
+}
diff --git a/spec-main/fixtures/apps/open-new-window-from-link/preload.js b/spec-main/fixtures/apps/open-new-window-from-link/preload.js
new file mode 100644
index 0000000000000..edb91c4291072
--- /dev/null
+++ b/spec-main/fixtures/apps/open-new-window-from-link/preload.js
@@ -0,0 +1,3 @@
+window.addEventListener('click', e => {
+ console.log('click', e);
+});