chore: move permissions API into features/ (#33)
- drive-by accessibility spec moved to a shared folder
This commit is contained in:
parent
48a78b2c8a
commit
76eb289f54
89
docs/api.md
89
docs/api.md
|
|
@ -53,14 +53,16 @@
|
||||||
* [event: 'targetcreated'](#event-targetcreated-1)
|
* [event: 'targetcreated'](#event-targetcreated-1)
|
||||||
* [event: 'targetdestroyed'](#event-targetdestroyed-1)
|
* [event: 'targetdestroyed'](#event-targetdestroyed-1)
|
||||||
* [browserContext.browser()](#browsercontextbrowser)
|
* [browserContext.browser()](#browsercontextbrowser)
|
||||||
* [browserContext.clearPermissionOverrides()](#browsercontextclearpermissionoverrides)
|
|
||||||
* [browserContext.close()](#browsercontextclose)
|
* [browserContext.close()](#browsercontextclose)
|
||||||
* [browserContext.isIncognito()](#browsercontextisincognito)
|
* [browserContext.isIncognito()](#browsercontextisincognito)
|
||||||
* [browserContext.newPage()](#browsercontextnewpage)
|
* [browserContext.newPage()](#browsercontextnewpage)
|
||||||
* [browserContext.overridePermissions(origin, permissions)](#browsercontextoverridepermissionsorigin-permissions)
|
|
||||||
* [browserContext.pages()](#browsercontextpages)
|
* [browserContext.pages()](#browsercontextpages)
|
||||||
|
* [browserContext.permissions](#browsercontextpermissions)
|
||||||
* [browserContext.targets()](#browsercontexttargets)
|
* [browserContext.targets()](#browsercontexttargets)
|
||||||
* [browserContext.waitForTarget(predicate[, options])](#browsercontextwaitfortargetpredicate-options)
|
* [browserContext.waitForTarget(predicate[, options])](#browsercontextwaitfortargetpredicate-options)
|
||||||
|
- [class: Permissions](#class-permissions)
|
||||||
|
* [permissions.clearOverrides()](#permissionsclearoverrides)
|
||||||
|
* [permissions.override(origin, permissions)](#permissionsoverrideorigin-permissions)
|
||||||
- [class: Page](#class-page)
|
- [class: Page](#class-page)
|
||||||
* [event: 'close'](#event-close)
|
* [event: 'close'](#event-close)
|
||||||
* [event: 'console'](#event-console)
|
* [event: 'console'](#event-console)
|
||||||
|
|
@ -828,18 +830,6 @@ Emitted when a target inside the browser context is destroyed, for example when
|
||||||
|
|
||||||
The browser this browser context belongs to.
|
The browser this browser context belongs to.
|
||||||
|
|
||||||
#### browserContext.clearPermissionOverrides()
|
|
||||||
- returns: <[Promise]>
|
|
||||||
|
|
||||||
Clears all permission overrides for the browser context.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const context = browser.defaultBrowserContext();
|
|
||||||
context.overridePermissions('https://example.com', ['clipboard-read']);
|
|
||||||
// do stuff ..
|
|
||||||
context.clearPermissionOverrides();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### browserContext.close()
|
#### browserContext.close()
|
||||||
- returns: <[Promise]>
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
|
@ -861,8 +851,48 @@ The default browser context is the only non-incognito browser context.
|
||||||
|
|
||||||
Creates a new page in the browser context.
|
Creates a new page in the browser context.
|
||||||
|
|
||||||
|
#### browserContext.pages()
|
||||||
|
- returns: <[Promise]<[Array]<[Page]>>> Promise which resolves to an array of all open pages. Non visible pages, such as `"background_page"`, will not be listed here. You can find them using [target.page()](#targetpage).
|
||||||
|
|
||||||
#### browserContext.overridePermissions(origin, permissions)
|
An array of all pages inside the browser context.
|
||||||
|
|
||||||
|
#### browserContext.permissions
|
||||||
|
- returns: <[Permissions]>
|
||||||
|
|
||||||
|
#### browserContext.targets()
|
||||||
|
- returns: <[Array]<[Target]>>
|
||||||
|
|
||||||
|
An array of all active targets inside the browser context.
|
||||||
|
|
||||||
|
#### browserContext.waitForTarget(predicate[, options])
|
||||||
|
- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target
|
||||||
|
- `options` <[Object]>
|
||||||
|
- `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds.
|
||||||
|
- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function.
|
||||||
|
|
||||||
|
This searches for a target in this specific browser context.
|
||||||
|
|
||||||
|
An example of finding a target for a page opened via `window.open`:
|
||||||
|
```js
|
||||||
|
await page.evaluate(() => window.open('https://www.example.com/'));
|
||||||
|
const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/');
|
||||||
|
```
|
||||||
|
|
||||||
|
### class: Permissions
|
||||||
|
|
||||||
|
#### permissions.clearOverrides()
|
||||||
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
Clears all permission overrides for the browser context.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const context = browser.defaultBrowserContext();
|
||||||
|
context.permissions.override('https://example.com', ['clipboard-read']);
|
||||||
|
// do stuff ..
|
||||||
|
context.permissions.clearOverrides();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### permissions.override(origin, permissions)
|
||||||
- `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com".
|
- `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com".
|
||||||
- `permissions` <[Array]<[string]>> An array of permissions to grant. All permissions that are not listed here will be automatically denied. Permissions can be one of the following values:
|
- `permissions` <[Array]<[string]>> An array of permissions to grant. All permissions that are not listed here will be automatically denied. Permissions can be one of the following values:
|
||||||
- `'geolocation'`
|
- `'geolocation'`
|
||||||
|
|
@ -886,32 +916,7 @@ Creates a new page in the browser context.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const context = browser.defaultBrowserContext();
|
const context = browser.defaultBrowserContext();
|
||||||
await context.overridePermissions('https://html5demos.com', ['geolocation']);
|
await context.permissions.override('https://html5demos.com', ['geolocation']);
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### browserContext.pages()
|
|
||||||
- returns: <[Promise]<[Array]<[Page]>>> Promise which resolves to an array of all open pages. Non visible pages, such as `"background_page"`, will not be listed here. You can find them using [target.page()](#targetpage).
|
|
||||||
|
|
||||||
An array of all pages inside the browser context.
|
|
||||||
|
|
||||||
#### browserContext.targets()
|
|
||||||
- returns: <[Array]<[Target]>>
|
|
||||||
|
|
||||||
An array of all active targets inside the browser context.
|
|
||||||
|
|
||||||
#### browserContext.waitForTarget(predicate[, options])
|
|
||||||
- `predicate` <[function]\([Target]\):[boolean]> A function to be run for every target
|
|
||||||
- `options` <[Object]>
|
|
||||||
- `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds.
|
|
||||||
- returns: <[Promise]<[Target]>> Promise which resolves to the first target found that matches the `predicate` function.
|
|
||||||
|
|
||||||
This searches for a target in this specific browser context.
|
|
||||||
|
|
||||||
An example of finding a target for a page opened via `window.open`:
|
|
||||||
```js
|
|
||||||
await page.evaluate(() => window.open('https://www.example.com/'));
|
|
||||||
const newWindowTarget = await browserContext.waitForTarget(target => target.url() === 'https://www.example.com/');
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### class: Page
|
### class: Page
|
||||||
|
|
@ -1762,7 +1767,7 @@ Sets the page's geolocation.
|
||||||
await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
||||||
```
|
```
|
||||||
|
|
||||||
> **NOTE** Consider using [browserContext.overridePermissions](#browsercontextoverridepermissionsorigin-permissions) to grant permissions for the page to read its geolocation.
|
> **NOTE** Consider using [browserContext.permissions.override](#permissionsoverrideorigin-permissions) to grant permissions for the page to read its geolocation.
|
||||||
|
|
||||||
#### page.setJavaScriptEnabled(enabled)
|
#### page.setJavaScriptEnabled(enabled)
|
||||||
- `enabled` <[boolean]> Whether or not to enable JavaScript on the page.
|
- `enabled` <[boolean]> Whether or not to enable JavaScript on the page.
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ export = {
|
||||||
Mouse: require('./chromium/Input').Mouse,
|
Mouse: require('./chromium/Input').Mouse,
|
||||||
PDF: require('./chromium/features/pdf').PDF,
|
PDF: require('./chromium/features/pdf').PDF,
|
||||||
Page: require('./chromium/Page').Page,
|
Page: require('./chromium/Page').Page,
|
||||||
|
Permissions: require('./chromium/features/permissions').Permissions,
|
||||||
Playwright: require('./chromium/Playwright').Playwright,
|
Playwright: require('./chromium/Playwright').Playwright,
|
||||||
Request: require('./chromium/NetworkManager').Request,
|
Request: require('./chromium/NetworkManager').Request,
|
||||||
Response: require('./chromium/NetworkManager').Response,
|
Response: require('./chromium/NetworkManager').Response,
|
||||||
|
|
@ -45,7 +46,7 @@ export = {
|
||||||
Workers: require('./chromium/features/workers').Workers,
|
Workers: require('./chromium/features/workers').Workers,
|
||||||
},
|
},
|
||||||
Firefox: {
|
Firefox: {
|
||||||
Accessibility: require('./firefox/Accessibility').Accessibility,
|
Accessibility: require('./firefox/features/accessibility').Accessibility,
|
||||||
Browser: require('./firefox/Browser').Browser,
|
Browser: require('./firefox/Browser').Browser,
|
||||||
BrowserContext: require('./firefox/Browser').BrowserContext,
|
BrowserContext: require('./firefox/Browser').BrowserContext,
|
||||||
BrowserFetcher: require('./firefox/BrowserFetcher').BrowserFetcher,
|
BrowserFetcher: require('./firefox/BrowserFetcher').BrowserFetcher,
|
||||||
|
|
@ -60,6 +61,7 @@ export = {
|
||||||
Keyboard: require('./firefox/Input').Keyboard,
|
Keyboard: require('./firefox/Input').Keyboard,
|
||||||
Mouse: require('./firefox/Input').Mouse,
|
Mouse: require('./firefox/Input').Mouse,
|
||||||
Page: require('./firefox/Page').Page,
|
Page: require('./firefox/Page').Page,
|
||||||
|
Permissions: require('./firefox/features/permissions').Permissions,
|
||||||
Playwright: require('./firefox/Playwright').Playwright,
|
Playwright: require('./firefox/Playwright').Playwright,
|
||||||
Request: require('./firefox/NetworkManager').Request,
|
Request: require('./firefox/NetworkManager').Request,
|
||||||
Response: require('./firefox/NetworkManager').Response,
|
Response: require('./firefox/NetworkManager').Response,
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,21 @@ import { EventEmitter } from 'events';
|
||||||
import { assert } from '../helper';
|
import { assert } from '../helper';
|
||||||
import { Browser } from './Browser';
|
import { Browser } from './Browser';
|
||||||
import { Connection } from './Connection';
|
import { Connection } from './Connection';
|
||||||
|
import { Permissions } from './features/permissions';
|
||||||
import { Page } from './Page';
|
import { Page } from './Page';
|
||||||
import { Target } from './Target';
|
import { Target } from './Target';
|
||||||
import { Protocol } from './protocol';
|
|
||||||
|
|
||||||
export class BrowserContext extends EventEmitter {
|
export class BrowserContext extends EventEmitter {
|
||||||
private _connection: Connection;
|
readonly permissions: Permissions;
|
||||||
|
|
||||||
private _browser: Browser;
|
private _browser: Browser;
|
||||||
private _id: string;
|
private _id: string;
|
||||||
|
|
||||||
constructor(connection: Connection, browser: Browser, contextId: string | null) {
|
constructor(connection: Connection, browser: Browser, contextId: string | null) {
|
||||||
super();
|
super();
|
||||||
this._connection = connection;
|
|
||||||
this._browser = browser;
|
this._browser = browser;
|
||||||
this._id = contextId;
|
this._id = contextId;
|
||||||
|
this.permissions = new Permissions(connection, contextId);
|
||||||
}
|
}
|
||||||
|
|
||||||
targets(): Target[] {
|
targets(): Target[] {
|
||||||
|
|
@ -56,38 +57,6 @@ export class BrowserContext extends EventEmitter {
|
||||||
return !!this._id;
|
return !!this._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
async overridePermissions(origin: string, permissions: string[]) {
|
|
||||||
const webPermissionToProtocol = new Map<string, Protocol.Browser.PermissionType>([
|
|
||||||
['geolocation', 'geolocation'],
|
|
||||||
['midi', 'midi'],
|
|
||||||
['notifications', 'notifications'],
|
|
||||||
['camera', 'videoCapture'],
|
|
||||||
['microphone', 'audioCapture'],
|
|
||||||
['background-sync', 'backgroundSync'],
|
|
||||||
['ambient-light-sensor', 'sensors'],
|
|
||||||
['accelerometer', 'sensors'],
|
|
||||||
['gyroscope', 'sensors'],
|
|
||||||
['magnetometer', 'sensors'],
|
|
||||||
['accessibility-events', 'accessibilityEvents'],
|
|
||||||
['clipboard-read', 'clipboardRead'],
|
|
||||||
['clipboard-write', 'clipboardWrite'],
|
|
||||||
['payment-handler', 'paymentHandler'],
|
|
||||||
// chrome-specific permissions we have.
|
|
||||||
['midi-sysex', 'midiSysex'],
|
|
||||||
]);
|
|
||||||
const filtered = permissions.map(permission => {
|
|
||||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
|
||||||
if (!protocolPermission)
|
|
||||||
throw new Error('Unknown permission: ' + permission);
|
|
||||||
return protocolPermission;
|
|
||||||
});
|
|
||||||
await this._connection.send('Browser.grantPermissions', {origin, browserContextId: this._id || undefined, permissions: filtered});
|
|
||||||
}
|
|
||||||
|
|
||||||
async clearPermissionOverrides() {
|
|
||||||
await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined});
|
|
||||||
}
|
|
||||||
|
|
||||||
newPage(): Promise<Page> {
|
newPage(): Promise<Page> {
|
||||||
return this._browser._createPageInContext(this._id);
|
return this._browser._createPageInContext(this._id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
61
src/chromium/features/permissions.ts
Normal file
61
src/chromium/features/permissions.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Protocol } from '../protocol';
|
||||||
|
import { Connection } from './../Connection';
|
||||||
|
|
||||||
|
export class Permissions {
|
||||||
|
private _client: Connection;
|
||||||
|
private _browserContextId: string;
|
||||||
|
|
||||||
|
constructor(connection: Connection, browserContextId: string | null) {
|
||||||
|
this._client = connection;
|
||||||
|
this._browserContextId = browserContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async override(origin: string, permissions: string[]) {
|
||||||
|
const webPermissionToProtocol = new Map<string, Protocol.Browser.PermissionType>([
|
||||||
|
['geolocation', 'geolocation'],
|
||||||
|
['midi', 'midi'],
|
||||||
|
['notifications', 'notifications'],
|
||||||
|
['camera', 'videoCapture'],
|
||||||
|
['microphone', 'audioCapture'],
|
||||||
|
['background-sync', 'backgroundSync'],
|
||||||
|
['ambient-light-sensor', 'sensors'],
|
||||||
|
['accelerometer', 'sensors'],
|
||||||
|
['gyroscope', 'sensors'],
|
||||||
|
['magnetometer', 'sensors'],
|
||||||
|
['accessibility-events', 'accessibilityEvents'],
|
||||||
|
['clipboard-read', 'clipboardRead'],
|
||||||
|
['clipboard-write', 'clipboardWrite'],
|
||||||
|
['payment-handler', 'paymentHandler'],
|
||||||
|
// chrome-specific permissions we have.
|
||||||
|
['midi-sysex', 'midiSysex'],
|
||||||
|
]);
|
||||||
|
const filtered = permissions.map(permission => {
|
||||||
|
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||||
|
if (!protocolPermission)
|
||||||
|
throw new Error('Unknown permission: ' + permission);
|
||||||
|
return protocolPermission;
|
||||||
|
});
|
||||||
|
await this._client.send('Browser.grantPermissions', {origin, browserContextId: this._browserContextId || undefined, permissions: filtered});
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearOverrides() {
|
||||||
|
await this._client.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,11 +15,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {RegisteredListener, helper, assert} from '../helper';
|
import { EventEmitter } from 'events';
|
||||||
import {Page, Viewport} from './Page';
|
import { Events } from '../Events';
|
||||||
import {EventEmitter} from 'events';
|
import { assert, helper, RegisteredListener } from '../helper';
|
||||||
import {Connection, ConnectionEvents} from './Connection';
|
import { Connection, ConnectionEvents } from './Connection';
|
||||||
import {Events} from '../Events';
|
import { Permissions } from './features/permissions';
|
||||||
|
import { Page, Viewport } from './Page';
|
||||||
|
|
||||||
export class Browser extends EventEmitter {
|
export class Browser extends EventEmitter {
|
||||||
private _connection: Connection;
|
private _connection: Connection;
|
||||||
|
|
@ -262,36 +263,16 @@ export class BrowserContext extends EventEmitter {
|
||||||
_connection: Connection;
|
_connection: Connection;
|
||||||
_browser: Browser;
|
_browser: Browser;
|
||||||
_browserContextId: string;
|
_browserContextId: string;
|
||||||
|
readonly permissions: Permissions;
|
||||||
|
|
||||||
constructor(connection: Connection, browser: Browser, browserContextId: string | null) {
|
constructor(connection: Connection, browser: Browser, browserContextId: string | null) {
|
||||||
super();
|
super();
|
||||||
this._connection = connection;
|
this._connection = connection;
|
||||||
this._browser = browser;
|
this._browser = browser;
|
||||||
this._browserContextId = browserContextId;
|
this._browserContextId = browserContextId;
|
||||||
|
this.permissions = new Permissions(connection, browserContextId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async overridePermissions(origin: string, permissions: Array<string>) {
|
|
||||||
const webPermissionToProtocol = new Map([
|
|
||||||
['geolocation', 'geo'],
|
|
||||||
['microphone', 'microphone'],
|
|
||||||
['camera', 'camera'],
|
|
||||||
['notifications', 'desktop-notifications'],
|
|
||||||
]);
|
|
||||||
permissions = permissions.map(permission => {
|
|
||||||
const protocolPermission = webPermissionToProtocol.get(permission);
|
|
||||||
if (!protocolPermission)
|
|
||||||
throw new Error('Unknown permission: ' + permission);
|
|
||||||
return protocolPermission;
|
|
||||||
});
|
|
||||||
await this._connection.send('Browser.grantPermissions', {origin, browserContextId: this._browserContextId || undefined, permissions});
|
|
||||||
}
|
|
||||||
|
|
||||||
async clearPermissionOverrides() {
|
|
||||||
await this._connection.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
targets(): Array<Target> {
|
targets(): Array<Target> {
|
||||||
return this._browser.targets().filter(target => target.browserContext() === this);
|
return this._browser.targets().filter(target => target.browserContext() === this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import {FrameManager, normalizeWaitUntil, FrameManagerEvents} from './FrameManag
|
||||||
import {NetworkManager, Request, Response, NetworkManagerEvents} from './NetworkManager';
|
import {NetworkManager, Request, Response, NetworkManagerEvents} from './NetworkManager';
|
||||||
import {TimeoutSettings} from '../TimeoutSettings';
|
import {TimeoutSettings} from '../TimeoutSettings';
|
||||||
import {NavigationWatchdog} from './NavigationWatchdog';
|
import {NavigationWatchdog} from './NavigationWatchdog';
|
||||||
import {Accessibility} from './Accessibility';
|
import {Accessibility} from './features/accessibility';
|
||||||
import { Target, BrowserContext } from './Browser';
|
import { Target, BrowserContext } from './Browser';
|
||||||
import { Events } from '../Events';
|
import { Events } from '../Events';
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ export class Page extends EventEmitter {
|
||||||
private _keyboard: Keyboard;
|
private _keyboard: Keyboard;
|
||||||
private _mouse: Mouse;
|
private _mouse: Mouse;
|
||||||
private _touchscreen: Touchscreen;
|
private _touchscreen: Touchscreen;
|
||||||
private _accessibility: Accessibility;
|
readonly accessibility: Accessibility;
|
||||||
private _closed: boolean;
|
private _closed: boolean;
|
||||||
private _pageBindings: Map<string, Function>;
|
private _pageBindings: Map<string, Function>;
|
||||||
private _networkManager: NetworkManager;
|
private _networkManager: NetworkManager;
|
||||||
|
|
@ -56,7 +56,7 @@ export class Page extends EventEmitter {
|
||||||
this._keyboard = new Keyboard(session);
|
this._keyboard = new Keyboard(session);
|
||||||
this._mouse = new Mouse(session, this._keyboard);
|
this._mouse = new Mouse(session, this._keyboard);
|
||||||
this._touchscreen = new Touchscreen(session, this._keyboard, this._mouse);
|
this._touchscreen = new Touchscreen(session, this._keyboard, this._mouse);
|
||||||
this._accessibility = new Accessibility(session);
|
this.accessibility = new Accessibility(session);
|
||||||
this._closed = false;
|
this._closed = false;
|
||||||
this._pageBindings = new Map();
|
this._pageBindings = new Map();
|
||||||
this._networkManager = new NetworkManager(session);
|
this._networkManager = new NetworkManager(session);
|
||||||
|
|
@ -334,10 +334,6 @@ export class Page extends EventEmitter {
|
||||||
return this._frameManager.mainFrame();
|
return this._frameManager.mainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
get accessibility() {
|
|
||||||
return this._accessibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
get keyboard(){
|
get keyboard(){
|
||||||
return this._keyboard;
|
return this._keyboard;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ class AXNode {
|
||||||
private _name: string;
|
private _name: string;
|
||||||
private _role: string;
|
private _role: string;
|
||||||
private _cachedHasFocusableChild: boolean|undefined;
|
private _cachedHasFocusableChild: boolean|undefined;
|
||||||
|
|
||||||
constructor(payload) {
|
constructor(payload) {
|
||||||
this._payload = payload;
|
this._payload = payload;
|
||||||
this._children = (payload.children || []).map(x => new AXNode(x));
|
this._children = (payload.children || []).map(x => new AXNode(x));
|
||||||
|
|
@ -105,6 +106,7 @@ class AXNode {
|
||||||
this._role = this._payload.role;
|
this._role = this._payload.role;
|
||||||
this._cachedHasFocusableChild;
|
this._cachedHasFocusableChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isPlainTextField(): boolean {
|
_isPlainTextField(): boolean {
|
||||||
if (this._richlyEditable)
|
if (this._richlyEditable)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -112,10 +114,12 @@ class AXNode {
|
||||||
return true;
|
return true;
|
||||||
return this._role === 'entry';
|
return this._role === 'entry';
|
||||||
}
|
}
|
||||||
|
|
||||||
_isTextOnlyObject(): boolean {
|
_isTextOnlyObject(): boolean {
|
||||||
const role = this._role;
|
const role = this._role;
|
||||||
return (role === 'text leaf' || role === 'text' || role === 'statictext');
|
return (role === 'text leaf' || role === 'text' || role === 'statictext');
|
||||||
}
|
}
|
||||||
|
|
||||||
_hasFocusableChild(): boolean {
|
_hasFocusableChild(): boolean {
|
||||||
if (this._cachedHasFocusableChild === undefined) {
|
if (this._cachedHasFocusableChild === undefined) {
|
||||||
this._cachedHasFocusableChild = false;
|
this._cachedHasFocusableChild = false;
|
||||||
|
|
@ -128,6 +132,7 @@ class AXNode {
|
||||||
}
|
}
|
||||||
return this._cachedHasFocusableChild;
|
return this._cachedHasFocusableChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
isLeafNode(): boolean {
|
isLeafNode(): boolean {
|
||||||
if (!this._children.length)
|
if (!this._children.length)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -160,6 +165,7 @@ class AXNode {
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isControl(): boolean {
|
isControl(): boolean {
|
||||||
switch (this._role) {
|
switch (this._role) {
|
||||||
case 'checkbutton':
|
case 'checkbutton':
|
||||||
|
|
@ -191,6 +197,7 @@ class AXNode {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isInteresting(insideControl: boolean): boolean {
|
isInteresting(insideControl: boolean): boolean {
|
||||||
if (this._focusable || this._richlyEditable)
|
if (this._focusable || this._richlyEditable)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -202,6 +209,7 @@ class AXNode {
|
||||||
return false;
|
return false;
|
||||||
return this.isLeafNode() && !!this._name.trim();
|
return this.isLeafNode() && !!this._name.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize(): SerializedAXNode {
|
serialize(): SerializedAXNode {
|
||||||
const node: {[x in keyof SerializedAXNode]: any} = {
|
const node: {[x in keyof SerializedAXNode]: any} = {
|
||||||
role: this._role
|
role: this._role
|
||||||
49
src/firefox/features/permissions.ts
Normal file
49
src/firefox/features/permissions.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Google Inc. All rights reserved.
|
||||||
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Connection } from '../Connection';
|
||||||
|
|
||||||
|
export class Permissions {
|
||||||
|
private _connection: Connection;
|
||||||
|
private _browserContextId: string;
|
||||||
|
|
||||||
|
constructor(connection: Connection, browserContextId: string | null) {
|
||||||
|
this._connection = connection;
|
||||||
|
this._browserContextId = browserContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async override(origin: string, permissions: Array<string>) {
|
||||||
|
const webPermissionToProtocol = new Map([
|
||||||
|
['geolocation', 'geo'],
|
||||||
|
['microphone', 'microphone'],
|
||||||
|
['camera', 'camera'],
|
||||||
|
['notifications', 'desktop-notifications'],
|
||||||
|
]);
|
||||||
|
permissions = permissions.map(permission => {
|
||||||
|
const protocolPermission = webPermissionToProtocol.get(permission);
|
||||||
|
if (!protocolPermission)
|
||||||
|
throw new Error('Unknown permission: ' + permission);
|
||||||
|
return protocolPermission;
|
||||||
|
});
|
||||||
|
await this._connection.send('Browser.grantPermissions', {origin, browserContextId: this._browserContextId || undefined, permissions});
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearOverrides() {
|
||||||
|
await this._connection.send('Browser.resetPermissions', {browserContextId: this._browserContextId || undefined});
|
||||||
|
}
|
||||||
|
}
|
||||||
97
src/tests/permissions.spec.js
Normal file
97
src/tests/permissions.spec.js
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports.addTests = function({testRunner, expect, WEBKIT}) {
|
||||||
|
const {describe, xdescribe, fdescribe} = testRunner;
|
||||||
|
const {it, fit, xit} = testRunner;
|
||||||
|
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||||
|
|
||||||
|
// Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)
|
||||||
|
describe('Permissions', function() {
|
||||||
|
function getPermission(page, name) {
|
||||||
|
return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
it.skip(WEBKIT)('should be prompt by default', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should deny permission when not listed', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should fail when bad permission is given', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
let error = {};
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, ['foo']).catch(e => error = e);
|
||||||
|
expect(error.message).toBe('Unknown permission: foo');
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should grant permission when listed', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should reset permissions', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
||||||
|
await context.permissions.clearOverrides();
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should trigger permission onchange', async({page, server, context}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window['events'] = [];
|
||||||
|
return navigator.permissions.query({name: 'geolocation'}).then(function(result) {
|
||||||
|
window['events'].push(result.state);
|
||||||
|
result.onchange = function() {
|
||||||
|
window['events'].push(result.state);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
expect(await page.evaluate(() => window['events'])).toEqual(['prompt']);
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||||
|
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied']);
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||||
|
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']);
|
||||||
|
await context.permissions.clearOverrides();
|
||||||
|
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']);
|
||||||
|
});
|
||||||
|
it.skip(WEBKIT)('should isolate permissions between browser contexs', async({page, server, context, browser}) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
const otherContext = await browser.createIncognitoBrowserContext();
|
||||||
|
const otherPage = await otherContext.newPage();
|
||||||
|
await otherPage.goto(server.EMPTY_PAGE);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||||
|
expect(await getPermission(otherPage, 'geolocation')).toBe('prompt');
|
||||||
|
|
||||||
|
await context.permissions.override(server.EMPTY_PAGE, []);
|
||||||
|
await otherContext.permissions.override(server.EMPTY_PAGE, ['geolocation']);
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
||||||
|
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
||||||
|
|
||||||
|
await context.permissions.clearOverrides();
|
||||||
|
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
||||||
|
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
||||||
|
|
||||||
|
await otherContext.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -166,84 +166,12 @@ module.exports.addTests = function({testRunner, expect, headless, playwright, FF
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)
|
|
||||||
describe('BrowserContext.overridePermissions', function() {
|
|
||||||
function getPermission(page, name) {
|
|
||||||
return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
it.skip(WEBKIT)('should be prompt by default', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should deny permission when not listed', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, []);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should fail when bad permission is given', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
let error = null;
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, ['foo']).catch(e => error = e);
|
|
||||||
expect(error.message).toBe('Unknown permission: foo');
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should grant permission when listed', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, ['geolocation']);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should reset permissions', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, ['geolocation']);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('granted');
|
|
||||||
await context.clearPermissionOverrides();
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should trigger permission onchange', async({page, server, context}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
await page.evaluate(() => {
|
|
||||||
window.events = [];
|
|
||||||
return navigator.permissions.query({name: 'geolocation'}).then(function(result) {
|
|
||||||
window.events.push(result.state);
|
|
||||||
result.onchange = function() {
|
|
||||||
window.events.push(result.state);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
expect(await page.evaluate(() => window.events)).toEqual(['prompt']);
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, []);
|
|
||||||
expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied']);
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, ['geolocation']);
|
|
||||||
expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied', 'granted']);
|
|
||||||
await context.clearPermissionOverrides();
|
|
||||||
expect(await page.evaluate(() => window.events)).toEqual(['prompt', 'denied', 'granted', 'prompt']);
|
|
||||||
});
|
|
||||||
it.skip(WEBKIT)('should isolate permissions between browser contexs', async({page, server, context, browser}) => {
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
|
||||||
const otherContext = await browser.createIncognitoBrowserContext();
|
|
||||||
const otherPage = await otherContext.newPage();
|
|
||||||
await otherPage.goto(server.EMPTY_PAGE);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
|
||||||
expect(await getPermission(otherPage, 'geolocation')).toBe('prompt');
|
|
||||||
|
|
||||||
await context.overridePermissions(server.EMPTY_PAGE, []);
|
|
||||||
await otherContext.overridePermissions(server.EMPTY_PAGE, ['geolocation']);
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('denied');
|
|
||||||
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
|
||||||
|
|
||||||
await context.clearPermissionOverrides();
|
|
||||||
expect(await getPermission(page, 'geolocation')).toBe('prompt');
|
|
||||||
expect(await getPermission(otherPage, 'geolocation')).toBe('granted');
|
|
||||||
|
|
||||||
await otherContext.close();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: not supported in WebKit (as well as Emulation domain in general).
|
// FIXME: not supported in WebKit (as well as Emulation domain in general).
|
||||||
// It was removed from WebKit in https://webkit.org/b/126630
|
// It was removed from WebKit in https://webkit.org/b/126630
|
||||||
describe.skip(FFOX || WEBKIT)('Page.setGeolocation', function() {
|
describe.skip(FFOX || WEBKIT)('Page.setGeolocation', function() {
|
||||||
it('should work', async({page, server, context}) => {
|
it('should work', async({page, server, context}) => {
|
||||||
await context.overridePermissions(server.PREFIX, ['geolocation']);
|
await context.permissions.override(server.PREFIX, ['geolocation']);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
await page.setGeolocation({longitude: 10, latitude: 10});
|
await page.setGeolocation({longitude: 10, latitude: 10});
|
||||||
const geolocation = await page.evaluate(() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {
|
const geolocation = await page.evaluate(() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,9 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => {
|
||||||
|
|
||||||
// Page-level tests that are given a browser, a context and a page.
|
// Page-level tests that are given a browser, a context and a page.
|
||||||
// Each test is launched in a new browser context.
|
// Each test is launched in a new browser context.
|
||||||
require('../src/chromium/features/accessibility.spec.js').addTests(testOptions);
|
require('../src/tests/accessibility.spec.js').addTests(testOptions);
|
||||||
|
require('../src/tests/permissions.spec.js').addTests(testOptions);
|
||||||
|
require('../src/chromium/features/workers.spec.js').addTests(testOptions);
|
||||||
require('./browser.spec.js').addTests(testOptions);
|
require('./browser.spec.js').addTests(testOptions);
|
||||||
require('./click.spec.js').addTests(testOptions);
|
require('./click.spec.js').addTests(testOptions);
|
||||||
require('./cookies.spec.js').addTests(testOptions);
|
require('./cookies.spec.js').addTests(testOptions);
|
||||||
|
|
@ -154,7 +156,6 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => {
|
||||||
require('./target.spec.js').addTests(testOptions);
|
require('./target.spec.js').addTests(testOptions);
|
||||||
require('./touchscreen.spec.js').addTests(testOptions);
|
require('./touchscreen.spec.js').addTests(testOptions);
|
||||||
require('./waittask.spec.js').addTests(testOptions);
|
require('./waittask.spec.js').addTests(testOptions);
|
||||||
require('../src/chromium/features/workers.spec.js').addTests(testOptions);
|
|
||||||
if (CHROME) {
|
if (CHROME) {
|
||||||
require('./CDPSession.spec.js').addTests(testOptions);
|
require('./CDPSession.spec.js').addTests(testOptions);
|
||||||
require('../src/chromium/features/coverage.spec.js').addTests(testOptions);
|
require('../src/chromium/features/coverage.spec.js').addTests(testOptions);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue