From c5393256151d516616065706211366d5665a93cd Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 20 Mar 2020 19:17:46 -0700 Subject: [PATCH] feat(geo): implement geo override in ff (#1438) --- package.json | 2 +- src/chromium/crBrowser.ts | 2 -- src/firefox/ffBrowser.ts | 10 ++++++---- src/firefox/ffPage.ts | 6 ++++++ test/geolocation.spec.js | 27 ++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 22d6bcd97c..81ad8b1e2c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "main": "index.js", "playwright": { "chromium_revision": "751710", - "firefox_revision": "1043", + "firefox_revision": "1044", "webkit_revision": "1180" }, "scripts": { diff --git a/src/chromium/crBrowser.ts b/src/chromium/crBrowser.ts index 041fa6a777..f235aba915 100644 --- a/src/chromium/crBrowser.ts +++ b/src/chromium/crBrowser.ts @@ -268,8 +268,6 @@ export class CRBrowserContext extends BrowserContextBase { async _initialize() { if (this._options.permissions) await this.grantPermissions(this._options.permissions); - if (this._options.geolocation) - await this.setGeolocation(this._options.geolocation); if (this._options.offline) await this.setOffline(this._options.offline); if (this._options.httpCredentials) diff --git a/src/firefox/ffBrowser.ts b/src/firefox/ffBrowser.ts index 680acbb47d..c6e5ea7fb7 100644 --- a/src/firefox/ffBrowser.ts +++ b/src/firefox/ffBrowser.ts @@ -16,7 +16,7 @@ */ import { Browser, createPageInNewContext } from '../browser'; -import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions } from '../browserContext'; +import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext'; import { Events } from '../events'; import { assert, helper, RegisteredListener } from '../helper'; import * as network from '../network'; @@ -170,8 +170,6 @@ export class FFBrowserContext extends BrowserContextBase { async _initialize() { if (this._options.permissions) await this.grantPermissions(this._options.permissions); - if (this._options.geolocation) - await this.setGeolocation(this._options.geolocation); if (this._options.extraHTTPHeaders) await this.setExtraHTTPHeaders(this._options.extraHTTPHeaders); if (this._options.offline) @@ -250,7 +248,11 @@ export class FFBrowserContext extends BrowserContextBase { } async setGeolocation(geolocation: types.Geolocation | null): Promise { - throw new Error('Geolocation emulation is not supported in Firefox'); + if (geolocation) + geolocation = verifyGeolocation(geolocation); + this._options.geolocation = geolocation || undefined; + for (const page of this.pages()) + await (page._delegate as FFPage)._setGeolocation(geolocation); } async setExtraHTTPHeaders(headers: network.Headers): Promise { diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index f3eaca5ed6..724b351cea 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -86,6 +86,7 @@ export class FFPage implements PageDelegate { } async _initialize() { + const geolocation = this._browserContext._options.geolocation; try { await Promise.all([ // TODO: we should get rid of this call to resolve before any early events arrive, e.g. dialogs. @@ -93,6 +94,7 @@ export class FFPage implements PageDelegate { script: '', worldName: UTILITY_WORLD_NAME, }), + geolocation ? this._setGeolocation(geolocation) : Promise.resolve(), new Promise(f => this._session.once('Page.ready', f)), ]); this._pageCallback(this._page); @@ -481,6 +483,10 @@ export class FFPage implements PageDelegate { throw new Error('Frame has been detached.'); return result.handle; } + + async _setGeolocation(geolocation: types.Geolocation | null) { + await this._session.send('Page.setGeolocationOverride', geolocation || {}); + } } function toRemoteObject(handle: dom.ElementHandle): Protocol.Runtime.RemoteObject { diff --git a/test/geolocation.spec.js b/test/geolocation.spec.js index 435cb2e443..45ff04746f 100644 --- a/test/geolocation.spec.js +++ b/test/geolocation.spec.js @@ -23,7 +23,7 @@ module.exports.describe = function ({ testRunner, expect, FFOX, WEBKIT }) { const {it, fit, xit, dit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe.fail(FFOX)('Overrides.setGeolocation', function() { + describe('Overrides.setGeolocation', function() { it('should work', async({page, server, context}) => { await context.grantPermissions(['geolocation']); await page.goto(server.EMPTY_PAGE); @@ -87,5 +87,30 @@ module.exports.describe = function ({ testRunner, expect, FFOX, WEBKIT }) { }); await context.close(); }); + it('watchPosition should be notified', async({page, server, context}) => { + await context.grantPermissions(['geolocation']); + await page.goto(server.EMPTY_PAGE); + const messages = []; + page.on('console', message => messages.push(message.text())); + + await context.setGeolocation({latitude: 0, longitude: 0}); + await page.evaluate(() => { + navigator.geolocation.watchPosition(pos => { + const coords = pos.coords; + console.log(`lat=${coords.latitude} lng=${coords.longitude}`); + }, err => {}); + }); + await context.setGeolocation({latitude: 0, longitude: 10}); + await page.waitForEvent('console', message => message.text().includes('lat=0 lng=10')); + await context.setGeolocation({latitude: 20, longitude: 30}); + await page.waitForEvent('console', message => message.text().includes('lat=20 lng=30')); + await context.setGeolocation({latitude: 40, longitude: 50}); + await page.waitForEvent('console', message => message.text().includes('lat=40 lng=50')); + + const allMessages = messages.join('|'); + expect(allMessages).toContain('lat=0 lng=10'); + expect(allMessages).toContain('lat=20 lng=30'); + expect(allMessages).toContain('lat=40 lng=50'); + }); }); };