diff --git a/core/lib/GlobalPool.ts b/core/lib/GlobalPool.ts index 518bf328e..a0a1e7c87 100644 --- a/core/lib/GlobalPool.ts +++ b/core/lib/GlobalPool.ts @@ -158,6 +158,7 @@ export default class GlobalPool { sessionId: session.id, }), session.getMitmProxy(), + session.useIncognitoContext(), ); await session.initialize(browserContext); diff --git a/core/lib/Session.ts b/core/lib/Session.ts index f63a519da..c4d57537e 100644 --- a/core/lib/Session.ts +++ b/core/lib/Session.ts @@ -294,12 +294,17 @@ export default class Session }; } + public useIncognitoContext(): boolean { + const options = this.options; + return !(options.showBrowser === true && options.sessionKeepAlive === true); + } + public async registerWithMitm( sharedMitmProxy: MitmProxy, doesPuppetSupportBrowserContextProxy: boolean, ): Promise { let mitmProxy = sharedMitmProxy; - if (doesPuppetSupportBrowserContextProxy) { + if (doesPuppetSupportBrowserContextProxy && this.useIncognitoContext()) { this.isolatedMitmProxy = await MitmProxy.start(GlobalPool.localProxyPortStart, Core.dataDir); mitmProxy = this.isolatedMitmProxy; } diff --git a/interfaces/IDevtoolsSession.ts b/interfaces/IDevtoolsSession.ts index 2cde0ae3e..7627fec84 100644 --- a/interfaces/IDevtoolsSession.ts +++ b/interfaces/IDevtoolsSession.ts @@ -2,6 +2,7 @@ import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping'; import Protocol from 'devtools-protocol'; import ITypedEventEmitter from '@ulixee/commons/interfaces/ITypedEventEmitter'; import { FilterFlags, FilterOutFlags } from './AllowedNames'; +import RemoteObject = Protocol.Runtime.RemoteObject; export declare type DevtoolsEvents = { [Key in keyof ProtocolMapping.Events]: ProtocolMapping.Events[Key][0]; @@ -16,6 +17,8 @@ type RequiredParamsCommands = keyof FilterOutFlags, 'waitOn'> { id: string; + disposeRemoteObject(object: RemoteObject): void; + send( method: T, params: DevtoolsCommandParams[T], diff --git a/interfaces/IPuppetBrowser.ts b/interfaces/IPuppetBrowser.ts index 374fbb9df..7ebeb920c 100644 --- a/interfaces/IPuppetBrowser.ts +++ b/interfaces/IPuppetBrowser.ts @@ -14,6 +14,7 @@ export default interface IPuppetBrowser { plugins: ICorePlugins, logger: IBoundLog, proxy?: IProxyConnectionOptions, + isIncognito?: boolean, ): Promise; close(): Promise; } diff --git a/interfaces/IPuppetContext.ts b/interfaces/IPuppetContext.ts index 20abcc4c3..f3f1f5034 100644 --- a/interfaces/IPuppetContext.ts +++ b/interfaces/IPuppetContext.ts @@ -33,6 +33,7 @@ export interface IPuppetPageOptions { export interface IPuppetContextEvents { page: { page: IPuppetPage }; worker: { worker: IPuppetWorker }; + close: void; 'devtools-message': { direction: 'send' | 'receive'; timestamp: Date; diff --git a/plugins/default-browser-emulator/index.ts b/plugins/default-browser-emulator/index.ts index 57be9b7c4..13b7b11b5 100644 --- a/plugins/default-browser-emulator/index.ts +++ b/plugins/default-browser-emulator/index.ts @@ -41,8 +41,8 @@ import configureDeviceProfile from './lib/helpers/configureDeviceProfile'; import configureHttp2Session from './lib/helpers/configureHttp2Session'; const dataLoader = new DataLoader(__dirname); -export const latestBrowserEngineId = 'chrome-88-0'; -export const latestChromeBrowserVersion = { major: '88', minor: '0' }; +export const latestBrowserEngineId = 'chrome-89-0'; +export const latestChromeBrowserVersion = { major: '89', minor: '0' }; @BrowserEmulatorClassDecorator export default class DefaultBrowserEmulator extends BrowserEmulator { diff --git a/plugins/default-browser-emulator/package.json b/plugins/default-browser-emulator/package.json index 52a886619..8c679098d 100644 --- a/plugins/default-browser-emulator/package.json +++ b/plugins/default-browser-emulator/package.json @@ -4,7 +4,7 @@ "description": "Browser emulator generated from DoubleAgent data", "main": "index.js", "dependencies": { - "@ulixee/chrome-88-0": "^4324.182.4", + "@ulixee/chrome-89-0": "^4389.128.4", "@ulixee/commons": "1.5.5", "@ulixee/hero-interfaces": "1.5.4", "@ulixee/hero-plugin-utils": "1.5.4", diff --git a/puppet-chrome/lib/Browser.ts b/puppet-chrome/lib/Browser.ts index f26e26dbe..399c1ccd8 100755 --- a/puppet-chrome/lib/Browser.ts +++ b/puppet-chrome/lib/Browser.ts @@ -20,10 +20,8 @@ const { log } = Log(module); let browserIdCounter = 0; export class Browser extends TypedEventEmitter implements IPuppetBrowser { - public readonly browserContextsById = new Map(); public readonly devtoolsSession: DevtoolsSession; public onDevtoolsAttached?: (session: DevtoolsSession) => Promise; - public id: string; public get name(): string { @@ -38,11 +36,16 @@ export class Browser extends TypedEventEmitter implements IPuppe return this.fullVersion?.split('.').map(Number).shift(); } + private readonly browserContextsById = new Map(); + private readonly connection: Connection; private readonly closeCallback: () => void; private version: GetVersionResponse; + private get defaultBrowserContext(): BrowserContext { + return this.browserContextsById.get(undefined); + } constructor(connection: Connection, closeCallback: () => void) { super(); @@ -63,6 +66,7 @@ export class Browser extends TypedEventEmitter implements IPuppe plugins: ICorePlugins, logger: IBoundLog, proxy?: IProxyConnectionOptions, + isIncognito = true, ): Promise { const proxySettings = proxy?.address ? { @@ -70,13 +74,25 @@ export class Browser extends TypedEventEmitter implements IPuppe proxyServer: proxy.address, } : {}; + if (!isIncognito) { + if (!this.browserContextsById.has(undefined)) { + this.createBrowserContext(undefined, plugins, logger, proxy); + } + const context = this.browserContextsById.get(undefined); + context.proxy = proxy; + return context; + } + // Creates a new incognito browser context. This won't share cookies/cache with other browser contexts. const { browserContextId } = await this.devtoolsSession.send('Target.createBrowserContext', { disposeOnDetach: true, ...proxySettings, }); + return this.createBrowserContext(browserContextId, plugins, logger, proxy); + } - return new BrowserContext(this, plugins, browserContextId, logger, proxy); + public getBrowserContext(id: string) { + return this.browserContextsById.get(id) ?? this.defaultBrowserContext; } public async close(): Promise { @@ -108,20 +124,18 @@ export class Browser extends TypedEventEmitter implements IPuppe private onAttachedToTarget(event: Protocol.Target.AttachedToTargetEvent) { const { targetInfo, sessionId } = event; - if (!targetInfo.browserContextId) { - assert(targetInfo.browserContextId, `targetInfo: ${JSON.stringify(targetInfo, null, 2)}`); - } + assert(targetInfo.browserContextId, `targetInfo: ${JSON.stringify(targetInfo, null, 2)}`); if (targetInfo.type === 'page') { const devtoolsSession = this.connection.getSession(sessionId); - const context = this.browserContextsById.get(targetInfo.browserContextId); + const context = this.getBrowserContext(targetInfo.browserContextId); context?.onPageAttached(devtoolsSession, targetInfo).catch(() => null); return; } if (targetInfo.type === 'shared_worker') { const devtoolsSession = this.connection.getSession(sessionId); - const context = this.browserContextsById.get(targetInfo.browserContextId); + const context = this.getBrowserContext(targetInfo.browserContextId); context?.onSharedWorkerAttached(devtoolsSession, targetInfo).catch(() => null); } @@ -156,11 +170,11 @@ export class Browser extends TypedEventEmitter implements IPuppe private async onTargetCreated(event: Protocol.Target.TargetCreatedEvent) { const { targetInfo } = event; if (targetInfo.type === 'page' && !targetInfo.attached) { - const context = this.browserContextsById.get(targetInfo.browserContextId); + const context = this.getBrowserContext(targetInfo.browserContextId); await context?.attachToTarget(targetInfo.targetId); } if (targetInfo.type === 'shared_worker') { - const context = this.browserContextsById.get(targetInfo.browserContextId); + const context = this.getBrowserContext(targetInfo.browserContextId); await context?.attachToWorker(targetInfo); } } @@ -188,6 +202,19 @@ export class Browser extends TypedEventEmitter implements IPuppe } } + private createBrowserContext( + browserContextId: string, + plugins: ICorePlugins, + logger: IBoundLog, + proxy?: IProxyConnectionOptions, + ) { + const context = new BrowserContext(this, plugins, browserContextId, logger, proxy); + this.browserContextsById.set(browserContextId, context); + context.on('close', () => this.browserContextsById.delete(browserContextId)); + + return context; + } + public static async create( connection: Connection, browserEngine: IBrowserEngine, diff --git a/puppet-chrome/lib/BrowserContext.ts b/puppet-chrome/lib/BrowserContext.ts index 3415e8891..c90ad14cb 100644 --- a/puppet-chrome/lib/BrowserContext.ts +++ b/puppet-chrome/lib/BrowserContext.ts @@ -74,7 +74,6 @@ export class BrowserContext browserContextId: contextId, }); this.proxy = proxy; - this.browser.browserContextsById.set(this.id, this); this.subscribeToDevtoolsMessages(this.browser.devtoolsSession, { sessionType: 'browser', @@ -227,15 +226,17 @@ export class BrowserContext if (this.browser.devtoolsSession.isConnected()) { await Promise.all([...this.pagesById.values()].map(x => x.close())); - await this.sendWithBrowserDevtoolsSession('Target.disposeBrowserContext', { - browserContextId: this.id, - }).catch(err => { - if (err instanceof CanceledPromiseError) return; - throw err; - }); + if (this.id) { + await this.sendWithBrowserDevtoolsSession('Target.disposeBrowserContext', { + browserContextId: this.id, + }).catch(err => { + if (err instanceof CanceledPromiseError) return; + throw err; + }); + } } removeEventListeners(this.eventListeners); - this.browser.browserContextsById.delete(this.id); + this.emit('close'); } async getCookies(url?: URL): Promise { diff --git a/puppet-chrome/lib/Frame.ts b/puppet-chrome/lib/Frame.ts index 0d01cef60..73471ed52 100644 --- a/puppet-chrome/lib/Frame.ts +++ b/puppet-chrome/lib/Frame.ts @@ -342,12 +342,12 @@ export default class Frame extends TypedEventEmitter impleme public removeContextId(executionContextId: number): void { if (this.defaultContextId === executionContextId) this.defaultContextId = null; - if (this.isolatedContextId === executionContextId) this.defaultContextId = null; + if (this.isolatedContextId === executionContextId) this.isolatedContextId = null; } public clearContextIds(): void { this.defaultContextId = null; - this.defaultContextId = null; + this.isolatedContextId = null; } public addContextId(executionContextId: number, isDefault: boolean): void { diff --git a/puppet/index.ts b/puppet/index.ts index da4326c06..9f6502d77 100644 --- a/puppet/index.ts +++ b/puppet/index.ts @@ -18,7 +18,7 @@ const { log } = Log(module); let puppBrowserCounter = 1; export default class Puppet extends TypedEventEmitter<{ close: void }> { public get browserId(): string { - return this.browser.id; + return this.browser?.id; } public readonly id: number; @@ -79,12 +79,13 @@ export default class Puppet extends TypedEventEmitter<{ close: void }> { plugins: ICorePlugins, logger: IBoundLog, proxy?: IProxyConnectionOptions, + isIncognito = true, ): Promise { if (!this.isStarted || !this.browser) { throw new Error('This Puppet instance has not had start() called on it'); } if (this.isShuttingDown) throw new Error('Shutting down'); - return this.browser.newContext(plugins, logger, proxy); + return this.browser.newContext(plugins, logger, proxy, isIncognito); } public async close() { diff --git a/yarn.lock b/yarn.lock index 2160fdf1e..7b2e87dc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2145,10 +2145,10 @@ "@typescript-eslint/types" "4.28.3" eslint-visitor-keys "^2.0.0" -"@ulixee/chrome-88-0@^4324.182.4": - version "4324.182.4" - resolved "https://registry.yarnpkg.com/@ulixee/chrome-88-0/-/chrome-88-0-4324.182.4.tgz#b5de2e5e8569a380b6bff99074ef8d66c6bbb686" - integrity sha512-HZBSbZEVjWyjnkj/UYbnYd8dvHiXroeGPNGG3anOLHIW8dIDVnPtdwJXD/7Kcm6hUXVmZY2q3w1y5i8L94V9uQ== +"@ulixee/chrome-89-0@^4389.128.4": + version "4389.128.4" + resolved "https://registry.yarnpkg.com/@ulixee/chrome-89-0/-/chrome-89-0-4389.128.4.tgz#a71f9739078c90d93e97bb26a2eac145ce397a45" + integrity sha512-BmoLbzC2ACmep5pAXnpK2HvvWbjeMxsum/9PDsyzdVlHzJ3HbdTVZuaqPrJ5h12ZYZbEK9PYlamy9twaaulDfA== dependencies: "@ulixee/chrome-app" "^1.0.2"