feat: add allow/block serviceWorkers option (#14714)

Adds cross-browser support for easily allowing/blocking Service Workers via a Context option.

Includes plumbing for Playwright Test's `use`.

Resolves #14522.

Relates #1090.
Supercedes #14321.
This commit is contained in:
Ross Wollman 2022-06-08 18:27:51 -04:00 committed by GitHub
parent 48ab172bda
commit 85d03714d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 117 additions and 6 deletions

View File

@ -637,10 +637,18 @@ contexts override the proxy, global proxy will be never used and can be any stri
## context-option-strict
- `strictSelectors` <[boolean]>
It specified, enables strict selectors mode for this context. In the strict selectors mode all operations
If specified, enables strict selectors mode for this context. In the strict selectors mode all operations
on selectors that imply single target DOM element will throw when more than one element matches the selector.
See [Locator] to learn more about the strict mode.
## context-option-service-worker-policy
- `serviceWorkers` <[ServiceWorkerPolicy]<"allow"|"block">>
* `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered by sites.
* `"block"`: Playwright will block all registration of Service Workers.
Defaults to `"allow"`.
## select-options-values
* langs: java, js, csharp
- `values` <[null]|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>>
@ -796,6 +804,7 @@ An acceptable perceived color difference in the [YIQ color space](https://en.wik
- %%-context-option-recordvideo-dir-%%
- %%-context-option-recordvideo-size-%%
- %%-context-option-strict-%%
- %%-context-option-service-worker-policy-%%
## browser-option-args
- `args` <[Array]<[string]>>
@ -1020,4 +1029,3 @@ When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`,
- %%-screenshot-option-type-%%
- %%-screenshot-option-mask-%%
- %%-input-timeout-%%

View File

@ -215,3 +215,4 @@ Learn more about [recording video](../test-configuration.md#record-video).
## property: TestOptions.viewport = %%-context-option-viewport-%%
## property: TestOptions.serviceWorkers = %%-context-option-service-worker-policy-%%

View File

@ -413,6 +413,7 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
noDefaultViewport: options.viewport === null,
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
storageState: await prepareStorageState(options),
serviceWorkers: options.serviceWorkers,
recordHar: prepareRecordHarOptions(options.recordHar),
};
if (!contextParams.recordVideo && options.videosPath) {

View File

@ -747,6 +747,7 @@ export type BrowserTypeLaunchPersistentContextParams = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
userDataDir: string,
slowMo?: number,
};
@ -816,6 +817,7 @@ export type BrowserTypeLaunchPersistentContextOptions = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
slowMo?: number,
};
export type BrowserTypeLaunchPersistentContextResult = {
@ -909,6 +911,7 @@ export type BrowserNewContextParams = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
proxy?: {
server: string,
bypass?: string,
@ -965,6 +968,7 @@ export type BrowserNewContextOptions = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
proxy?: {
server: string,
bypass?: string,
@ -3984,6 +3988,7 @@ export type AndroidDeviceLaunchBrowserParams = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
pkg?: string,
proxy?: {
server: string,
@ -4037,6 +4042,7 @@ export type AndroidDeviceLaunchBrowserOptions = {
},
recordHar?: RecordHarOptions,
strictSelectors?: boolean,
serviceWorkers?: 'allow' | 'block',
pkg?: string,
proxy?: {
server: string,

View File

@ -455,6 +455,11 @@ ContextOptions:
height: number
recordHar: RecordHarOptions?
strictSelectors: boolean?
serviceWorkers:
type: enum?
literals:
- allow
- block
LocalUtils:
type: interface

View File

@ -354,6 +354,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
})),
recordHar: tOptional(tType('RecordHarOptions')),
strictSelectors: tOptional(tBoolean),
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
userDataDir: tString,
slowMo: tOptional(tNumber),
});
@ -410,6 +411,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
})),
recordHar: tOptional(tType('RecordHarOptions')),
strictSelectors: tOptional(tBoolean),
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
proxy: tOptional(tObject({
server: tString,
bypass: tOptional(tString),
@ -1441,6 +1443,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
})),
recordHar: tOptional(tType('RecordHarOptions')),
strictSelectors: tOptional(tBoolean),
serviceWorkers: tOptional(tEnum(['allow', 'block'])),
pkg: tOptional(tString),
proxy: tOptional(tObject({
server: tString,

View File

@ -122,6 +122,8 @@ export abstract class BrowserContext extends SdkObject {
if (debugMode() === 'console')
await this.extendInjectedScript(consoleApiSource.source);
if (this._options.serviceWorkers === 'block')
await this.addInitScript(`\nnavigator.serviceWorker.register = () => { console.warn('Service Worker registration blocked by Playwright'); };\n`);
}
async _ensureVideosPath() {

View File

@ -266,6 +266,7 @@ export type BrowserContextOptions = {
strictSelectors?: boolean,
proxy?: ProxySettings,
baseURL?: string,
serviceWorkers?: 'allow' | 'block',
};
export type EnvArray = { name: string, value: string }[];

View File

@ -10371,13 +10371,22 @@ export interface BrowserType<Unused = {}> {
height: number;
};
/**
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
* by sites.
* - `"block"`: Playwright will block all registration of Service Workers.
*
* Defaults to `"allow"`.
*/
serviceWorkers?: "allow"|"block";
/**
* Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
*/
slowMo?: number;
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
* more about the strict mode.
*/
@ -11528,7 +11537,16 @@ export interface AndroidDevice {
};
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
* by sites.
* - `"block"`: Playwright will block all registration of Service Workers.
*
* Defaults to `"allow"`.
*/
serviceWorkers?: "allow"|"block";
/**
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
* more about the strict mode.
*/
@ -13060,6 +13078,15 @@ export interface Browser extends EventEmitter {
height: number;
};
/**
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
* by sites.
* - `"block"`: Playwright will block all registration of Service Workers.
*
* Defaults to `"allow"`.
*/
serviceWorkers?: "allow"|"block";
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via
@ -13115,7 +13142,7 @@ export interface Browser extends EventEmitter {
};
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
* more about the strict mode.
*/
@ -15521,6 +15548,15 @@ export interface BrowserContextOptions {
height: number;
};
/**
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
* by sites.
* - `"block"`: Playwright will block all registration of Service Workers.
*
* Defaults to `"allow"`.
*/
serviceWorkers?: "allow"|"block";
/**
* Populates context with given storage state. This option can be used to initialize context with logged-in information
* obtained via
@ -15576,7 +15612,7 @@ export interface BrowserContextOptions {
};
/**
* It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* If specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors
* that imply single target DOM element will throw when more than one element matches the selector. See [Locator] to learn
* more about the strict mode.
*/

View File

@ -159,6 +159,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
baseURL: [ async ({ }, use) => {
await use(process.env.PLAYWRIGHT_TEST_BASE_URL);
}, { option: true } ],
serviceWorkers: [ 'allow', { option: true } ],
contextOptions: [ {}, { option: true } ],
_combinedContextOptions: async ({
@ -183,6 +184,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
userAgent,
baseURL,
contextOptions,
serviceWorkers,
}, use) => {
const options: BrowserContextOptions = {};
if (acceptDownloads !== undefined)
@ -225,6 +227,8 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
options.viewport = viewport;
if (baseURL !== undefined)
options.baseURL = baseURL;
if (serviceWorkers !== undefined)
options.serviceWorkers = serviceWorkers;
await use({
...contextOptions,
...options,

View File

@ -152,6 +152,7 @@ function contextHash(context: BrowserContextOptions): string {
timezoneId: context.timezoneId,
userAgent: context.userAgent,
deviceScaleFactor: context.deviceScaleFactor,
serviceWorkers: context.serviceWorkers,
};
return JSON.stringify(hash);
}

View File

@ -2494,6 +2494,7 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
type ServiceWorkerPolicy = Exclude<BrowserContextOptions['serviceWorkers'], undefined>;
type ConnectOptions = {
/**
* A browser websocket endpoint to connect to.
@ -2798,6 +2799,14 @@ export interface PlaywrightTestOptions {
* Learn more about [various timeouts](https://playwright.dev/docs/test-timeouts).
*/
navigationTimeout: number | undefined;
/**
* - `"allow"`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered
* by sites.
* - `"block"`: Playwright will block all registration of Service Workers.
*
* Defaults to `"allow"`.
*/
serviceWorkers: ServiceWorkerPolicy | undefined;
}

View File

@ -0,0 +1,32 @@
/**
* 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 { browserTest as it, expect } from '../config/browserTest';
it('should allow service workers by default', async ({ page, server }) => {
await page.goto(server.PREFIX + '/serviceworkers/empty/sw.html');
await expect(page.evaluate(() => window['registrationPromise'])).resolves.toBeTruthy();
});
it.describe('block', () => {
it.use({ serviceWorkers: 'block' });
it('blocks service worker registration', async ({ page, server }) => {
await Promise.all([
page.waitForEvent('console', evt => evt.text() === 'Service Worker registration blocked by Playwright'),
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html'),
]);
});
});

View File

@ -175,6 +175,7 @@ type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
type ExtraHTTPHeaders = Exclude<BrowserContextOptions['extraHTTPHeaders'], undefined>;
type Proxy = Exclude<BrowserContextOptions['proxy'], undefined>;
type StorageState = Exclude<BrowserContextOptions['storageState'], undefined>;
type ServiceWorkerPolicy = Exclude<BrowserContextOptions['serviceWorkers'], undefined>;
type ConnectOptions = {
/**
* A browser websocket endpoint to connect to.
@ -231,6 +232,7 @@ export interface PlaywrightTestOptions {
contextOptions: BrowserContextOptions;
actionTimeout: number | undefined;
navigationTimeout: number | undefined;
serviceWorkers: ServiceWorkerPolicy | undefined;
}