From d250f74e4e78ba168ebee66bcd82b51bfe4fb60f Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 13 Feb 2020 15:14:17 -0800 Subject: [PATCH] fix(firefox): partially implement setOfflineMode using interception --- src/firefox/ffNetworkManager.ts | 25 ++++++++++++++++++++++--- src/firefox/ffPage.ts | 2 +- test/interception.spec.js | 4 ++-- test/test.js | 2 +- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/firefox/ffNetworkManager.ts b/src/firefox/ffNetworkManager.ts index c513622c29..f9a0467268 100644 --- a/src/firefox/ffNetworkManager.ts +++ b/src/firefox/ffNetworkManager.ts @@ -28,6 +28,8 @@ export class FFNetworkManager { private _requests: Map; private _page: Page; private _eventListeners: RegisteredListener[]; + private _userInterceptionEnabled = false; + private _offlineModeEnabled = false; constructor(session: FFSession, page: Page) { this._session = session; @@ -48,6 +50,17 @@ export class FFNetworkManager { } async setRequestInterception(enabled: boolean) { + this._userInterceptionEnabled = enabled; + await this._updateProtocolInterception(); + } + + async setOfflineMode(enabled: boolean) { + this._offlineModeEnabled = enabled; + await this._updateProtocolInterception(); + } + + async _updateProtocolInterception() { + const enabled = this._userInterceptionEnabled || this._offlineModeEnabled; await this._session.send('Network.setRequestInterception', {enabled}); } @@ -62,9 +75,15 @@ export class FFNetworkManager { redirectChain.push(redirected.request); this._requests.delete(redirected._id); } - const request = new InterceptableRequest(this._session, frame, redirectChain, event); + const request = new InterceptableRequest(this._session, frame, redirectChain, event, event.isIntercepted && this._userInterceptionEnabled); this._requests.set(request._id, request); this._page._frameManager.requestStarted(request.request); + if (event.isIntercepted && !this._userInterceptionEnabled) { + if (this._offlineModeEnabled) + request.abort('internetdisconnected'); + else + request.continue({}); + } } _onResponseReceived(event: Protocol.Network.responseReceivedPayload) { @@ -146,7 +165,7 @@ class InterceptableRequest implements network.RequestDelegate { _id: string; private _session: FFSession; - constructor(session: FFSession, frame: frames.Frame, redirectChain: network.Request[], payload: Protocol.Network.requestWillBeSentPayload) { + constructor(session: FFSession, frame: frames.Frame, redirectChain: network.Request[], payload: Protocol.Network.requestWillBeSentPayload, isIntercepted: boolean) { this._id = payload.requestId; this._session = session; @@ -154,7 +173,7 @@ class InterceptableRequest implements network.RequestDelegate { for (const {name, value} of payload.headers) headers[name.toLowerCase()] = value; - this.request = new network.Request(payload.isIntercepted ? this : null, frame, redirectChain, payload.navigationId, + this.request = new network.Request(isIntercepted ? this : null, frame, redirectChain, payload.navigationId, payload.url, causeToResourceType[payload.cause] || 'other', payload.method, payload.postData, headers); } diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 9dfae6114e..7588ed22de 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -284,7 +284,7 @@ export class FFPage implements PageDelegate { } async setOfflineMode(enabled: boolean): Promise { - throw new Error('Offline mode not implemented in Firefox'); + await this._networkManager.setOfflineMode(enabled); } async authenticate(credentials: types.Credentials | null): Promise { diff --git a/test/interception.spec.js b/test/interception.spec.js index ed8ce6a872..c98a5cfa20 100644 --- a/test/interception.spec.js +++ b/test/interception.spec.js @@ -521,7 +521,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); }); - describe.skip(FFOX)('Interception.setOfflineMode', function() { + describe('Interception.setOfflineMode', function() { it('should work', async({page, server}) => { await page.setOfflineMode(true); let error = null; @@ -531,7 +531,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const response = await page.goto(server.EMPTY_PAGE); expect(response.status()).toBe(200); }); - it('should emulate navigator.onLine', async({page, server}) => { + it.skip(FFOX)('should emulate navigator.onLine', async({page, server}) => { expect(await page.evaluate(() => window.navigator.onLine)).toBe(true); await page.setOfflineMode(true); expect(await page.evaluate(() => window.navigator.onLine)).toBe(false); diff --git a/test/test.js b/test/test.js index 688735ed08..f4cbc43b9b 100644 --- a/test/test.js +++ b/test/test.js @@ -87,7 +87,7 @@ if (process.env.BROWSER === 'firefox') { ...require('../lib/events').Events, ...require('../lib/chromium/events').Events, }; - missingCoverage = ['browserContext.setGeolocation', 'elementHandle.scrollIntoViewIfNeeded', 'page.setOfflineMode']; + missingCoverage = ['browserContext.setGeolocation', 'elementHandle.scrollIntoViewIfNeeded']; } else if (process.env.BROWSER === 'webkit') { product = 'WebKit'; events = require('../lib/events').Events;