From d570fc780903d2f9b1782a64cf63b889d103fc1a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 18 Dec 2019 18:07:11 -0800 Subject: [PATCH] feat: further strip the browser api (#304) --- docs/api.md | 80 +++---- examples/block-images.js | 36 --- examples/custom-event.js | 48 ---- examples/detect-sniff.js | 44 ---- examples/download-and-verify.js | 17 -- examples/pdf.js | 33 --- examples/proxy.js | 35 --- examples/screenshot-fullpage.js | 29 --- examples/screenshot.js | 27 --- examples/search.js | 55 ----- src/browserContext.ts | 11 - src/chromium/Browser.ts | 25 -- src/firefox/Browser.ts | 20 -- src/page.ts | 3 - src/webkit/Browser.ts | 24 -- test/browser.spec.js | 24 -- test/browsercontext.spec.js | 15 +- test/chromium/browser.spec.js | 14 +- test/chromium/chromium.spec.js | 5 +- test/chromium/connect.spec.js | 16 +- test/chromium/headful.spec.js | 8 +- test/chromium/launcher.spec.js | 12 +- test/chromium/tracing.spec.js | 4 +- test/defaultbrowsercontext.spec.js | 2 +- test/firefox/launcher.spec.js | 2 +- test/launcher.spec.js | 6 +- test/page.spec.js | 8 +- test/playwright.spec.js | 7 +- utils/browser/test.js | 8 +- utils/doclint/check_public_api/test/test.js | 2 +- utils/doclint/cli.js | 2 +- utils/fetch_devices.js | 241 -------------------- utils/protocol-types-generator/index.js | 6 +- 33 files changed, 90 insertions(+), 779 deletions(-) delete mode 100644 examples/block-images.js delete mode 100644 examples/custom-event.js delete mode 100644 examples/detect-sniff.js delete mode 100644 examples/download-and-verify.js delete mode 100644 examples/pdf.js delete mode 100644 examples/proxy.js delete mode 100644 examples/screenshot-fullpage.js delete mode 100644 examples/screenshot.js delete mode 100644 examples/search.js delete mode 100755 utils/fetch_devices.js diff --git a/docs/api.md b/docs/api.md index 2287bb179a..313da8fdfb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -36,8 +36,6 @@ * [browser.disconnect()](#browserdisconnect) * [browser.isConnected()](#browserisconnected) * [browser.newContext(options)](#browsernewcontextoptions) - * [browser.newPage(options)](#browsernewpageoptions) - * [browser.pages()](#browserpages) * [browser.process()](#browserprocess) - [class: BrowserContext](#class-browsercontext) * [browserContext.browser()](#browsercontextbrowser) @@ -359,7 +357,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.goto('https://www.google.com'); // other actions... await browser.close(); @@ -405,7 +404,8 @@ const iPhone = playwright.devices['iPhone 6']; (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.emulate(iPhone); await page.goto('https://www.google.com'); // other actions... @@ -558,7 +558,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.goto('https://example.com'); await browser.close(); })(); @@ -648,31 +649,6 @@ Creates a new browser context. It won't share cookies/cache with other browser c })(); ``` -#### browser.newPage(options) -- `options` <[Object]> - - `ignoreHTTPSErrors` Whether to ignore HTTPS errors during navigation. Defaults to `false`. - - `bypassCSP` Toggles bypassing page's Content-Security-Policy. - - `viewport` Sets a consistent viewport for each page. Defaults to an 800x600 viewport. `null` disables the default viewport. - - `width` <[number]> page width in pixels. - - `height` <[number]> page height in pixels. - - `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`. - - `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`. - - `hasTouch`<[boolean]> Specifies if viewport supports touch events. Defaults to `false` - - `isLandscape` <[boolean]> Specifies if viewport is in landscape mode. Defaults to `false`. - - `userAgent` Specific user agent to use in this page - - `mediaType` Changes the CSS media type of the page. The only allowed values are `'screen'`, `'print'` and `null`. Passing `null` disables CSS media emulation. - - `colorScheme` Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. - - `javaScriptEnabled` Whether or not to enable or disable JavaScript in the page. Defaults to true. - - `timezoneId` Changes the timezone of the page. See [ICU’s `metaZones.txt`](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) for a list of supported timezone IDs. - -Promise which resolves to a new [Page] object. The [Page] is created in a new browser context that it will own. Closing this page will close the context. - -#### browser.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. In case of multiple browser contexts, -the method will return an array with all the pages in all browser contexts. - #### browser.process() - returns: Spawned browser process. Returns `null` if the browser instance was created with [`playwright.connect`](#playwrightconnectoptions) method. @@ -680,8 +656,7 @@ the method will return an array with all the pages in all browser contexts. * extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) -BrowserContexts provide a way to operate multiple independent browser sessions. When a browser is launched, it has -a single BrowserContext used by default. The method `browser.newPage()` creates a page in the default browser context. +BrowserContexts provide a way to operate multiple independent browser sessions. If a page opens another page, e.g. with a `window.open` call, the popup will belong to the parent page's browser context. @@ -840,7 +815,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.goto('https://example.com'); await page.screenshot({path: 'screenshot.png'}); await browser.close(); @@ -1240,7 +1216,8 @@ const crypto = require('crypto'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); page.on('console', msg => console.log(msg.text())); await page.exposeFunction('md5', text => crypto.createHash('md5').update(text).digest('hex') @@ -1263,7 +1240,8 @@ const fs = require('fs'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); page.on('console', msg => console.log(msg.text())); await page.exposeFunction('readfile', async filePath => { return new Promise((resolve, reject) => { @@ -1634,7 +1612,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); const watchDog = page.waitForFunction('window.innerWidth < 100'); await page.setViewport({width: 50, height: 50}); await watchDog; @@ -1715,7 +1694,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); let currentURL; page .waitForSelector('img') @@ -1744,7 +1724,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); let currentURL; page .waitForXPath('//img') @@ -2178,7 +2159,7 @@ Emitted when the url of a target changes. #### event: 'targetcreated' - <[Target]> -Emitted when a target is created, for example when a new page is opened by [`window.open`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) or [`browser.newPage`](#browsernewpage). +Emitted when a target is created, for example when a new page is opened by [`window.open`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) or [`browserContext.newPage`](#browsercontextnewpage). > **NOTE** This includes target creations in incognito browser contexts. @@ -2256,7 +2237,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); page.on('dialog', async dialog => { console.log(dialog.message()); await dialog.dismiss(); @@ -2319,7 +2301,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.goto('https://www.google.com/chrome/browser/canary.html'); dumpFrameTree(page.mainFrame(), ''); await browser.close(); @@ -2716,7 +2699,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100'); page.setViewport({width: 50, height: 50}); await watchDog; @@ -2770,7 +2754,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); let currentURL; page.mainFrame() .waitForSelector('img') @@ -2798,7 +2783,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); let currentURL; page.mainFrame() .waitForXPath('//img') @@ -2961,7 +2947,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.interception.enable(); page.on('request', interceptedRequest => { if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg')) @@ -3103,7 +3090,8 @@ const playwright = require('playwright'); (async () => { const browser = await playwright.launch(); - const page = await browser.newPage(); + const context = await browser.newContext(); + const page = await context.newPage(); await page.goto('https://example.com'); const hrefElement = await page.$('a'); await hrefElement.click(); diff --git a/examples/block-images.js b/examples/block-images.js deleted file mode 100644 index 474c001c7a..0000000000 --- a/examples/block-images.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2017 Google Inc., PhantomJS Authors 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - await page.interception.enable(); - page.on('request', request => { - if (request.resourceType() === 'image') - request.abort(); - else - request.continue(); - }); - await page.goto('https://news.google.com/news/'); - await page.screenshot({path: 'news.png', fullPage: true}); - - await browser.close(); -})(); - diff --git a/examples/custom-event.js b/examples/custom-event.js deleted file mode 100644 index be7265f581..0000000000 --- a/examples/custom-event.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - - // Define a window.onCustomEvent function on the page. - await page.exposeFunction('onCustomEvent', e => { - console.log(`${e.type} fired`, e.detail || ''); - }); - - /** - * Attach an event listener to page to capture a custom event on page load/navigation. - * @param {string} type Event name. - * @return {!Promise} - */ - function listenFor(type) { - return page.evaluateOnNewDocument(type => { - document.addEventListener(type, e => { - window.onCustomEvent({type, detail: e.detail}); - }); - }, type); - } - - await listenFor('app-ready'); // Listen for "app-ready" custom event on page load. - - await page.goto('https://www.chromestatus.com/features', {waitUntil: 'networkidle0'}); - - await browser.close(); -})(); diff --git a/examples/detect-sniff.js b/examples/detect-sniff.js deleted file mode 100644 index 202b84478d..0000000000 --- a/examples/detect-sniff.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2017 Google Inc., PhantomJS Authors 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -function sniffDetector() { - const userAgent = window.navigator.userAgent; - const platform = window.navigator.platform; - - window.navigator.__defineGetter__('userAgent', function() { - window.navigator.sniffed = true; - return userAgent; - }); - - window.navigator.__defineGetter__('platform', function() { - window.navigator.sniffed = true; - return platform; - }); -} - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - await page.evaluateOnNewDocument(sniffDetector); - await page.goto('https://www.google.com', {waitUntil: 'networkidle2'}); - console.log('Sniffed: ' + (await page.evaluate(() => !!navigator.sniffed))); - - await browser.close(); -})(); diff --git a/examples/download-and-verify.js b/examples/download-and-verify.js deleted file mode 100644 index beab8f8f8a..0000000000 --- a/examples/download-and-verify.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -(async () => { - const browserName = process.argv[2]; - const playwright = require('playwright')(browserName); - - console.log('downloading ' + browserName + '...'); - const revisionInfo = await playwright.downloadBrowser(); - console.log('downloaded to ' + revisionInfo.folderPath); - - console.log('checking user agent...'); - const browser = await playwright.launch(); - const page = await browser.newPage(); - console.log(await page.evaluate('navigator.userAgent')); - await browser.close(); -})() diff --git a/examples/pdf.js b/examples/pdf.js deleted file mode 100644 index c782fe1cbe..0000000000 --- a/examples/pdf.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'}); - // page.pdf() is currently supported only in headless mode. - // @see https://bugs.chromium.org/p/chromium/issues/detail?id=753118 - await page.pdf({ - path: 'hn.pdf', - format: 'letter' - }); - - await browser.close(); -})(); diff --git a/examples/proxy.js b/examples/proxy.js deleted file mode 100644 index b405647f21..0000000000 --- a/examples/proxy.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch({ - // Launch chromium using a proxy server on port 9876. - // More on proxying: - // https://www.chromium.org/developers/design-documents/network-settings - args: [ - '--proxy-server=127.0.0.1:9876', - // Use proxy for localhost URLs - '--proxy-bypass-list=<-loopback>', - ] - }); - const page = await browser.newPage(); - await page.goto('https://google.com'); - await browser.close(); -})(); diff --git a/examples/screenshot-fullpage.js b/examples/screenshot-fullpage.js deleted file mode 100644 index 603924ef14..0000000000 --- a/examples/screenshot-fullpage.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const playwright = require('playwright'); -const devices = require('playwright/DeviceDescriptors'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - await page.emulate(devices['iPhone 6']); - await page.goto('https://www.nytimes.com/'); - await page.screenshot({path: 'full.png', fullPage: true}); - await browser.close(); -})(); diff --git a/examples/screenshot.js b/examples/screenshot.js deleted file mode 100644 index 889d1be59d..0000000000 --- a/examples/screenshot.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - await page.goto('http://example.com'); - await page.screenshot({path: 'example.png'}); - await browser.close(); -})(); diff --git a/examples/search.js b/examples/search.js deleted file mode 100644 index aae2e8d50d..0000000000 --- a/examples/search.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * 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. - */ - -/** - * @fileoverview Search developers.google.com/web for articles tagged - * "Headless Chrome" and scrape results from the results page. - */ - -'use strict'; - -const playwright = require('playwright'); - -(async() => { - const browser = await playwright.launch(); - const page = await browser.newPage(); - - await page.goto('https://developers.google.com/web/'); - - // Type into search box. - await page.type('#searchbox input', 'Headless Chrome'); - - // Wait for suggest overlay to appear and click "show all results". - const allResultsSelector = '.devsite-suggest-all-results'; - await page.waitForSelector(allResultsSelector); - await page.click(allResultsSelector); - - // Wait for the results page to load and display the results. - const resultsSelector = '.gsc-results .gsc-thumbnail-inside a.gs-title'; - await page.waitForSelector(resultsSelector); - - // Extract the results from the page. - const links = await page.evaluate(resultsSelector => { - const anchors = Array.from(document.querySelectorAll(resultsSelector)); - return anchors.map(anchor => { - const title = anchor.textContent.split('|')[0].trim(); - return `${title} - ${anchor.href}`; - }); - }, resultsSelector); - console.log(links.join('\n')); - - await browser.close(); -})(); diff --git a/src/browserContext.ts b/src/browserContext.ts index 2cd4d3c377..446d0d7c6b 100644 --- a/src/browserContext.ts +++ b/src/browserContext.ts @@ -60,17 +60,6 @@ export class BrowserContext { return this._delegate.newPage(); } - async _createOwnerPage(): Promise { - try { - const page = await this._delegate.newPage(); - page._isContextOwner = true; - return page; - } catch (e) { - await this.close(); - throw e; - } - } - async cookies(...urls: string[]): Promise { return network.filterCookies(await this._delegate.cookies(), urls); } diff --git a/src/chromium/Browser.ts b/src/chromium/Browser.ts index 991d9dc9bb..3c477fe8e0 100644 --- a/src/chromium/Browser.ts +++ b/src/chromium/Browser.ts @@ -189,11 +189,6 @@ export class Browser extends EventEmitter { this.chromium.emit(Events.Chromium.TargetChanged, target); } - async newPage(options?: BrowserContextOptions): Promise { - const context = await this.newContext(options); - return context._createOwnerPage(); - } - async _closePage(page: Page) { await this._client.send('Target.closeTarget', { targetId: Target.fromPage(page)._targetId }); } @@ -232,22 +227,6 @@ export class Browser extends EventEmitter { } } - async pages(): Promise { - const contextPages = await Promise.all(this.browserContexts().map(context => context.pages())); - // Flatten array. - return contextPages.reduce((acc, x) => acc.concat(x), []); - } - - async version(): Promise { - const version = await this._getVersion(); - return version.product; - } - - async userAgent(): Promise { - const version = await this._getVersion(); - return version.userAgent; - } - async close() { await this._closeCallback.call(null); this.disconnect(); @@ -260,10 +239,6 @@ export class Browser extends EventEmitter { isConnected(): boolean { return !this._connection._closed; } - - _getVersion(): Promise { - return this._client.send('Browser.getVersion'); - } } async function emulateTimezone(session: CDPSession, timezoneId: string) { diff --git a/src/firefox/Browser.ts b/src/firefox/Browser.ts index e3537fa3fd..2429c5c17f 100644 --- a/src/firefox/Browser.ts +++ b/src/firefox/Browser.ts @@ -93,16 +93,6 @@ export class Browser extends EventEmitter { return this._defaultContext; } - async userAgent(): Promise { - const info = await this._connection.send('Browser.getInfo'); - return info.userAgent; - } - - async version(): Promise { - const info = await this._connection.send('Browser.getInfo'); - return info.version; - } - process(): import('child_process').ChildProcess | null { return this._process; } @@ -131,16 +121,6 @@ export class Browser extends EventEmitter { } } - async newPage(options?: BrowserContextOptions): Promise { - const context = await this.newContext(options); - return context._createOwnerPage(); - } - - async pages() { - const pageTargets = Array.from(this._targets.values()).filter(target => target.type() === 'page'); - return await Promise.all(pageTargets.map(target => target.page())); - } - _allTargets() { return Array.from(this._targets.values()); } diff --git a/src/page.ts b/src/page.ts index 96e18c8735..c14946be5d 100644 --- a/src/page.ts +++ b/src/page.ts @@ -93,7 +93,6 @@ export class Page extends EventEmitter { private _pageBindings = new Map(); readonly _screenshotter: Screenshotter; readonly _frameManager: frames.FrameManager; - _isContextOwner = false; constructor(delegate: PageDelegate, browserContext: BrowserContext) { super(); @@ -404,8 +403,6 @@ export class Page extends EventEmitter { await this._delegate.closePage(runBeforeUnload); if (!runBeforeUnload) await this._closedPromise; - if (this._isContextOwner) - await this._browserContext.close(); } isClosed(): boolean { diff --git a/src/webkit/Browser.ts b/src/webkit/Browser.ts index ed8f0b4eae..5f32dcc07f 100644 --- a/src/webkit/Browser.ts +++ b/src/webkit/Browser.ts @@ -65,19 +65,6 @@ export class Browser extends EventEmitter { }); } - async userAgent(): Promise { - const context = await this.newContext(); - const page = await context.newPage(); - const userAgent = await page.evaluate(() => navigator.userAgent); - context.close(); - return userAgent; - } - - async version(): Promise { - const userAgent = await this.userAgent(); - return userAgent.split(' ').pop(); - } - process(): childProcess.ChildProcess | null { return this._process; } @@ -99,11 +86,6 @@ export class Browser extends EventEmitter { return this._defaultContext; } - async newPage(options?: BrowserContextOptions): Promise { - const context = await this.newContext(options); - return context._createOwnerPage(); - } - targets(): Target[] { return Array.from(this._targets.values()); } @@ -132,12 +114,6 @@ export class Browser extends EventEmitter { } } - async pages(): Promise { - const contextPages = await Promise.all(this.browserContexts().map(context => context.pages())); - // Flatten array. - return contextPages.reduce((acc, x) => acc.concat(x), []); - } - _onTargetCreated(session: TargetSession, targetInfo: Protocol.Target.TargetInfo) { let context = null; if (targetInfo.browserContextId) { diff --git a/test/browser.spec.js b/test/browser.spec.js index f0f5691181..be77d79474 100644 --- a/test/browser.spec.js +++ b/test/browser.spec.js @@ -20,30 +20,6 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF const {it, fit, xit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe('Browser.version', function() { - it.skip(WEBKIT)('should return whether we are in headless', async({browser}) => { - const version = await browser.version(); - expect(version.length).toBeGreaterThan(0); - if (CHROME) - expect(version.startsWith('Headless')).toBe(headless); - else if (WEBKIT) - expect(version.startsWith('Safari/')).toBe(true); - else - expect(version.startsWith('Firefox/')).toBe(true); - }); - }); - - describe('Browser.userAgent', function() { - it('should include WebKit', async({browser}) => { - const userAgent = await browser.userAgent(); - expect(userAgent.length).toBeGreaterThan(0); - if (CHROME || WEBKIT) - expect(userAgent).toContain('WebKit'); - else - expect(userAgent).toContain('Gecko'); - }); - }); - describe('Browser.process', function() { it('should return child_process instance', async function({browser}) { const process = await browser.process(); diff --git a/test/browsercontext.spec.js b/test/browsercontext.spec.js index 531ec20ed9..7541dd2154 100644 --- a/test/browsercontext.spec.js +++ b/test/browsercontext.spec.js @@ -17,7 +17,7 @@ const utils = require('./utils'); -module.exports.describe = function({testRunner, expect, playwright, WEBKIT}) { +module.exports.describe = function({testRunner, expect, playwright, CHROME, WEBKIT}) { const {describe, xdescribe, fdescribe} = testRunner; const {it, fit, xit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; @@ -39,18 +39,7 @@ module.exports.describe = function({testRunner, expect, playwright, WEBKIT}) { await context.close(); expect(browser.browserContexts().length).toBe(1); }); - it('should close all belonging targets once closing context', async function({browser, newContext, server}) { - expect((await browser.pages()).length).toBe(1); - - const context = await newContext(); - await context.newPage(); - expect((await browser.pages()).length).toBe(2); - expect((await context.pages()).length).toBe(1); - - await context.close(); - expect((await browser.pages()).length).toBe(1); - }); - it('window.open should use parent tab context', async function({browser, newContext, server}) { + it('window.open should use parent tab context', async function({newContext, server}) { const context = await newContext(); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); diff --git a/test/chromium/browser.spec.js b/test/chromium/browser.spec.js index 2b331bad74..7e30b76689 100644 --- a/test/chromium/browser.spec.js +++ b/test/chromium/browser.spec.js @@ -6,12 +6,24 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF const {it, fit, xit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe('Browser.process', function() { + describe('CrBrowser', function() { it('should not return child_process for remote browser', async function({browser}) { const browserWSEndpoint = browser.chromium.wsEndpoint(); const remoteBrowser = await playwright.connect({browserWSEndpoint}); expect(remoteBrowser.process()).toBe(null); remoteBrowser.disconnect(); }); + it('should close all belonging targets once closing context', async function({browser, newContext}) { + const targets = async () => (await browser.chromium.targets()).filter(t => t.type() === 'page'); + expect((await targets()).length).toBe(1); + + const context = await newContext(); + await context.newPage(); + expect((await targets()).length).toBe(2); + expect((await context.pages()).length).toBe(1); + + await context.close(); + expect((await targets()).length).toBe(1); + }); }); }; diff --git a/test/chromium/chromium.spec.js b/test/chromium/chromium.spec.js index d6e95de04d..c5a552b44e 100644 --- a/test/chromium/chromium.spec.js +++ b/test/chromium/chromium.spec.js @@ -57,8 +57,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME }); it('should be able to use the default page in the browser', async({page, server, browser}) => { // The pages will be the testing page and the original newtab page - const allPages = await browser.pages(); - const originalPage = allPages.find(p => p !== page); + const originalPage = (await browser.defaultContext().pages())[0]; expect(await originalPage.evaluate(() => ['Hello', 'world'].join(' '))).toBe('Hello world'); expect(await originalPage.$('body')).toBeTruthy(); }); @@ -194,7 +193,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME let resolved = false; const targetPromise = browser.chromium.waitForTarget(target => target.url() === server.EMPTY_PAGE); targetPromise.then(() => resolved = true); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); expect(resolved).toBe(false); await page.goto(server.EMPTY_PAGE); const target = await targetPromise; diff --git a/test/chromium/connect.spec.js b/test/chromium/connect.spec.js index 0622a5019b..2681d4b26c 100644 --- a/test/chromium/connect.spec.js +++ b/test/chromium/connect.spec.js @@ -32,11 +32,11 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p ...defaultBrowserOptions, browserWSEndpoint: originalBrowser.chromium.wsEndpoint() }); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); expect(await page.evaluate(() => 7 * 8)).toBe(56); browser.disconnect(); - const secondPage = await originalBrowser.newPage(); + const secondPage = await originalBrowser.defaultContext().newPage(); expect(await secondPage.evaluate(() => 7 * 6)).toBe(42, 'original browser should still work'); await originalBrowser.close(); }); @@ -54,12 +54,12 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p it('should be able to reconnect to a disconnected browser', async({server}) => { const originalBrowser = await playwright.launch(defaultBrowserOptions); const browserWSEndpoint = originalBrowser.chromium.wsEndpoint(); - const page = await originalBrowser.newPage(); + const page = await originalBrowser.defaultContext().newPage(); await page.goto(server.PREFIX + '/frames/nested-frames.html'); originalBrowser.disconnect(); const browser = await playwright.connect({...defaultBrowserOptions, browserWSEndpoint}); - const pages = await browser.pages(); + const pages = await browser.defaultContext().pages(); const restoredPage = pages.find(page => page.url() === server.PREFIX + '/frames/nested-frames.html'); expect(utils.dumpFrames(restoredPage.mainFrame())).toEqual([ 'http://localhost:/frames/nested-frames.html', @@ -77,7 +77,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const browserTwo = await playwright.connect({ ...defaultBrowserOptions, browserWSEndpoint: browserOne.chromium.wsEndpoint() }); const [page1, page2] = await Promise.all([ new Promise(x => browserOne.chromium.once('targetcreated', target => x(target.page()))), - browserTwo.newPage(), + browserTwo.defaultContext().newPage(), ]); expect(await page1.evaluate(() => 7 * 8)).toBe(56); expect(await page2.evaluate(() => 7 * 6)).toBe(42); @@ -90,7 +90,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p server.setRoute('/one-style.css', () => {}); const browser = await playwright.launch(defaultBrowserOptions); const remote = await playwright.connect({...defaultBrowserOptions, browserWSEndpoint: browser.chromium.wsEndpoint()}); - const page = await remote.newPage(); + const page = await remote.defaultContext().newPage(); const navigationPromise = page.goto(server.PREFIX + '/one-style.html', {timeout: 60000}).catch(e => e); await server.waitForRequest('/one-style.css'); remote.disconnect(); @@ -102,7 +102,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p server.setRoute('/empty.html', () => {}); const browser = await playwright.launch(defaultBrowserOptions); const remote = await playwright.connect({...defaultBrowserOptions, browserWSEndpoint: browser.chromium.wsEndpoint()}); - const page = await remote.newPage(); + const page = await remote.defaultContext().newPage(); const watchdog = page.waitForSelector('div', { timeout: 60000 }).catch(e => e); remote.disconnect(); const error = await watchdog; @@ -115,7 +115,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p it('should terminate network waiters', async({context, server}) => { const browser = await playwright.launch(defaultBrowserOptions); const remote = await playwright.connect({...defaultBrowserOptions, browserWSEndpoint: browser.chromium.wsEndpoint()}); - const newPage = await remote.newPage(); + const newPage = await remote.defaultContext().newPage(); const results = await Promise.all([ newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e), newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e), diff --git a/test/chromium/headful.spec.js b/test/chromium/headful.spec.js index 1f40bf4570..22a2fbdd5b 100644 --- a/test/chromium/headful.spec.js +++ b/test/chromium/headful.spec.js @@ -47,7 +47,7 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows describe('HEADFUL', function() { it('background_page target type should be available', async() => { const browserWithExtension = await playwright.launch(extensionOptions); - const page = await browserWithExtension.newPage(); + const page = await browserWithExtension.defaultContext().newPage(); const backgroundPageTarget = await browserWithExtension.chromium.waitForTarget(target => target.type() === 'background_page'); await page.close(); await browserWithExtension.close(); @@ -63,7 +63,7 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows }); it('should have default url when launching browser', async function() { const browser = await playwright.launch(extensionOptions); - const pages = (await browser.pages()).map(page => page.url()); + const pages = (await browser.defaultContext().pages()).map(page => page.url()); expect(pages).toEqual(['about:blank']); await browser.close(); }); @@ -89,7 +89,7 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows xit('OOPIF: should report google.com frame', async({server}) => { // https://google.com is isolated by default in Chromium embedder. const browser = await playwright.launch(headfulOptions); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(server.EMPTY_PAGE); await page.interception.enable(); page.on('request', r => page.interception.fulfill(r, {body: 'YO, GOOGLE.COM'})); @@ -109,7 +109,7 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows }); it('should close browser with beforeunload page', async({server}) => { const browser = await playwright.launch(headfulOptions); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers // fire. diff --git a/test/chromium/launcher.spec.js b/test/chromium/launcher.spec.js index 5fd503bc7d..c1a429085a 100644 --- a/test/chromium/launcher.spec.js +++ b/test/chromium/launcher.spec.js @@ -38,7 +38,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const options = Object.assign({userDataDir}, defaultBrowserOptions); const browser = await playwright.launch(options); // Open a page to make sure its functional. - await browser.newPage(); + await browser.defaultContext().newPage(); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); await browser.close(); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); @@ -87,12 +87,12 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const browserURL = 'http://127.0.0.1:21222'; const browser1 = await playwright.connect({browserURL}); - const page1 = await browser1.newPage(); + const page1 = await browser1.defaultContext().newPage(); expect(await page1.evaluate(() => 7 * 8)).toBe(56); browser1.disconnect(); const browser2 = await playwright.connect({browserURL: browserURL + '/'}); - const page2 = await browser2.newPage(); + const page2 = await browser2.defaultContext().newPage(); expect(await page2.evaluate(() => 8 * 7)).toBe(56); browser2.disconnect(); originalBrowser.close(); @@ -163,7 +163,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const browser = await playwright.launch(options); expect((await browser.defaultContext().pages()).length).toBe(1); expect(browser.chromium.wsEndpoint()).toBe(''); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); expect(await page.evaluate('11 * 11')).toBe(121); await page.close(); await browser.close(); @@ -173,7 +173,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p options.args = ['--remote-debugging-pipe'].concat(options.args || []); const browser = await playwright.launch(options); expect(browser.chromium.wsEndpoint()).toBe(''); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); expect(await page.evaluate('11 * 11')).toBe(121); await page.close(); await browser.close(); @@ -196,7 +196,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p browser.chromium.on('targetcreated', () => events.push('CREATED')); browser.chromium.on('targetchanged', () => events.push('CHANGED')); browser.chromium.on('targetdestroyed', () => events.push('DESTROYED')); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(server.EMPTY_PAGE); await page.close(); expect(events).toEqual(['CREATED', 'CHANGED', 'DESTROYED']); diff --git a/test/chromium/tracing.spec.js b/test/chromium/tracing.spec.js index 435eef51bc..3af62de4aa 100644 --- a/test/chromium/tracing.spec.js +++ b/test/chromium/tracing.spec.js @@ -26,7 +26,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p beforeEach(async function(state) { state.outputFile = path.join(ASSETS_DIR, `trace-${state.parallelIndex}.json`); state.browser = await playwright.launch(defaultBrowserOptions); - state.page = await state.browser.newPage(); + state.page = await state.browser.defaultContext().newPage(); }); afterEach(async function(state) { await state.browser.close(); @@ -52,7 +52,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); it('should throw if tracing on two pages', async({browser, page, server, outputFile}) => { await browser.chromium.startTracing(page, {path: outputFile}); - const newPage = await browser.newPage(); + const newPage = await browser.defaultContext().newPage(); let error = null; await browser.chromium.startTracing(newPage, {path: outputFile}).catch(e => error = e); await newPage.close(); diff --git a/test/defaultbrowsercontext.spec.js b/test/defaultbrowsercontext.spec.js index dd7352df21..b6f2d8e5be 100644 --- a/test/defaultbrowsercontext.spec.js +++ b/test/defaultbrowsercontext.spec.js @@ -23,7 +23,7 @@ module.exports.describe = function ({ testRunner, expect, defaultBrowserOptions, describe('defaultContext()', function() { beforeEach(async state => { state.browser = await playwright.launch(defaultBrowserOptions); - state.page = await state.browser.newPage(); + state.page = await state.browser.defaultContext().newPage(); }); afterEach(async state => { await state.browser.close(); diff --git a/test/firefox/launcher.spec.js b/test/firefox/launcher.spec.js index ab0b996f24..5e5b3e8ea2 100644 --- a/test/firefox/launcher.spec.js +++ b/test/firefox/launcher.spec.js @@ -34,7 +34,7 @@ module.exports.describe = function ({ testRunner, expect, defaultBrowserOptions, const options = Object.assign({userDataDir}, defaultBrowserOptions); const browser = await playwright.launch(options); // Open a page to make sure its functional. - await browser.newPage(); + await browser.defaultContext().newPage(); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); await browser.close(); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); diff --git a/test/launcher.spec.js b/test/launcher.spec.js index 3e8821c3d6..74f7fe6720 100644 --- a/test/launcher.spec.js +++ b/test/launcher.spec.js @@ -32,7 +32,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p describe('Playwright.launch', function() { it('should reject all promises when browser is closed', async() => { const browser = await playwright.launch(defaultBrowserOptions); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); let error = null; const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e); await browser.close(); @@ -47,7 +47,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); it('should have default URL when launching browser', async function() { const browser = await playwright.launch(defaultBrowserOptions); - const pages = (await browser.pages()).map(page => page.url()); + const pages = (await browser.defaultContext().pages()).map(page => page.url()); expect(pages).toEqual(['about:blank']); await browser.close(); }); @@ -55,7 +55,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const options = Object.assign({}, defaultBrowserOptions); options.args = [server.EMPTY_PAGE].concat(options.args || []); const browser = await playwright.launch(options); - const pages = await browser.pages(); + const pages = await browser.defaultContext().pages(); expect(pages.length).toBe(1); const page = pages[0]; if (page.url() !== server.EMPTY_PAGE) { diff --git a/test/page.spec.js b/test/page.spec.js index 196faca824..bb12ccc2b7 100644 --- a/test/page.spec.js +++ b/test/page.spec.js @@ -34,11 +34,11 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF ]); expect(error.message).toContain('Protocol error'); }); - it('should not be visible in browser.pages', async({browser}) => { - const newPage = await browser.newPage(); - expect(await browser.pages()).toContain(newPage); + it('should not be visible in context.pages', async({context}) => { + const newPage = await context.newPage(); + expect(await context.pages()).toContain(newPage); await newPage.close(); - expect(await browser.pages()).not.toContain(newPage); + expect(await context.pages()).not.toContain(newPage); }); it('should run beforeunload if asked for', async({context, server}) => { const newPage = await context.newPage(); diff --git a/test/playwright.spec.js b/test/playwright.spec.js index 2d758e791d..1ae7e56229 100644 --- a/test/playwright.spec.js +++ b/test/playwright.spec.js @@ -99,7 +99,6 @@ module.exports.describe = ({testRunner, product, playwrightPath}) => { }); beforeEach(async(state, test) => { - const pages = []; const contexts = []; const onLine = (line) => test.output += line + '\n'; @@ -111,7 +110,6 @@ module.exports.describe = ({testRunner, product, playwrightPath}) => { } state.tearDown = async () => { - await Promise.all(pages.map(p => p.close())); await Promise.all(contexts.map(c => c.close())); if (!WEBKIT) { rl.removeListener('line', onLine); @@ -126,9 +124,8 @@ module.exports.describe = ({testRunner, product, playwrightPath}) => { }; state.newPage = async (options) => { - const page = await state.browser.newPage(options); - pages.push(page); - return page; + const context = await state.newContext(options); + return await context.newPage(options); }; }); diff --git a/utils/browser/test.js b/utils/browser/test.js index 7e336807d8..5b2363b82b 100644 --- a/utils/browser/test.js +++ b/utils/browser/test.js @@ -36,7 +36,7 @@ afterAll(async state => { }); beforeEach(async state => { - state.page = await state.browser.newPage(); + state.page = await state.browser.defaultContext().newPage(); await state.page.evaluateOnNewDocument(playwrightWeb); await state.page.addScriptTag({ content: playwrightWeb + '\n//# sourceURL=playwright-web.js' @@ -55,7 +55,7 @@ describe('Playwright-Web', () => { await page.evaluate(async(browserWSEndpoint, serverConfig) => { const playwright = require('playwright'); const browser = await playwright.connect({browserWSEndpoint}); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(serverConfig.EMPTY_PAGE); }, browser2.wsEndpoint(), serverConfig); const pageURLs = (await browser2.pages()).map(page => page.url()).sort(); @@ -77,10 +77,10 @@ describe('Playwright-Web', () => { const playwright = require('playwright'); window.cdp.close = () => {}; const browser = await playwright.connect({transport: window.cdp}); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(serverConfig.EMPTY_PAGE); }, serverConfig); - const pageURLs = (await browser.pages()).map(page => page.url()).sort(); + const pageURLs = (await browser.defaultContext().pages()).map(page => page.url()).sort(); expect(pageURLs).toEqual([ 'about:blank', 'about:blank', diff --git a/utils/doclint/check_public_api/test/test.js b/utils/doclint/check_public_api/test/test.js index 46a19d0188..95ba2165dd 100644 --- a/utils/doclint/check_public_api/test/test.js +++ b/utils/doclint/check_public_api/test/test.js @@ -35,7 +35,7 @@ let page; beforeAll(async function() { browser = await playwright.launch(); - page = await browser.newPage(); + page = await browser.defaultContext().newPage(); }); afterAll(async function() { diff --git a/utils/doclint/cli.js b/utils/doclint/cli.js index 2cc10c4989..24741b23a9 100755 --- a/utils/doclint/cli.js +++ b/utils/doclint/cli.js @@ -46,7 +46,7 @@ async function run() { messages.push(...await preprocessor.ensureReleasedAPILinks([readme], VERSION)); const browser = await playwright.launch(); - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); const checkPublicAPI = require('./check_public_api'); const jsSources = await Source.readdir(path.join(PROJECT_DIR, 'src')); messages.push(...await checkPublicAPI(page, mdSources, jsSources)); diff --git a/utils/fetch_devices.js b/utils/fetch_devices.js deleted file mode 100755 index 9d03e9195a..0000000000 --- a/utils/fetch_devices.js +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/env node -/** - * 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 util = require('util'); -const fs = require('fs'); -const path = require('path'); -const playwright = require('..'); -const DEVICES_URL = 'https://raw.githubusercontent.com/ChromeDevTools/devtools-frontend/master/front_end/emulated_devices/module.json'; - -const template = `/** - * 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. - */ - -module.exports = %s; -for (const device of module.exports) - module.exports[device.name] = device; -`; - -const help = `Usage: node ${path.basename(__filename)} [-u ] - -u, --url The URL to load devices descriptor from. If not set, - devices will be fetched from the tip-of-tree of DevTools - frontend. - - -h, --help Show this help message - -Fetch Chrome DevTools front-end emulation devices from given URL, convert them to playwright -devices and save to the . -`; - -const argv = require('minimist')(process.argv.slice(2), { - alias: { u: 'url', h: 'help' }, -}); - -if (argv.help) { - console.log(help); - return; -} - -const url = argv.url || DEVICES_URL; -const outputPath = argv._[0]; -if (!outputPath) { - console.log('ERROR: output file name is missing. Use --help for help.'); - return; -} - -main(url); - -async function main(url) { - const browser = await playwright.launch(); - const chromeVersion = (await browser.version()).split('/').pop(); - await browser.close(); - console.log('GET ' + url); - const text = await httpGET(url); - let json = null; - try { - json = JSON.parse(text); - } catch (e) { - console.error(`FAILED: error parsing response - ${e.message}`); - return; - } - const devicePayloads = json.extensions.filter(extension => extension.type === 'emulated-device').map(extension => extension.device); - let devices = []; - for (const payload of devicePayloads) { - let names = []; - if (payload.title === 'iPhone 6/7/8') - names = ['iPhone 6', 'iPhone 7', 'iPhone 8']; - else if (payload.title === 'iPhone 6/7/8 Plus') - names = ['iPhone 6 Plus', 'iPhone 7 Plus', 'iPhone 8 Plus']; - else if (payload.title === 'iPhone 5/SE') - names = ['iPhone 5', 'iPhone SE']; - else - names = [payload.title]; - for (const name of names) { - const device = createDevice(chromeVersion, name, payload, false); - const landscape = createDevice(chromeVersion, name, payload, true); - devices.push(device); - if (landscape.viewport.width !== device.viewport.width || landscape.viewport.height !== device.viewport.height) - devices.push(landscape); - } - } - devices = devices.filter(device => device.viewport.isMobile); - devices.sort((a, b) => a.name.localeCompare(b.name)); - // Use single-quotes instead of double-quotes to conform with codestyle. - const serialized = JSON.stringify(devices, null, 2) - .replace(/'/g, `\\'`) - .replace(/"/g, `'`); - const result = util.format(template, serialized); - fs.writeFileSync(outputPath, result, 'utf8'); -} - -/** - * @param {string} chromeVersion - * @param {string} deviceName - * @param {*} descriptor - * @param {boolean} landscape - * @return {!Object} - */ -function createDevice(chromeVersion, deviceName, descriptor, landscape) { - const devicePayload = loadFromJSONV1(descriptor); - const viewportPayload = landscape ? devicePayload.horizontal : devicePayload.vertical; - return { - name: deviceName + (landscape ? ' landscape' : ''), - userAgent: devicePayload.userAgent.includes('%s') ? util.format(devicePayload.userAgent, chromeVersion) : devicePayload.userAgent, - viewport: { - width: viewportPayload.width, - height: viewportPayload.height, - deviceScaleFactor: devicePayload.deviceScaleFactor, - isMobile: devicePayload.capabilities.includes('mobile'), - hasTouch: devicePayload.capabilities.includes('touch'), - isLandscape: landscape || false - } - }; -} - -/** - * @param {*} json - * @return {?Object} - */ -function loadFromJSONV1(json) { - /** - * @param {*} object - * @param {string} key - * @param {string} type - * @param {*=} defaultValue - * @return {*} - */ - function parseValue(object, key, type, defaultValue) { - if (typeof object !== 'object' || object === null || !object.hasOwnProperty(key)) { - if (typeof defaultValue !== 'undefined') - return defaultValue; - throw new Error('Emulated device is missing required property \'' + key + '\''); - } - const value = object[key]; - if (typeof value !== type || value === null) - throw new Error('Emulated device property \'' + key + '\' has wrong type \'' + typeof value + '\''); - return value; - } - - /** - * @param {*} object - * @param {string} key - * @return {number} - */ - function parseIntValue(object, key) { - const value = /** @type {number} */ (parseValue(object, key, 'number')); - if (value !== Math.abs(value)) - throw new Error('Emulated device value \'' + key + '\' must be integer'); - return value; - } - - /** - * @param {*} json - * @return {!{width: number, height: number}} - */ - function parseOrientation(json) { - const result = {}; - const minDeviceSize = 50; - const maxDeviceSize = 9999; - result.width = parseIntValue(json, 'width'); - if (result.width < 0 || result.width > maxDeviceSize || - result.width < minDeviceSize) - throw new Error('Emulated device has wrong width: ' + result.width); - - result.height = parseIntValue(json, 'height'); - if (result.height < 0 || result.height > maxDeviceSize || - result.height < minDeviceSize) - throw new Error('Emulated device has wrong height: ' + result.height); - - return /** @type {!{width: number, height: number}} */ (result); - } - - const result = {}; - result.type = /** @type {string} */ (parseValue(json, 'type', 'string')); - result.userAgent = /** @type {string} */ (parseValue(json, 'user-agent', 'string')); - - const capabilities = parseValue(json, 'capabilities', 'object', []); - if (!Array.isArray(capabilities)) - throw new Error('Emulated device capabilities must be an array'); - result.capabilities = []; - for (let i = 0; i < capabilities.length; ++i) { - if (typeof capabilities[i] !== 'string') - throw new Error('Emulated device capability must be a string'); - result.capabilities.push(capabilities[i]); - } - - result.deviceScaleFactor = /** @type {number} */ (parseValue(json['screen'], 'device-pixel-ratio', 'number')); - if (result.deviceScaleFactor < 0 || result.deviceScaleFactor > 100) - throw new Error('Emulated device has wrong deviceScaleFactor: ' + result.deviceScaleFactor); - - result.vertical = parseOrientation(parseValue(json['screen'], 'vertical', 'object')); - result.horizontal = parseOrientation(parseValue(json['screen'], 'horizontal', 'object')); - return result; -} - -/** - * @param {url} - * @return {!Promise} - */ -function httpGET(url) { - let fulfill, reject; - const promise = new Promise((res, rej) => { - fulfill = res; - reject = rej; - }); - const driver = url.startsWith('https://') ? require('https') : require('http'); - const request = driver.get(url, response => { - let data = ''; - response.setEncoding('utf8'); - response.on('data', chunk => data += chunk); - response.on('end', () => fulfill(data)); - response.on('error', reject); - }); - request.on('error', reject); - return promise; -} diff --git a/utils/protocol-types-generator/index.js b/utils/protocol-types-generator/index.js index f8b47e7202..b0ff592db9 100644 --- a/utils/protocol-types-generator/index.js +++ b/utils/protocol-types-generator/index.js @@ -12,16 +12,14 @@ async function generateChromeProtocol(revision) { const playwright = await require('../../chromium'); const browser = await playwright.launch({executablePath: revision.executablePath}); const origin = browser.chromium.wsEndpoint().match(/ws:\/\/([0-9A-Za-z:\.]*)\//)[1]; - const page = await browser.newPage(); + const page = await browser.defaultContext().newPage(); await page.goto(`http://${origin}/json/protocol`); const json = JSON.parse(await page.evaluate(() => document.documentElement.innerText)); - const version = await browser.version(); await browser.close(); fs.writeFileSync(outputPath, jsonToTS(json)); - console.log(`Wrote protocol.ts for ${version} to ${path.relative(process.cwd(), outputPath)}`); + console.log(`Wrote protocol.ts to ${path.relative(process.cwd(), outputPath)}`); } - async function generateWebKitProtocol(revision) { const outputPath = path.join(__dirname, '..', '..', 'src', 'webkit', 'protocol.ts'); if (revision.local && fs.existsSync(outputPath))