feat(context): remove the notion of incognito context (#299)

This commit is contained in:
Pavel Feldman 2019-12-18 16:44:02 -08:00 committed by Dmitry Gozman
parent da051a72a8
commit 0e3328218d
6 changed files with 42 additions and 59 deletions

View File

@ -44,7 +44,6 @@
* [browserContext.clearCookies()](#browsercontextclearcookies)
* [browserContext.close()](#browsercontextclose)
* [browserContext.cookies([...urls])](#browsercontextcookiesurls)
* [browserContext.isIncognito()](#browsercontextisincognito)
* [browserContext.newPage()](#browsercontextnewpage)
* [browserContext.overrides](#browsercontextoverrides)
* [browserContext.pages()](#browsercontextpages)
@ -736,12 +735,6 @@ will be closed.
If no URLs are specified, this method returns all cookies.
If URLs are specified, only cookies that affect those URLs are returned.
#### browserContext.isIncognito()
- returns: <[boolean]>
Returns whether BrowserContext is incognito.
The default browser context is the only non-incognito browser context.
> **NOTE** the default browser context cannot be closed.
#### browserContext.newPage()

View File

@ -15,19 +15,18 @@
* limitations under the License.
*/
import { assert } from './helper';
import { Page } from './page';
import * as input from './input';
import * as network from './network';
import * as types from './types';
export interface BrowserDelegate {
contextPages(): Promise<Page[]>;
createPageInContext(): Promise<Page>;
closeContext(): Promise<void>;
getContextCookies(): Promise<network.NetworkCookie[]>;
clearContextCookies(): Promise<void>;
setContextCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
export interface BrowserContextDelegate {
pages(): Promise<Page[]>;
newPage(): Promise<Page>;
close(): Promise<void>;
cookies(): Promise<network.NetworkCookie[]>;
clearCookies(): Promise<void>;
setCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
}
export type BrowserContextOptions = {
@ -42,34 +41,28 @@ export type BrowserContextOptions = {
};
export class BrowserContext {
private readonly _delegate: BrowserDelegate;
private readonly _isIncognito: boolean;
private readonly _delegate: BrowserContextDelegate;
readonly _options: BrowserContextOptions;
private _closed = false;
constructor(delegate: BrowserDelegate, isIncognito: boolean, options: BrowserContextOptions) {
constructor(delegate: BrowserContextDelegate, options: BrowserContextOptions) {
this._delegate = delegate;
this._isIncognito = isIncognito;
this._options = options;
if (!options.viewport && options.viewport !== null)
options.viewport = { width: 800, height: 600 };
}
async pages(): Promise<Page[]> {
return this._delegate.contextPages();
}
isIncognito(): boolean {
return this._isIncognito;
return this._delegate.pages();
}
async newPage(): Promise<Page> {
return this._delegate.createPageInContext();
return this._delegate.newPage();
}
async _createOwnerPage(): Promise<Page> {
try {
const page = await this._delegate.createPageInContext();
const page = await this._delegate.newPage();
page._isContextOwner = true;
return page;
} catch (e) {
@ -79,22 +72,21 @@ export class BrowserContext {
}
async cookies(...urls: string[]): Promise<network.NetworkCookie[]> {
return network.filterCookies(await this._delegate.getContextCookies(), urls);
return network.filterCookies(await this._delegate.cookies(), urls);
}
async clearCookies() {
await this._delegate.clearContextCookies();
await this._delegate.clearCookies();
}
async setCookies(cookies: network.SetNetworkCookieParam[]) {
await this._delegate.setContextCookies(network.rewriteCookies(cookies));
await this._delegate.setCookies(network.rewriteCookies(cookies));
}
async close() {
if (this._closed)
return;
assert(this._isIncognito, 'Non-incognito profiles cannot be closed!');
await this._delegate.closeContext();
await this._delegate.close();
this._closed = true;
}
}

View File

@ -73,16 +73,15 @@ export class Browser extends EventEmitter {
}
_createBrowserContext(contextId: string | null, options: BrowserContextOptions): BrowserContext {
const isIncognito = !!contextId;
let overrides: Overrides | null = null;
const context = new BrowserContext({
contextPages: async (): Promise<Page[]> => {
pages: async (): Promise<Page[]> => {
const targets = this._allTargets().filter(target => target.browserContext() === context && target.type() === 'page');
const pages = await Promise.all(targets.map(target => target.page()));
return pages.filter(page => !!page);
},
createPageInContext: async (): Promise<Page> => {
newPage: async (): Promise<Page> => {
const { targetId } = await this._client.send('Target.createTarget', { url: 'about:blank', browserContextId: contextId || undefined });
const target = this._targets.get(targetId);
assert(await target._initializedPromise, 'Failed to create target for page');
@ -109,12 +108,13 @@ export class Browser extends EventEmitter {
return page;
},
closeContext: async (): Promise<void> => {
close: async (): Promise<void> => {
assert(contextId, 'Non-incognito profiles cannot be closed!');
await this._client.send('Target.disposeBrowserContext', {browserContextId: contextId || undefined});
this._contexts.delete(contextId);
},
getContextCookies: async (): Promise<network.NetworkCookie[]> => {
cookies: async (): Promise<network.NetworkCookie[]> => {
const { cookies } = await this._client.send('Storage.getCookies', { browserContextId: contextId || undefined });
return cookies.map(c => {
const copy: any = { sameSite: 'None', ...c };
@ -124,14 +124,14 @@ export class Browser extends EventEmitter {
});
},
clearContextCookies: async (): Promise<void> => {
clearCookies: async (): Promise<void> => {
await this._client.send('Storage.clearCookies', { browserContextId: contextId || undefined });
},
setContextCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
setCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
await this._client.send('Storage.setCookies', { cookies, browserContextId: contextId || undefined });
},
}, isIncognito, options);
}, options);
overrides = new Overrides(context);
(context as any).permissions = new Permissions(this._client, contextId);
(context as any).overrides = overrides;

View File

@ -16,7 +16,7 @@
*/
import { EventEmitter } from 'events';
import { helper, RegisteredListener } from '../helper';
import { helper, RegisteredListener, assert } from '../helper';
import { Connection, ConnectionEvents, JugglerSessionEvents } from './Connection';
import { Events } from './events';
import { Events as CommonEvents } from '../events';
@ -175,15 +175,14 @@ export class Browser extends EventEmitter {
}
_createBrowserContext(browserContextId: string | null, options: BrowserContextOptions): BrowserContext {
const isIncognito = !!browserContextId;
const context = new BrowserContext({
contextPages: async (): Promise<Page[]> => {
pages: async (): Promise<Page[]> => {
const targets = this._allTargets().filter(target => target.browserContext() === context && target.type() === 'page');
const pages = await Promise.all(targets.map(target => target.page()));
return pages.filter(page => !!page);
},
createPageInContext: async (): Promise<Page> => {
newPage: async (): Promise<Page> => {
const {targetId} = await this._connection.send('Target.newPage', {
browserContextId: browserContextId || undefined
});
@ -205,12 +204,13 @@ export class Browser extends EventEmitter {
return page;
},
closeContext: async (): Promise<void> => {
close: async (): Promise<void> => {
assert(browserContextId, 'Non-incognito profiles cannot be closed!');
await this._connection.send('Target.removeBrowserContext', { browserContextId });
this._contexts.delete(browserContextId);
},
getContextCookies: async (): Promise<network.NetworkCookie[]> => {
cookies: async (): Promise<network.NetworkCookie[]> => {
const { cookies } = await this._connection.send('Browser.getCookies', { browserContextId: browserContextId || undefined });
return cookies.map(c => {
const copy: any = { ... c };
@ -219,14 +219,14 @@ export class Browser extends EventEmitter {
});
},
clearContextCookies: async (): Promise<void> => {
clearCookies: async (): Promise<void> => {
await this._connection.send('Browser.clearCookies', { browserContextId: browserContextId || undefined });
},
setContextCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
setCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
await this._connection.send('Browser.setCookies', { browserContextId: browserContextId || undefined, cookies });
},
}, isIncognito, options);
}, options);
(context as any).permissions = new Permissions(this._connection, browserContextId);
return context;
}

View File

@ -17,7 +17,7 @@
import * as childProcess from 'child_process';
import { EventEmitter } from 'events';
import { helper, RegisteredListener, debugError } from '../helper';
import { helper, RegisteredListener, debugError, assert } from '../helper';
import * as network from '../network';
import { Connection, ConnectionEvents, TargetSession } from './Connection';
import { Page } from '../page';
@ -209,26 +209,26 @@ export class Browser extends EventEmitter {
}
_createBrowserContext(browserContextId: string | undefined, options: BrowserContextOptions): BrowserContext {
const isIncognito = !!browserContextId;
const context = new BrowserContext({
contextPages: async (): Promise<Page[]> => {
pages: async (): Promise<Page[]> => {
const targets = this.targets().filter(target => target._browserContext === context && target._type === 'page');
const pages = await Promise.all(targets.map(target => target.page()));
return pages.filter(page => !!page);
},
createPageInContext: async (): Promise<Page> => {
newPage: async (): Promise<Page> => {
const { targetId } = await this._connection.send('Browser.createPage', { browserContextId });
const target = this._targets.get(targetId);
return await target.page();
},
closeContext: async (): Promise<void> => {
close: async (): Promise<void> => {
assert(browserContextId, 'Non-incognito profiles cannot be closed!');
await this._connection.send('Browser.deleteContext', { browserContextId });
this._contexts.delete(browserContextId);
},
getContextCookies: async (): Promise<network.NetworkCookie[]> => {
cookies: async (): Promise<network.NetworkCookie[]> => {
const { cookies } = await this._connection.send('Browser.getAllCookies', { browserContextId });
return cookies.map((c: network.NetworkCookie) => ({
...c,
@ -236,15 +236,15 @@ export class Browser extends EventEmitter {
}));
},
clearContextCookies: async (): Promise<void> => {
clearCookies: async (): Promise<void> => {
await this._connection.send('Browser.deleteAllCookies', { browserContextId });
},
setContextCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
setCookies: async (cookies: network.SetNetworkCookieParam[]): Promise<void> => {
const cc = cookies.map(c => ({ ...c, session: c.expires === -1 || c.expires === undefined })) as Protocol.Browser.SetCookieParam[];
await this._connection.send('Browser.setCookies', { cookies: cc, browserContextId });
},
}, isIncognito, options);
}, options);
return context;
}
}

View File

@ -26,7 +26,6 @@ module.exports.addTests = function({testRunner, expect, playwright, WEBKIT}) {
it('should have default context', async function({browser, server}) {
expect(browser.browserContexts().length).toBe(1);
const defaultContext = browser.browserContexts()[0];
expect(defaultContext.isIncognito()).toBe(false);
let error = null;
await defaultContext.close().catch(e => error = e);
expect(browser.defaultContext()).toBe(defaultContext);
@ -35,7 +34,6 @@ module.exports.addTests = function({testRunner, expect, playwright, WEBKIT}) {
it('should create new incognito context', async function({browser, newContext}) {
expect(browser.browserContexts().length).toBe(1);
const context = await newContext();
expect(context.isIncognito()).toBe(true);
expect(browser.browserContexts().length).toBe(2);
expect(browser.browserContexts().indexOf(context) !== -1).toBe(true);
await context.close();