Skip to content

Commit 97aacf3

Browse files
cherry-pick(release-1.11): wait for existing pages when connecting (#6619)
This cherry-picks two PRs: - PR #6502 SHA 2ea465b - PR #6511 SHA 3bded35 Co-authored-by: Joel Einbinder <[email protected]>
1 parent f496c65 commit 97aacf3

File tree

5 files changed

+51
-10
lines changed

5 files changed

+51
-10
lines changed

src/client/electron.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,18 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
6767
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.ElectronApplicationInitializer) {
6868
super(parent, type, guid, initializer);
6969
this._context = BrowserContext.from(initializer.context);
70-
this._context.on(Events.BrowserContext.Page, page => {
71-
this._windows.add(page);
72-
this.emit(Events.ElectronApplication.Window, page);
73-
page.once(Events.Page.Close, () => this._windows.delete(page));
74-
});
70+
for (const page of this._context._pages)
71+
this._onPage(page);
72+
this._context.on(Events.BrowserContext.Page, page => this._onPage(page));
7573
this._channel.on('close', () => this.emit(Events.ElectronApplication.Close));
7674
}
7775

76+
_onPage(page: Page) {
77+
this._windows.add(page);
78+
this.emit(Events.ElectronApplication.Window, page);
79+
page.once(Events.Page.Close, () => this._windows.delete(page));
80+
}
81+
7882
windows(): Page[] {
7983
// TODO: add ElectronPage class inherting from Page.
8084
return [...this._windows];

src/server/chromium/crBrowser.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,16 @@ export class CRBrowser extends Browser {
6161
return browser;
6262
}
6363
browser._defaultContext = new CRBrowserContext(browser, undefined, options.persistent);
64-
6564
await Promise.all([
66-
session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }),
65+
session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }).then(async () => {
66+
// Target.setAutoAttach has a bug where it does not wait for new Targets being attached.
67+
// However making a dummy call afterwards fixes this.
68+
// This can be removed after https://chromium-review.googlesource.com/c/chromium/src/+/2885888 lands in stable.
69+
await session.send('Target.getTargetInfo');
70+
}),
6771
(browser._defaultContext as CRBrowserContext)._initialize(),
6872
]);
69-
73+
await browser._waitForAllPagesToBeInitialized();
7074
return browser;
7175
}
7276

@@ -104,6 +108,10 @@ export class CRBrowser extends Browser {
104108
return this.options.name === 'clank';
105109
}
106110

111+
async _waitForAllPagesToBeInitialized() {
112+
await Promise.all([...this._crPages.values()].map(page => page.pageOrError()));
113+
}
114+
107115
_onAttachedToTarget({targetInfo, sessionId, waitingForDebugger}: Protocol.Target.attachedToTargetPayload) {
108116
if (targetInfo.type === 'browser')
109117
return;

src/server/electron/electron.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export class ElectronApplication extends SdkObject {
6363
// Emit application closed after context closed.
6464
Promise.resolve().then(() => this.emit(ElectronApplication.Events.Close));
6565
});
66+
for (const page of this._browserContext.pages())
67+
this._onPage(page);
6668
this._browserContext.on(BrowserContext.Events.Page, event => this._onPage(event));
6769
this._nodeConnection = nodeConnection;
6870
this._nodeSession = nodeConnection.rootSession;
@@ -77,7 +79,7 @@ export class ElectronApplication extends SdkObject {
7779
this._nodeSession.send('Runtime.enable', {}).catch(e => {});
7880
}
7981

80-
private async _onPage(page: Page) {
82+
private _onPage(page: Page) {
8183
// Needs to be sync.
8284
const windowId = ++this._lastWindowId;
8385
(page as any)._browserWindowId = windowId;

tests/chromium/chromium.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,30 @@ playwrightTest.describe('chromium', () => {
246246
}
247247
});
248248
});
249+
250+
playwrightTest('should report all pages in an existing browser', async ({ browserType, browserOptions }, testInfo) => {
251+
const port = 9339 + testInfo.workerIndex;
252+
const browserServer = await browserType.launch({
253+
...browserOptions,
254+
args: ['--remote-debugging-port=' + port]
255+
});
256+
try {
257+
const cdpBrowser = await browserType.connectOverCDP({
258+
endpointURL: `http://localhost:${port}/`,
259+
});
260+
const contexts = cdpBrowser.contexts();
261+
expect(contexts.length).toBe(1);
262+
for (let i = 0; i < 3; i++)
263+
await contexts[0].newPage();
264+
await cdpBrowser.close();
265+
266+
const cdpBrowser2 = await browserType.connectOverCDP({
267+
endpointURL: `http://localhost:${port}/`,
268+
});
269+
expect(cdpBrowser2.contexts()[0].pages().length).toBe(3);
270+
271+
await cdpBrowser2.close();
272+
} finally {
273+
await browserServer.close();
274+
}
275+
});

tests/electron/electron-app.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ test('should return browser window', async ({ playwright }) => {
101101
const electronApp = await playwright._electron.launch({
102102
args: [path.join(__dirname, '..', 'config', 'electron-window-app.js')],
103103
});
104-
const page = await electronApp.waitForEvent('window');
104+
const page = await electronApp.firstWindow();
105105
const bwHandle = await electronApp.browserWindow(page);
106106
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
107107
await electronApp.close();

0 commit comments

Comments
 (0)