diff --git a/package.json b/package.json index 4ea265a4a8..7fe6be6cba 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "playwright": { "chromium_revision": "724623", "firefox_revision": "1011", - "webkit_revision": "1084" + "webkit_revision": "1087" }, "scripts": { "unit": "node test/test.js", diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 67526195b3..7e76d56af4 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -188,6 +188,7 @@ export class FFPage implements PageDelegate { } async navigateFrame(frame: frames.Frame, url: string, referer: string | undefined): Promise { + this._page._validateNavigationReferrer(referer); const response = await this._session.send('Page.navigate', { url, referer, frameId: frame._id }); return { newDocumentId: response.navigationId || undefined, isSameDocument: !response.navigationId }; } diff --git a/src/frames.ts b/src/frames.ts index ae10b8ddc9..df5b236f1a 100644 --- a/src/frames.ts +++ b/src/frames.ts @@ -219,6 +219,11 @@ export class FrameManager { this._page.emit(Events.Page.RequestFailed, request); } + provisionalLoadFailed(documentId: string, error: string) { + for (const watcher of this._lifecycleWatchers) + watcher._onProvisionalLoadFailed(documentId, error); + } + private _removeFramesRecursively(frame: Frame) { for (const child of frame.childFrames()) this._removeFramesRecursively(child); @@ -973,6 +978,10 @@ class LifecycleWatcher { } } + _onProvisionalLoadFailed(documentId: string, error: string) { + this._onAbortedNewDocumentNavigation(this._frame, documentId, error); + } + _onLifecycleEvent(frame: Frame) { this._checkLifecycleComplete(); } diff --git a/src/page.ts b/src/page.ts index 47bf3304e0..43534267cf 100644 --- a/src/page.ts +++ b/src/page.ts @@ -171,6 +171,18 @@ export class Page extends platform.EventEmitter { this.emit(Events.Page.FileChooser, fileChooser); } + _validateNavigationReferrer(referrer: string | undefined) { + if (!referrer) + return; + if (!this._state.extraHTTPHeaders) + return; + const header = this._state.extraHTTPHeaders['referer']; + if (!header) + return; + if (header !== referrer) + throw new Error('"referer" is already specified as extra HTTP header'); + } + browserContext(): BrowserContext { return this._browserContext; } diff --git a/src/webkit/wkBrowser.ts b/src/webkit/wkBrowser.ts index a48110dc1e..97d3c5bc5e 100644 --- a/src/webkit/wkBrowser.ts +++ b/src/webkit/wkBrowser.ts @@ -62,6 +62,7 @@ export class WKBrowser extends platform.EventEmitter implements Browser { this._eventListeners = [ helper.addEventListener(this._browserSession, 'Browser.pageProxyCreated', this._onPageProxyCreated.bind(this)), helper.addEventListener(this._browserSession, 'Browser.pageProxyDestroyed', this._onPageProxyDestroyed.bind(this)), + helper.addEventListener(this._browserSession, 'Browser.provisionalLoadFailed', event => this._onProvisionalLoadFailed(event)), helper.addEventListener(this._browserSession, kPageProxyMessageReceived, this._onPageProxyMessageReceived.bind(this)), ]; @@ -142,6 +143,11 @@ export class WKBrowser extends platform.EventEmitter implements Browser { pageProxy.dispatchMessageToSession(event.message); } + _onProvisionalLoadFailed(event: Protocol.Browser.provisionalLoadFailedPayload) { + const pageProxy = this._pageProxies.get(event.pageProxyId)!; + pageProxy.handleProvisionalLoadFailed(event); + } + disconnect() { throw new Error('Unsupported operation'); } diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index c6d374f229..185b04f29e 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -223,8 +223,12 @@ export class WKPage implements PageDelegate { } async navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise { - await this._session.send('Page.navigate', { url, frameId: frame._id, referrer }); - return {}; // We cannot get loaderId of cross-process navigation in advance. + this._page._validateNavigationReferrer(referrer); + if (this._pageProxySession.isDisposed()) + throw new Error('Target closed'); + const pageProxyId = this._pageProxySession.sessionId; + const result = await this._pageProxySession.connection!.browserSession.send('Browser.navigate', { url, pageProxyId, frameId: frame._id, referrer }); + return { newDocumentId: result.loaderId, isSameDocument: !result.loaderId }; } needsLifecycleResetOnSetContent(): boolean { diff --git a/src/webkit/wkPageProxy.ts b/src/webkit/wkPageProxy.ts index 2e2fb585a1..3641a09986 100644 --- a/src/webkit/wkPageProxy.ts +++ b/src/webkit/wkPageProxy.ts @@ -64,6 +64,12 @@ export class WKPageProxy { this._pageProxySession.dispatchMessage(message); } + handleProvisionalLoadFailed(event: Protocol.Browser.provisionalLoadFailedPayload) { + if (!this._wkPage) + return; + this._wkPage._page._frameManager.provisionalLoadFailed(event.loaderId, event.error); + } + async page(): Promise { if (!this._pagePromise) this._pagePromise = this._initializeWKPage(); diff --git a/test/navigation.spec.js b/test/navigation.spec.js index 6010bacfaf..46b717e7b2 100644 --- a/test/navigation.spec.js +++ b/test/navigation.spec.js @@ -158,7 +158,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI await page.goto(httpsServer.PREFIX + '/redirect/1.html').catch(e => error = e); expectSSLError(error.message); }); - it.skip(WEBKIT)('should not crash when navigating to bad SSL after a cross origin navigation', async({page, server, httpsServer}) => { + it('should not crash when navigating to bad SSL after a cross origin navigation', async({page, server, httpsServer}) => { await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); await page.goto(httpsServer.EMPTY_PAGE).catch(e => void 0); }); @@ -322,19 +322,26 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI expect(request2.headers['referer']).toBe(server.PREFIX + '/grid.html'); expect(page.url()).toBe(server.PREFIX + '/grid.html'); }); - it.skip(FFOX)('should use referer option when setExtraHTTPHeaders provides referer', async({page, server}) => { + it('should use referer option when setExtraHTTPHeaders provides referer', async({page, server}) => { await page.setExtraHTTPHeaders({ 'referer': 'http://microsoft.com/' }); - const [request1, request2] = await Promise.all([ - server.waitForRequest('/grid.html'), - server.waitForRequest('/digits/1.png'), - page.goto(server.PREFIX + '/grid.html', { - referer: 'http://google.com/', - }), - ]); - expect(request1.headers['referer']).toBe('http://google.com/'); - // Make sure subresources use referer specified by setExtraHTTPHeaders. - expect(request2.headers['referer']).toBe('http://microsoft.com/'); - expect(page.url()).toBe(server.PREFIX + '/grid.html'); + try { + const [request1, request2] = await Promise.all([ + server.waitForRequest('/grid.html'), + server.waitForRequest('/digits/1.png'), + page.goto(server.PREFIX + '/grid.html', { + referer: 'http://google.com/', + }), + ]); + expect(request1.headers['referer']).toBe('http://google.com/'); + // Make sure subresources use referer specified by setExtraHTTPHeaders. + expect(request2.headers['referer']).toBe('http://microsoft.com/'); + expect(page.url()).toBe(server.PREFIX + '/grid.html'); + } catch (error) { + if (FFOX || WEBKIT) + expect(error.message).toBe('"referer" is already specified as extra HTTP header'); + else + throw error; + } }); it('should override referrer-policy', async({page, server}) => { server.setRoute('/grid.html', (req, res) => { diff --git a/test/page.spec.js b/test/page.spec.js index 6f4ddd18b7..11a30bb676 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -781,6 +781,9 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF describe('Page.setCacheEnabled', function() { it('should enable or disable the cache based on the state passed', async({page, server}) => { await page.goto(server.PREFIX + '/cached/one-style.html'); + // WebKit does r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData); + // when navigating to the same url, load empty.html to avoid that. + await page.goto(server.EMPTY_PAGE); const [cachedRequest] = await Promise.all([ server.waitForRequest('/cached/one-style.html'), page.goto(server.PREFIX + '/cached/one-style.html'),