diff --git a/browsers.json b/browsers.json index 7e14f0cdae..a2c506ce6f 100644 --- a/browsers.json +++ b/browsers.json @@ -6,7 +6,7 @@ }, { "name": "firefox", - "revision": "1087" + "revision": "1088" }, { "name": "webkit", diff --git a/packages/playwright-firefox/browsers.json b/packages/playwright-firefox/browsers.json index 82f63bcb58..5adb43a9f6 100644 --- a/packages/playwright-firefox/browsers.json +++ b/packages/playwright-firefox/browsers.json @@ -2,7 +2,7 @@ "browsers": [ { "name": "firefox", - "revision": "1087" + "revision": "1088" } ] } diff --git a/packages/playwright/browsers.json b/packages/playwright/browsers.json index 7e14f0cdae..a2c506ce6f 100644 --- a/packages/playwright/browsers.json +++ b/packages/playwright/browsers.json @@ -6,7 +6,7 @@ }, { "name": "firefox", - "revision": "1087" + "revision": "1088" }, { "name": "webkit", diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index c78c62deeb..47de9e6ebe 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -49,7 +49,7 @@ export class CRPage implements PageDelegate { readonly rawMouse: RawMouseImpl; readonly rawKeyboard: RawKeyboardImpl; readonly _targetId: string; - private readonly _opener: CRPage | null; + readonly _opener: CRPage | null; private readonly _pdf: CRPDF; private readonly _coverage: CRCoverage; readonly _browserContext: CRBrowserContext; @@ -654,7 +654,18 @@ class FrameSession { } _onDownloadWillBegin(payload: Protocol.Page.downloadWillBeginPayload) { - this._crPage._browserContext._browser._downloadCreated(this._page, payload.guid, payload.url); + let originPage = this._crPage._initializedPage; + // If it's a new window download, report it on the opener page. + if (!originPage) { + // Resume the page creation with an error. The page will automatically close right + // after the download begins. + this._firstNonInitialNavigationCommittedReject(new Error('Starting new page download')); + if (this._crPage._opener) + originPage = this._crPage._opener._initializedPage; + } + if (!originPage) + return; + this._crPage._browserContext._browser._downloadCreated(originPage, payload.guid, payload.url); } _onDownloadProgress(payload: Protocol.Page.downloadProgressPayload) { diff --git a/src/firefox/ffBrowser.ts b/src/firefox/ffBrowser.ts index 3f06f3e12c..5f50b3522e 100644 --- a/src/firefox/ffBrowser.ts +++ b/src/firefox/ffBrowser.ts @@ -153,7 +153,18 @@ export class FFBrowser extends BrowserBase { assert(ffPage); if (!ffPage) return; - this._downloadCreated(ffPage._page, payload.uuid, payload.url); + let originPage = ffPage._initializedPage; + // If it's a new window download, report it on the opener page. + if (!originPage) { + // Resume the page creation with an error. The page will automatically close right + // after the download begins. + ffPage._pageCallback(new Error('Starting new page download')); + if (ffPage._opener) + originPage = ffPage._opener._initializedPage; + } + if (!originPage) + return; + this._downloadCreated(originPage, payload.uuid, payload.url); } _onDownloadFinished(payload: Protocol.Browser.downloadFinishedPayload) { diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index e9e0655cd6..4416d40707 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -45,9 +45,9 @@ export class FFPage implements PageDelegate { readonly _networkManager: FFNetworkManager; readonly _browserContext: FFBrowserContext; private _pagePromise: Promise; - private _pageCallback: (pageOrError: Page | Error) => void = () => {}; + _pageCallback: (pageOrError: Page | Error) => void = () => {}; _initializedPage: Page | null = null; - private readonly _opener: FFPage | null; + readonly _opener: FFPage | null; private readonly _contextIdToContext: Map; private _eventListeners: RegisteredListener[]; private _workers = new Map(); diff --git a/src/webkit/wkBrowser.ts b/src/webkit/wkBrowser.ts index 1f8d68c577..6cc34c9e0f 100644 --- a/src/webkit/wkBrowser.ts +++ b/src/webkit/wkBrowser.ts @@ -107,7 +107,18 @@ export class WKBrowser extends BrowserBase { // here by simulating cancelled provisional load which matches downloads from network. frameManager.provisionalLoadFailed(frame, '', 'Download is starting'); } - this._downloadCreated(page._page, payload.uuid, payload.url); + let originPage = page._initializedPage; + // If it's a new window download, report it on the opener page. + if (!originPage) { + // Resume the page creation with an error. The page will automatically close right + // after the download begins. + page._firstNonInitialNavigationCommittedReject(new Error('Starting new page download')); + if (page._opener) + originPage = page._opener._initializedPage; + } + if (!originPage) + return; + this._downloadCreated(originPage, payload.uuid, payload.url); } _onDownloadFinished(payload: Protocol.Playwright.downloadFinishedPayload) { diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index e8087a4cfd..fbd452fa2e 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -53,7 +53,7 @@ export class WKPage implements PageDelegate { private readonly _pagePromise: Promise; private _pagePromiseCallback: (page: Page | Error) => void = () => {}; private readonly _pageProxySession: WKSession; - private readonly _opener: WKPage | null; + readonly _opener: WKPage | null; private readonly _requestIdToRequest = new Map(); private readonly _workers: WKWorkers; private readonly _contextIdToContext: Map; @@ -65,7 +65,7 @@ export class WKPage implements PageDelegate { _initializedPage: Page | null = null; private _firstNonInitialNavigationCommittedPromise: Promise; private _firstNonInitialNavigationCommittedFulfill = () => {}; - private _firstNonInitialNavigationCommittedReject = (e: Error) => {}; + _firstNonInitialNavigationCommittedReject = (e: Error) => {}; private _lastConsoleMessage: { derivedType: string, text: string, handles: JSHandle[]; count: number, location: ConsoleMessageLocation; } | null = null; constructor(browserContext: WKBrowserContext, pageProxySession: WKSession, opener: WKPage | null) { diff --git a/test/download.spec.js b/test/download.spec.js index 9d14f3f219..bac21e72a3 100644 --- a/test/download.spec.js +++ b/test/download.spec.js @@ -117,7 +117,10 @@ describe('Download', function() { expect(fs.readFileSync(path).toString()).toBe('Hello world'); await page.close(); }); - it.fail(CHROMIUM || WEBKIT || FFOX)('should report new window downloads', async({browser, server}) => { + it('should report new window downloads', async({browser, server}) => { + // TODO: - the test fails in headful Chromium as the popup page gets closed along + // with the session before download completed event arrives. + // - WebKit doesn't close the popup page const page = await browser.newPage({ acceptDownloads: true }); await page.setContent(`download`); const [ download ] = await Promise.all([