Skip to content

Commit

Permalink
fix(permissions): manage permissions on the proxy level in webkit (#1451
Browse files Browse the repository at this point in the history
)
  • Loading branch information
pavelfeldman authored Mar 21, 2020
1 parent 96c9c81 commit 5a42cbd
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"playwright": {
"chromium_revision": "751710",
"firefox_revision": "1045",
"webkit_revision": "1180"
"webkit_revision": "1182"
},
"scripts": {
"ctest": "cross-env BROWSER=chromium node test/test.js",
Expand Down
2 changes: 1 addition & 1 deletion src/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export abstract class BrowserContextBase extends platform.EventEmitter implement
_closed = false;
private readonly _closePromise: Promise<Error>;
private _closePromiseFulfill: ((error: Error) => void) | undefined;
private _permissions = new Map<string, string[]>();
readonly _permissions = new Map<string, string[]>();

constructor(options: BrowserContextOptions) {
super();
Expand Down
13 changes: 2 additions & 11 deletions src/webkit/wkBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,20 +263,11 @@ export class WKBrowserContext extends BrowserContextBase {
}

async _doGrantPermissions(origin: string, permissions: string[]) {
const webPermissionToProtocol = new Map<string, string>([
['geolocation', 'geolocation'],
]);
const filtered = permissions.map(permission => {
const protocolPermission = webPermissionToProtocol.get(permission);
if (!protocolPermission)
throw new Error('Unknown permission: ' + permission);
return protocolPermission;
});
await this._browser._browserSession.send('Playwright.grantPermissions', { origin, browserContextId: this._browserContextId, permissions: filtered });
await Promise.all(this.pages().map(page => (page._delegate as WKPage)._grantPermissions(origin, permissions)));
}

async _doClearPermissions() {
await this._browser._browserSession.send('Playwright.resetPermissions', { browserContextId: this._browserContextId });
await Promise.all(this.pages().map(page => (page._delegate as WKPage)._clearPermissions()));
}

async setGeolocation(geolocation: types.Geolocation | null): Promise<void> {
Expand Down
21 changes: 21 additions & 0 deletions src/webkit/wkPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export class WKPage implements PageDelegate {
if (this._page._state.viewportSize || contextOptions.viewport)
promises.push(this._updateViewport());
promises.push(this.updateHttpCredentials());
if (this._browserContext._permissions.size) {
for (const [key, value] of this._browserContext._permissions)
this._grantPermissions(key, value);
}
await Promise.all(promises);
}

Expand Down Expand Up @@ -820,6 +824,23 @@ export class WKPage implements PageDelegate {
request.request._setFailureText(event.errorText);
this._page._frameManager.requestFailed(request.request, event.errorText.includes('cancelled'));
}

async _grantPermissions(origin: string, permissions: string[]) {
const webPermissionToProtocol = new Map<string, string>([
['geolocation', 'geolocation'],
]);
const filtered = permissions.map(permission => {
const protocolPermission = webPermissionToProtocol.get(permission);
if (!protocolPermission)
throw new Error('Unknown permission: ' + permission);
return protocolPermission;
});
await this._pageProxySession.send('Emulation.grantPermissions', { origin, permissions: filtered });
}

async _clearPermissions() {
await this._pageProxySession.send('Emulation.resetPermissions', {});
}
}

function toRemoteObject(handle: dom.ElementHandle): Protocol.Runtime.RemoteObject {
Expand Down
7 changes: 7 additions & 0 deletions test/assets/geolocation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
window.geolocationPromise = new Promise(resolve => {
navigator.geolocation.getCurrentPosition(position => {
resolve({latitude: position.coords.latitude, longitude: position.coords.longitude});
});
});
</script>
10 changes: 10 additions & 0 deletions test/geolocation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,15 @@ module.exports.describe = function ({ testRunner, expect, FFOX, WEBKIT }) {
expect(allMessages).toContain('lat=20 lng=30');
expect(allMessages).toContain('lat=40 lng=50');
});
it.fail(FFOX)('should use context options for popup', async({page, context, server}) => {
await context.grantPermissions(['geolocation']);
await context.setGeolocation({ longitude: 10, latitude: 10 });
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(url => window._popup = window.open(url), server.PREFIX + '/geolocation.html'),
]);
const geolocation = await popup.evaluate(() => window.geolocationPromise);
expect(geolocation).toEqual({ longitude: 10, latitude: 10 });
});
});
};

0 comments on commit 5a42cbd

Please sign in to comment.