Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(firefox): support Browser.target() #4028

Merged
merged 2 commits into from Feb 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
65 changes: 35 additions & 30 deletions experimental/puppeteer-firefox/lib/Browser.js
Expand Up @@ -31,8 +31,8 @@ class Browser extends EventEmitter {
this._process = process;
this._closeCallback = closeCallback;

/** @type {!Map<string, ?Target>} */
this._pageTargets = new Map();
/** @type {!Map<string, !Target>} */
this._targets = new Map();

this._defaultContext = new BrowserContext(this._connection, this, null);
/** @type {!Map<string, !BrowserContext>} */
Expand All @@ -43,9 +43,9 @@ class Browser extends EventEmitter {
this._connection.on(Events.Connection.Disconnected, () => this.emit(Events.Browser.Disconnected));

this._eventListeners = [
helper.addEventListener(this._connection, 'Browser.tabOpened', this._onTabOpened.bind(this)),
helper.addEventListener(this._connection, 'Browser.tabClosed', this._onTabClosed.bind(this)),
helper.addEventListener(this._connection, 'Browser.tabNavigated', this._onTabNavigated.bind(this)),
helper.addEventListener(this._connection, 'Browser.targetCreated', this._onTargetCreated.bind(this)),
helper.addEventListener(this._connection, 'Browser.targetDestroyed', this._onTargetDestroyed.bind(this)),
helper.addEventListener(this._connection, 'Browser.targetInfoChanged', this._onTargetInfoChanged.bind(this)),
];
}

Expand Down Expand Up @@ -152,29 +152,32 @@ class Browser extends EventEmitter {
* @return {Promise<Page>}
*/
async _createPageInContext(browserContextId) {
const {pageId} = await this._connection.send('Browser.newPage', {
const {targetId} = await this._connection.send('Browser.newPage', {
browserContextId: browserContextId || undefined
});
const target = this._pageTargets.get(pageId);
const target = this._targets.get(targetId);
return await target.page();
}

async pages() {
const pageTargets = Array.from(this._pageTargets.values());
const pageTargets = Array.from(this._targets.values()).filter(target => target.type() === 'page');
return await Promise.all(pageTargets.map(target => target.page()));
}

targets() {
return Array.from(this._pageTargets.values());
return Array.from(this._targets.values());
}

async _onTabOpened({pageId, url, browserContextId, openerId}) {
target() {
return this.targets().find(target => target.type() === 'browser');
}

async _onTargetCreated({targetId, url, browserContextId, openerId, type}) {
const context = browserContextId ? this._contexts.get(browserContextId) : this._defaultContext;
const opener = openerId ? this._pageTargets.get(openerId) : null;
const target = new Target(this._connection, this, context, pageId, url, opener);
this._pageTargets.set(pageId, target);
if (opener && opener._pagePromise) {
const openerPage = await opener._pagePromise;
const target = new Target(this._connection, this, context, targetId, type, url, openerId);
this._targets.set(targetId, target);
if (target.opener() && target.opener()._pagePromise) {
const openerPage = await target.opener()._pagePromise;
if (openerPage.listenerCount(Events.Page.Popup)) {
const popupPage = await target.page();
openerPage.emit(Events.Page.Popup, popupPage);
Expand All @@ -184,15 +187,15 @@ class Browser extends EventEmitter {
context.emit(Events.BrowserContext.TargetCreated, target);
}

_onTabClosed({pageId}) {
const target = this._pageTargets.get(pageId);
this._pageTargets.delete(pageId);
_onTargetDestroyed({targetId}) {
const target = this._targets.get(targetId);
this._targets.delete(targetId);
this.emit(Events.Browser.TargetDestroyed, target);
target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target);
}

_onTabNavigated({pageId, url}) {
const target = this._pageTargets.get(pageId);
_onTargetInfoChanged({targetId, url}) {
const target = this._targets.get(targetId);
target._url = url;
this.emit(Events.Browser.TargetChanged, target);
target.browserContext().emit(Events.BrowserContext.TargetChanged, target);
Expand All @@ -210,33 +213,35 @@ class Target {
* @param {*} connection
* @param {!Browser} browser
* @param {!BrowserContext} context
* @param {string} pageId
* @param {string} targetId
* @param {string} type
* @param {string} url
* @param {?Target} opener
* @param {string=} openerId
*/
constructor(connection, browser, context, pageId, url, opener) {
constructor(connection, browser, context, targetId, type, url, openerId) {
this._browser = browser;
this._context = context;
this._connection = connection;
this._pageId = pageId;
this._targetId = targetId;
this._type = type;
/** @type {?Promise<!Page>} */
this._pagePromise = null;
this._url = url;
this._opener = opener;
this._openerId = openerId;
}

/**
* @return {?Target}
*/
opener() {
return this._opener;
return this._openerId ? this._browser._targets.get(this._openerId) : null;
}

/**
* @return {"page"|"background_page"|"service_worker"|"other"|"browser"}
* @return {"page"|"browser"}
*/
type() {
return 'page';
return this._type;
}

url() {
Expand All @@ -251,8 +256,8 @@ class Target {
}

async page() {
if (!this._pagePromise)
this._pagePromise = Page.create(this._connection, this, this._pageId, this._browser._defaultViewport);
if (this._type === 'page' && !this._pagePromise)
this._pagePromise = Page.create(this._connection, this, this._targetId, this._browser._defaultViewport);
return this._pagePromise;
}

Expand Down
16 changes: 8 additions & 8 deletions experimental/puppeteer-firefox/lib/Page.js
Expand Up @@ -19,14 +19,14 @@ const writeFileAsync = util.promisify(fs.writeFile);
* @internal
*/
class PageSession extends EventEmitter {
constructor(connection, pageId) {
constructor(connection, targetId) {
super();
this._connection = connection;
this._pageId = pageId;
this._targetId = targetId;
const wrapperSymbol = Symbol('listenerWrapper');

function wrapperListener(listener, params) {
if (params.pageId === pageId)
if (params.targetId === targetId)
listener.call(null, params);
}

Expand All @@ -41,7 +41,7 @@ class PageSession extends EventEmitter {
}

async send(method, params = {}) {
params = Object.assign({}, params, {pageId: this._pageId});
params = Object.assign({}, params, {targetId: this._targetId});
return await this._connection.send(method, params);
}
}
Expand All @@ -51,11 +51,11 @@ class Page extends EventEmitter {
*
* @param {!Puppeteer.Connection} connection
* @param {!Puppeteer.Target} target
* @param {string} pageId
* @param {string} targetId
* @param {?Puppeteer.Viewport} defaultViewport
*/
static async create(connection, target, pageId, defaultViewport) {
const session = new PageSession(connection, pageId);
static async create(connection, target, targetId, defaultViewport) {
const session = new PageSession(connection, targetId);
const page = new Page(session, target);
await session.send('Page.enable');
if (defaultViewport)
Expand All @@ -82,7 +82,7 @@ class Page extends EventEmitter {
helper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)),
helper.addEventListener(this._session, 'Page.console', this._onConsole.bind(this)),
helper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)),
helper.addEventListener(this._session, 'Browser.tabClosed', this._onClosed.bind(this)),
helper.addEventListener(this._session, 'Browser.targetDestroyed', this._onClosed.bind(this)),
helper.addEventListener(this._frameManager, Events.FrameManager.Load, () => this.emit(Events.Page.Load)),
helper.addEventListener(this._frameManager, Events.FrameManager.DOMContentLoaded, () => this.emit(Events.Page.DOMContentLoaded)),
helper.addEventListener(this._frameManager, Events.FrameManager.FrameAttached, frame => this.emit(Events.Page.FrameAttached, frame)),
Expand Down
2 changes: 1 addition & 1 deletion experimental/puppeteer-firefox/package.json
Expand Up @@ -9,7 +9,7 @@
"node": ">=8.9.4"
},
"puppeteer": {
"firefox_revision": "10282bfac697c69a6fdfeec4cddae7caf98e1969"
"firefox_revision": "2ede4ae19f39ec7a1b73162a6004235908260dfe"
},
"scripts": {
"install": "node install.js",
Expand Down
2 changes: 1 addition & 1 deletion test/browser.spec.js
Expand Up @@ -20,7 +20,7 @@ module.exports.addTests = function({testRunner, expect, headless, puppeteer}) {
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;

describe('Browser.target', function() {
it_fails_ffox('should return browser target', async({browser}) => {
it('should return browser target', async({browser}) => {
const target = browser.target();
expect(target.type()).toBe('browser');
});
Expand Down
4 changes: 2 additions & 2 deletions test/target.spec.js
Expand Up @@ -24,7 +24,7 @@ module.exports.addTests = function({testRunner, expect, puppeteer, Errors}) {
const {TimeoutError} = Errors;

describe('Target', function() {
it_fails_ffox('Browser.targets should return all of the targets', async({page, server, browser}) => {
it('Browser.targets should return all of the targets', async({page, server, browser}) => {
// The pages will be the testing page and the original newtab page
const targets = browser.targets();
expect(targets.some(target => target.type() === 'page' &&
Expand All @@ -38,7 +38,7 @@ module.exports.addTests = function({testRunner, expect, puppeteer, Errors}) {
expect(allPages).toContain(page);
expect(allPages[0]).not.toBe(allPages[1]);
});
it_fails_ffox('should contain browser target', async({browser}) => {
it('should contain browser target', async({browser}) => {
const targets = browser.targets();
const browserTarget = targets.find(target => target.type() === 'browser');
expect(browserTarget).toBeTruthy();
Expand Down