diff --git a/src/Browser.js b/src/Browser.js deleted file mode 100644 index 3aae1963d6674..0000000000000 --- a/src/Browser.js +++ /dev/null @@ -1,386 +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. - */ - -const {helper, assert} = require('./helper'); -const {Target} = require('./Target'); -const EventEmitter = require('events'); -const {TaskQueue} = require('./TaskQueue'); -const {Events} = require('./Events'); -// Used as a TypeDef -// eslint-disable-next-line no-unused-vars -const {Connection} = require('./Connection'); - -class Browser extends EventEmitter { - /** - * @param {!Connection} connection - * @param {!Array} contextIds - * @param {boolean} ignoreHTTPSErrors - * @param {?Puppeteer.Viewport} defaultViewport - * @param {?Puppeteer.ChildProcess} process - * @param {function()=} closeCallback - */ - static async create(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) { - const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback); - await connection.send('Target.setDiscoverTargets', {discover: true}); - return browser; - } - - /** - * @param {!Connection} connection - * @param {!Array} contextIds - * @param {boolean} ignoreHTTPSErrors - * @param {?Puppeteer.Viewport} defaultViewport - * @param {?Puppeteer.ChildProcess} process - * @param {(function():Promise)=} closeCallback - */ - constructor(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) { - super(); - this._ignoreHTTPSErrors = ignoreHTTPSErrors; - this._defaultViewport = defaultViewport; - this._process = process; - this._screenshotTaskQueue = new TaskQueue(); - this._connection = connection; - this._closeCallback = closeCallback || new Function(); - - this._defaultContext = new BrowserContext(this._connection, this, null); - /** @type {Map} */ - this._contexts = new Map(); - for (const contextId of contextIds) - this._contexts.set(contextId, new BrowserContext(this._connection, this, contextId)); - - /** @type {Map} */ - this._targets = new Map(); - this._connection.on(Events.Connection.Disconnected, () => this.emit(Events.Browser.Disconnected)); - this._connection.on('Target.targetCreated', this._targetCreated.bind(this)); - this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this)); - this._connection.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this)); - } - - /** - * @return {?Puppeteer.ChildProcess} - */ - process() { - return this._process; - } - - /** - * @return {!Promise} - */ - async createIncognitoBrowserContext() { - const {browserContextId} = await this._connection.send('Target.createBrowserContext'); - const context = new BrowserContext(this._connection, this, browserContextId); - this._contexts.set(browserContextId, context); - return context; - } - - /** - * @return {!Array} - */ - browserContexts() { - return [this._defaultContext, ...Array.from(this._contexts.values())]; - } - - /** - * @return {!BrowserContext} - */ - defaultBrowserContext() { - return this._defaultContext; - } - - /** - * @param {?string} contextId - */ - async _disposeContext(contextId) { - await this._connection.send('Target.disposeBrowserContext', {browserContextId: contextId || undefined}); - this._contexts.delete(contextId); - } - - /** - * @param {!Protocol.Target.targetCreatedPayload} event - */ - async _targetCreated(event) { - const targetInfo = event.targetInfo; - const {browserContextId} = targetInfo; - const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId) : this._defaultContext; - - const target = new Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue); - assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated'); - this._targets.set(event.targetInfo.targetId, target); - - if (await target._initializedPromise) { - this.emit(Events.Browser.TargetCreated, target); - context.emit(Events.BrowserContext.TargetCreated, target); - } - } - - /** - * @param {{targetId: string}} event - */ - async _targetDestroyed(event) { - const target = this._targets.get(event.targetId); - target._initializedCallback(false); - this._targets.delete(event.targetId); - target._closedCallback(); - if (await target._initializedPromise) { - this.emit(Events.Browser.TargetDestroyed, target); - target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target); - } - } - - /** - * @param {!Protocol.Target.targetInfoChangedPayload} event - */ - _targetInfoChanged(event) { - const target = this._targets.get(event.targetInfo.targetId); - assert(target, 'target should exist before targetInfoChanged'); - const previousURL = target.url(); - const wasInitialized = target._isInitialized; - target._targetInfoChanged(event.targetInfo); - if (wasInitialized && previousURL !== target.url()) { - this.emit(Events.Browser.TargetChanged, target); - target.browserContext().emit(Events.BrowserContext.TargetChanged, target); - } - } - - /** - * @return {string} - */ - wsEndpoint() { - return this._connection.url(); - } - - /** - * @return {!Promise} - */ - async newPage() { - return this._defaultContext.newPage(); - } - - /** - * @param {?string} contextId - * @return {!Promise} - */ - async _createPageInContext(contextId) { - const {targetId} = await this._connection.send('Target.createTarget', {url: 'about:blank', browserContextId: contextId || undefined}); - const target = await this._targets.get(targetId); - assert(await target._initializedPromise, 'Failed to create target for page'); - const page = await target.page(); - return page; - } - - /** - * @return {!Array} - */ - targets() { - return Array.from(this._targets.values()).filter(target => target._isInitialized); - } - - /** - * @return {!Target} - */ - target() { - return this.targets().find(target => target.type() === 'browser'); - } - - /** - * @param {function(!Target):boolean} predicate - * @param {{timeout?: number}=} options - * @return {!Promise} - */ - async waitForTarget(predicate, options = {}) { - const { - timeout = 30000 - } = options; - const existingTarget = this.targets().find(predicate); - if (existingTarget) - return existingTarget; - let resolve; - const targetPromise = new Promise(x => resolve = x); - this.on(Events.Browser.TargetCreated, check); - this.on(Events.Browser.TargetChanged, check); - try { - if (!timeout) - return await targetPromise; - return await helper.waitWithTimeout(targetPromise, 'target', timeout); - } finally { - this.removeListener(Events.Browser.TargetCreated, check); - this.removeListener(Events.Browser.TargetChanged, check); - } - - /** - * @param {!Target} target - */ - function check(target) { - if (predicate(target)) - resolve(target); - } - } - - /** - * @return {!Promise>} - */ - async pages() { - const contextPages = await Promise.all(this.browserContexts().map(context => context.pages())); - // Flatten array. - return contextPages.reduce((acc, x) => acc.concat(x), []); - } - - /** - * @return {!Promise} - */ - async version() { - const version = await this._getVersion(); - return version.product; - } - - /** - * @return {!Promise} - */ - async userAgent() { - const version = await this._getVersion(); - return version.userAgent; - } - - async close() { - await this._closeCallback.call(null); - this.disconnect(); - } - - disconnect() { - this._connection.dispose(); - } - - /** - * @return {boolean} - */ - isConnected() { - return !this._connection._closed; - } - - /** - * @return {!Promise} - */ - _getVersion() { - return this._connection.send('Browser.getVersion'); - } -} - -class BrowserContext extends EventEmitter { - /** - * @param {!Connection} connection - * @param {!Browser} browser - * @param {?string} contextId - */ - constructor(connection, browser, contextId) { - super(); - this._connection = connection; - this._browser = browser; - this._id = contextId; - } - - /** - * @return {!Array} target - */ - targets() { - return this._browser.targets().filter(target => target.browserContext() === this); - } - - /** - * @param {function(!Target):boolean} predicate - * @param {{timeout?: number}=} options - * @return {!Promise} - */ - waitForTarget(predicate, options) { - return this._browser.waitForTarget(target => target.browserContext() === this && predicate(target), options); - } - - /** - * @return {!Promise>} - */ - async pages() { - const pages = await Promise.all( - this.targets() - .filter(target => target.type() === 'page') - .map(target => target.page()) - ); - return pages.filter(page => !!page); - } - - /** - * @return {boolean} - */ - isIncognito() { - return !!this._id; - } - - /** - * @param {string} origin - * @param {!Array} permissions - */ - async overridePermissions(origin, permissions) { - const webPermissionToProtocol = new Map([ - ['geolocation', 'geolocation'], - ['midi', 'midi'], - ['notifications', 'notifications'], - ['push', 'push'], - ['camera', 'videoCapture'], - ['microphone', 'audioCapture'], - ['background-sync', 'backgroundSync'], - ['ambient-light-sensor', 'sensors'], - ['accelerometer', 'sensors'], - ['gyroscope', 'sensors'], - ['magnetometer', 'sensors'], - ['accessibility-events', 'accessibilityEvents'], - ['clipboard-read', 'clipboardReadWrite'], - ['clipboard-write', 'clipboardReadWrite'], - ['payment-handler', 'paymentHandler'], - // chrome-specific permissions we have. - ['midi-sysex', 'midiSysex'], - ]); - 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._id || undefined, permissions}); - } - - async clearPermissionOverrides() { - await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined}); - } - - /** - * @return {!Promise} - */ - newPage() { - return this._browser._createPageInContext(this._id); - } - - /** - * @return {!Browser} - */ - browser() { - return this._browser; - } - - async close() { - assert(this._id, 'Non-incognito profiles cannot be closed!'); - await this._browser._disposeContext(this._id); - } -} - -module.exports = {Browser, BrowserContext}; diff --git a/src/Browser.ts b/src/Browser.ts new file mode 100644 index 0000000000000..b9aae8cd6ef23 --- /dev/null +++ b/src/Browser.ts @@ -0,0 +1,312 @@ +/** + * 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. + */ + +import {helper, assert} from './helper'; +import {Target} from './Target'; +import * as EventEmitter from 'events'; +import {TaskQueue} from './TaskQueue'; +import {Events} from './Events'; +import {Connection} from './Connection'; + +type BrowserCloseCallback = () => Promise | void; + +/* TODO(jacktfranklin): once Target is migrated to TS + * we can import + use its type here. But right now Target + * is implemented in JS so we can't import the type and have to use + * Puppeteer.Target + */ + +export class Browser extends EventEmitter { + static async create(connection: Connection, contextIds: string[], ignoreHTTPSErrors: boolean, defaultViewport?: Puppeteer.Viewport, process?: Puppeteer.ChildProcess, closeCallback?: BrowserCloseCallback): Promise { + const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback); + await connection.send('Target.setDiscoverTargets', {discover: true}); + return browser; + } + _ignoreHTTPSErrors: boolean; + _defaultViewport?: Puppeteer.Viewport; + _process?: Puppeteer.ChildProcess; + _screenshotTaskQueue = new TaskQueue(); + _connection: Connection; + _closeCallback: BrowserCloseCallback; + _defaultContext: BrowserContext; + _contexts: Map; + // TODO: once Target is in TypeScript we can type this properly. + _targets: Map; + + constructor(connection: Connection, contextIds: string[], ignoreHTTPSErrors: boolean, defaultViewport?: Puppeteer.Viewport, process?: Puppeteer.ChildProcess, closeCallback?: BrowserCloseCallback) { + super(); + this._ignoreHTTPSErrors = ignoreHTTPSErrors; + this._defaultViewport = defaultViewport; + this._process = process; + this._screenshotTaskQueue = new TaskQueue(); + this._connection = connection; + this._closeCallback = closeCallback || function(): void {}; + + this._defaultContext = new BrowserContext(this._connection, this, null); + this._contexts = new Map(); + for (const contextId of contextIds) + this._contexts.set(contextId, new BrowserContext(this._connection, this, contextId)); + + this._targets = new Map(); + this._connection.on(Events.Connection.Disconnected, () => this.emit(Events.Browser.Disconnected)); + this._connection.on('Target.targetCreated', this._targetCreated.bind(this)); + this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this)); + this._connection.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this)); + } + + process(): Puppeteer.ChildProcess | null { + return this._process; + } + + async createIncognitoBrowserContext(): Promise { + const {browserContextId} = await this._connection.send('Target.createBrowserContext'); + const context = new BrowserContext(this._connection, this, browserContextId); + this._contexts.set(browserContextId, context); + return context; + } + + browserContexts(): BrowserContext[] { + return [this._defaultContext, ...Array.from(this._contexts.values())]; + } + + defaultBrowserContext(): BrowserContext { + return this._defaultContext; + } + + /** + * @param {?string} contextId + */ + async _disposeContext(contextId?: string): Promise { + await this._connection.send('Target.disposeBrowserContext', {browserContextId: contextId || undefined}); + this._contexts.delete(contextId); + } + + async _targetCreated(event: Protocol.Target.targetCreatedPayload): Promise { + const targetInfo = event.targetInfo; + const {browserContextId} = targetInfo; + const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId) : this._defaultContext; + + const target = new Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue); + assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated'); + this._targets.set(event.targetInfo.targetId, target); + + if (await target._initializedPromise) { + this.emit(Events.Browser.TargetCreated, target); + context.emit(Events.BrowserContext.TargetCreated, target); + } + } + + /** + * @param {{targetId: string}} event + */ + async _targetDestroyed(event: { targetId: string}): Promise { + const target = this._targets.get(event.targetId); + target._initializedCallback(false); + this._targets.delete(event.targetId); + target._closedCallback(); + if (await target._initializedPromise) { + this.emit(Events.Browser.TargetDestroyed, target); + target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target); + } + } + + /** + * @param {!Protocol.Target.targetInfoChangedPayload} event + */ + _targetInfoChanged(event: Protocol.Target.targetInfoChangedPayload): void { + const target = this._targets.get(event.targetInfo.targetId); + assert(target, 'target should exist before targetInfoChanged'); + const previousURL = target.url(); + const wasInitialized = target._isInitialized; + target._targetInfoChanged(event.targetInfo); + if (wasInitialized && previousURL !== target.url()) { + this.emit(Events.Browser.TargetChanged, target); + target.browserContext().emit(Events.BrowserContext.TargetChanged, target); + } + } + + wsEndpoint(): string { + return this._connection.url(); + } + + async newPage(): Promise { + return this._defaultContext.newPage(); + } + + async _createPageInContext(contextId?: string): Promise { + const {targetId} = await this._connection.send('Target.createTarget', {url: 'about:blank', browserContextId: contextId || undefined}); + const target = await this._targets.get(targetId); + assert(await target._initializedPromise, 'Failed to create target for page'); + const page = await target.page(); + return page; + } + + targets(): Puppeteer.Target[] { + return Array.from(this._targets.values()).filter(target => target._isInitialized); + } + + target(): Puppeteer.Target { + return this.targets().find(target => target.type() === 'browser'); + } + + /** + * @param {function(!Target):boolean} predicate + * @param {{timeout?: number}=} options + * @return {!Promise} + */ + async waitForTarget(predicate: (x: Puppeteer.Target) => boolean, options: { timeout?: number} = {}): Promise { + const { + timeout = 30000 + } = options; + const existingTarget = this.targets().find(predicate); + if (existingTarget) + return existingTarget; + let resolve; + const targetPromise = new Promise(x => resolve = x); + this.on(Events.Browser.TargetCreated, check); + this.on(Events.Browser.TargetChanged, check); + try { + if (!timeout) + return await targetPromise; + return await helper.waitWithTimeout(targetPromise, 'target', timeout); + } finally { + this.removeListener(Events.Browser.TargetCreated, check); + this.removeListener(Events.Browser.TargetChanged, check); + } + + function check(target: Puppeteer.Target): void { + if (predicate(target)) + resolve(target); + } + } + + /** + * @return {!Promise>} + */ + 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(): Promise { + await this._closeCallback.call(null); + this.disconnect(); + } + + disconnect(): void { + this._connection.dispose(); + } + + isConnected(): boolean { + return !this._connection._closed; + } + + _getVersion(): Promise { + return this._connection.send('Browser.getVersion'); + } +} + +export class BrowserContext extends EventEmitter { + _connection: Connection; + _browser: Browser; + _id?: string; + + constructor(connection: Connection, browser: Browser, contextId?: string) { + super(); + this._connection = connection; + this._browser = browser; + this._id = contextId; + } + + targets(): Puppeteer.Target[] { + return this._browser.targets().filter(target => target.browserContext() === this); + } + + waitForTarget(predicate: (x: Puppeteer.Target) => boolean, options: { timeout?: number}): Promise { + return this._browser.waitForTarget(target => target.browserContext() === this && predicate(target), options); + } + + async pages(): Promise { + const pages = await Promise.all( + this.targets() + .filter(target => target.type() === 'page') + .map(target => target.page()) + ); + return pages.filter(page => !!page); + } + + isIncognito(): boolean { + return !!this._id; + } + + async overridePermissions(origin: string, permissions: Protocol.Browser.PermissionType[]): Promise { + const webPermissionToProtocol = new Map([ + ['geolocation', 'geolocation'], + ['midi', 'midi'], + ['notifications', 'notifications'], + // TODO: push isn't a valid type? + // ['push', 'push'], + ['camera', 'videoCapture'], + ['microphone', 'audioCapture'], + ['background-sync', 'backgroundSync'], + ['ambient-light-sensor', 'sensors'], + ['accelerometer', 'sensors'], + ['gyroscope', 'sensors'], + ['magnetometer', 'sensors'], + ['accessibility-events', 'accessibilityEvents'], + ['clipboard-read', 'clipboardReadWrite'], + ['clipboard-write', 'clipboardReadWrite'], + ['payment-handler', 'paymentHandler'], + // chrome-specific permissions we have. + ['midi-sysex', 'midiSysex'], + ]); + 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._id || undefined, permissions}); + } + + async clearPermissionOverrides(): Promise { + await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined}); + } + + newPage(): Promise { + return this._browser._createPageInContext(this._id); + } + + browser(): Browser { + return this._browser; + } + + async close(): Promise { + assert(this._id, 'Non-incognito profiles cannot be closed!'); + await this._browser._disposeContext(this._id); + } +} diff --git a/src/Connection.ts b/src/Connection.ts index 04329d1336b0d..f6bc2e4e02010 100644 --- a/src/Connection.ts +++ b/src/Connection.ts @@ -72,7 +72,7 @@ export class Connection extends EventEmitter { return this._url; } - send(method: string, params = {}): Promise { + send(method: T, params?: Protocol.CommandParameters[T]): Promise { const id = this._rawSend({method, params}); return new Promise((resolve, reject) => { this._callbacks.set(id, {resolve, reject, error: new Error(), method}); @@ -147,7 +147,7 @@ export class Connection extends EventEmitter { * @return {!Promise} */ async createSession(targetInfo: Protocol.Target.TargetInfo): Promise { - const {sessionId} = await this.send('Target.attachToTarget', {targetId: targetInfo.targetId, flatten: true}); + const {sessionId} = await this.send('Target.attachToTarget', {targetId: targetInfo.targetId, flatten: true}); return this._sessions.get(sessionId); } } diff --git a/src/Page.js b/src/Page.js index f1382a5b3d7d3..71bde110198a0 100644 --- a/src/Page.js +++ b/src/Page.js @@ -31,6 +31,9 @@ const {Coverage} = require('./Coverage'); const {Worker: PuppeteerWorker} = require('./Worker'); // Import used as typedef // eslint-disable-next-line no-unused-vars +const {Browser, BrowserContext} = require('./Browser'); +// Import used as typedef +// eslint-disable-next-line no-unused-vars const {createJSHandle, JSHandle, ElementHandle} = require('./JSHandle'); const {Accessibility} = require('./Accessibility'); const {TimeoutSettings} = require('./TimeoutSettings'); @@ -204,14 +207,14 @@ class Page extends EventEmitter { } /** - * @return {!Puppeteer.Browser} + * @return {!Browser} */ browser() { return this._target.browser(); } /** - * @return {!Puppeteer.BrowserContext} + * @return {!BrowserContext} */ browserContext() { return this._target.browserContext(); diff --git a/src/Puppeteer.js b/src/Puppeteer.js index f8b6f81509b90..8f84cacfc5999 100644 --- a/src/Puppeteer.js +++ b/src/Puppeteer.js @@ -17,6 +17,9 @@ const Launcher = require('./Launcher'); const {BrowserFetcher} = require('./BrowserFetcher'); const Errors = require('./Errors'); const DeviceDescriptors = require('./DeviceDescriptors'); +// Import used as typedef +// eslint-disable-next-line no-unused-vars +const {Browser} = require('./Browser'); module.exports = class { /** @@ -35,7 +38,7 @@ module.exports = class { /** * @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions & {product?: string, extraPrefsFirefox?: !object})=} options - * @return {!Promise} + * @return {!Promise} */ launch(options = {}) { if (options.product) @@ -45,7 +48,7 @@ module.exports = class { /** * @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport}) & {product?: string}=} options - * @return {!Promise} + * @return {!Promise} */ connect(options) { if (options.product) diff --git a/src/Target.js b/src/Target.js index 54825c2c5aca4..ad3a98dceb957 100644 --- a/src/Target.js +++ b/src/Target.js @@ -24,11 +24,14 @@ const {CDPSession} = require('./Connection'); // understand that unfortunately. // eslint-disable-next-line no-unused-vars const {TaskQueue} = require('./TaskQueue'); +// Import used as typedef +// eslint-disable-next-line no-unused-vars +const {Browser, BrowserContext} = require('./Browser'); class Target { /** * @param {!Protocol.Target.TargetInfo} targetInfo - * @param {!Puppeteer.BrowserContext} browserContext + * @param {!BrowserContext} browserContext * @param {!function():!Promise} sessionFactory * @param {boolean} ignoreHTTPSErrors * @param {?Puppeteer.Viewport} defaultViewport @@ -115,14 +118,14 @@ class Target { } /** - * @return {!Puppeteer.Browser} + * @return {!Browser} */ browser() { return this._browserContext.browser(); } /** - * @return {!Puppeteer.BrowserContext} + * @return {!BrowserContext} */ browserContext() { return this._browserContext; diff --git a/src/TaskQueue.ts b/src/TaskQueue.ts index d459d0550f5b5..e3b8f1549ca9d 100644 --- a/src/TaskQueue.ts +++ b/src/TaskQueue.ts @@ -19,7 +19,7 @@ * to make this into TaskQueue and let the caller tell us what types * the promise in the queue should return. */ -class TaskQueue { +export class TaskQueue { _chain: Promise; constructor() { @@ -32,5 +32,3 @@ class TaskQueue { return result; } } - -export = {TaskQueue}; diff --git a/src/externs.d.ts b/src/externs.d.ts index 0fa4f3c515eea..171fa23ffff85 100644 --- a/src/externs.d.ts +++ b/src/externs.d.ts @@ -1,4 +1,3 @@ -import { Browser as RealBrowser, BrowserContext as RealBrowserContext} from './Browser.js'; import {Target as RealTarget} from './Target.js'; import {Page as RealPage} from './Page.js'; import {Frame as RealFrame, FrameManager as RealFrameManager} from './FrameManager.js'; @@ -7,8 +6,6 @@ import { NetworkManager as RealNetworkManager, Request as RealRequest, Response import * as child_process from 'child_process'; declare global { module Puppeteer { - export class Browser extends RealBrowser {} - export class BrowserContext extends RealBrowserContext {} export class Target extends RealTarget {} export class Frame extends RealFrame {} export class FrameManager extends RealFrameManager {} diff --git a/test/oopif.spec.js b/test/oopif.spec.js index cc048c9540e7c..7ce0c3a12e1c9 100644 --- a/test/oopif.spec.js +++ b/test/oopif.spec.js @@ -64,7 +64,7 @@ describeChromeOnly('OOPIF', function() { /** - * @param {!Puppeteer.BrowserContext} context + * @param {!BrowserContext} context */ function oopifs(context) { return context.targets().filter(target => target._targetInfo.type === 'iframe'); diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index ef1de7c4557e4..958f9a59c88ab 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -335,6 +335,10 @@ function compareDocumentations(actual, expected) { actualName: '"load"|"domcontentloaded"|"networkidle0"|"networkidle2"|Array', expectedName: '"load"|"domcontentloaded"|"networkidle0"|"networkidle2"|Array' }], + ['Method BrowserContext.overridePermissions() permissions', { + actualName: 'Array', + expectedName: 'Array' + }], ]); const expectedForSource = expectedNamingMismatches.get(source);