Browse Source

fix: call loadUrl when opening new windows from links (#34159)

* fix: call loadUrl when opening new windows from links

* spec: add regression test
Shelley Vohr 2 years ago
parent
commit
dd6ce91f57

+ 22 - 0
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';
 

+ 20 - 0
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);
 

+ 11 - 0
spec-main/fixtures/apps/open-new-window-from-link/index.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
+    <title>Hello World!</title>
+  </head>
+  <body>
+    <a href="./new-window-page.html">Open New Window</a>
+  </body>
+</html>

+ 64 - 0
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();
+});

+ 11 - 0
spec-main/fixtures/apps/open-new-window-from-link/new-window-page.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
+    <title>Window From Link</title>
+  </head>
+  <body>
+    I'm a window opened from a link!
+  </body>
+</html>

+ 4 - 0
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"
+}

+ 3 - 0
spec-main/fixtures/apps/open-new-window-from-link/preload.js

@@ -0,0 +1,3 @@
+window.addEventListener('click', e => {
+  console.log('click', e);
+});