Repository: electron/electron
Pull request: fix: `createWindow` shouldn't load URL for `webContents`

#### Description of Change

Closes https://github.com/electron/electron/issues/43740.

Passing `createWindow` to `webContents.setWindowOpenHandler` shouldn't call `webContents.loadURL` on the existing webContents - this brings the logic into parity with what happens when `createWindow` is not passed: https://github.com/electron/electron/blob/7a9cbcac9fead05f3523b1178147a57bf8726b02/lib/browser/guest-window-manager.ts#L85-L96

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Fixed a potential issue accessing a child window document when overriding browserWindow creation via `setWindowOpenHandler`.

Changed files:
filename: lib/browser/guest-window-manager.ts
patch: @@ -71,14 +71,6 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
         throw new Error('Invalid webContents. Created window should be connected to webContents passed with options object.');
       }
 
-      webContents.loadURL(url, {
-        httpReferrer: referrer,
-        ...(postData && {
-          postData,
-          extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
-        })
-      });
-
       handleWindowLifecycleEvents({ embedder, frameName, guest, outlivesOpener });
     }
 

filename: spec/guest-window-manager-spec.ts
patch: @@ -231,6 +231,10 @@ describe('webContents.setWindowOpenHandler', () => {
             response.statusCode = 200;
             response.end('<title>Child page</title>');
             break;
+          case '/test':
+            response.statusCode = 200;
+            response.end('<title>Test page</title>');
+            break;
           default:
             throw new Error(`Unsupported endpoint: ${request.url}`);
         }
@@ -303,6 +307,32 @@ describe('webContents.setWindowOpenHandler', () => {
       expect(childWindow.title).to.equal(browserWindowTitle);
     });
 
+    it('should be able to access the child window document when createWindow is provided', async () => {
+      browserWindow.webContents.setWindowOpenHandler(() => {
+        return {
+          action: 'allow',
+          createWindow: (options) => {
+            const child = new BrowserWindow(options);
+            return child.webContents;
+          }
+        };
+      });
+
+      const aboutBlankTitle = await browserWindow.webContents.executeJavaScript(`
+        const win1 = window.open('about:blank', '', 'show=no');
+        win1.document.title = 'about-blank-title';
+        win1.document.title;
+      `);
+      expect(aboutBlankTitle).to.equal('about-blank-title');
+
+      const serverPageTitle = await browserWindow.webContents.executeJavaScript(`
+        const win2 = window.open('${url}/child', '', 'show=no');
+        win2.document.title = 'server-page-title';
+        win2.document.title;
+      `);
+      expect(serverPageTitle).to.equal('server-page-title');
+    });
+
     it('spawns browser window with overridden options', async () => {
       const childWindow = await new Promise<Electron.BrowserWindow>(resolve => {
         browserWindow.webContents.setWindowOpenHandler(() => {