mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	chore(bidi): set viewport and init script per context (#35247)
This commit is contained in:
		
							parent
							
								
									66b3efa826
								
							
						
					
					
						commit
						54d48c997f
					
				@ -20,7 +20,7 @@ import { BrowserContext, assertBrowserContextIsNotOwned } from '../browserContex
 | 
				
			|||||||
import * as network from '../network';
 | 
					import * as network from '../network';
 | 
				
			||||||
import { BidiConnection } from './bidiConnection';
 | 
					import { BidiConnection } from './bidiConnection';
 | 
				
			||||||
import { bidiBytesValueToString } from './bidiNetworkManager';
 | 
					import { bidiBytesValueToString } from './bidiNetworkManager';
 | 
				
			||||||
import { BidiPage } from './bidiPage';
 | 
					import { addMainBinding, BidiPage, kPlaywrightBindingChannel } from './bidiPage';
 | 
				
			||||||
import * as bidi from './third_party/bidiProtocol';
 | 
					import * as bidi from './third_party/bidiProtocol';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { RegisteredListener } from '../utils/eventsHelper';
 | 
					import type { RegisteredListener } from '../utils/eventsHelper';
 | 
				
			||||||
@ -203,6 +203,7 @@ export class BidiBrowser extends Browser {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export class BidiBrowserContext extends BrowserContext {
 | 
					export class BidiBrowserContext extends BrowserContext {
 | 
				
			||||||
  declare readonly _browser: BidiBrowser;
 | 
					  declare readonly _browser: BidiBrowser;
 | 
				
			||||||
 | 
					  private _initScriptIds: bidi.Script.PreloadScript[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(browser: BidiBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
 | 
					  constructor(browser: BidiBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
 | 
				
			||||||
    super(browser, options, browserContextId);
 | 
					    super(browser, options, browserContextId);
 | 
				
			||||||
@ -213,6 +214,45 @@ export class BidiBrowserContext extends BrowserContext {
 | 
				
			|||||||
    return [...this._browser._bidiPages.values()].filter(bidiPage => bidiPage._browserContext === this);
 | 
					    return [...this._browser._bidiPages.values()].filter(bidiPage => bidiPage._browserContext === this);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override async _initialize() {
 | 
				
			||||||
 | 
					    const promises: Promise<any>[] = [
 | 
				
			||||||
 | 
					      super._initialize(),
 | 
				
			||||||
 | 
					      this._installMainBinding(),
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    // FIXME: Persistent context doesn't have an id, so we can't set the command for it.
 | 
				
			||||||
 | 
					    if (this._options.viewport && this._browserContextId) {
 | 
				
			||||||
 | 
					      promises.push(this._browser._browserSession.send('browsingContext.setViewport', {
 | 
				
			||||||
 | 
					        viewport: {
 | 
				
			||||||
 | 
					          width: this._options.viewport.width,
 | 
				
			||||||
 | 
					          height: this._options.viewport.height
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        devicePixelRatio: this._options.deviceScaleFactor || 1,
 | 
				
			||||||
 | 
					        userContexts: [this._browserContextId],
 | 
				
			||||||
 | 
					      }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    await Promise.all(promises);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // TODO: consider calling this only when bindings are added.
 | 
				
			||||||
 | 
					  private async _installMainBinding() {
 | 
				
			||||||
 | 
					    // TODO: Cannot install main binding for persistent context as it doesn't have an id.
 | 
				
			||||||
 | 
					    if (!this._browserContextId)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    const functionDeclaration = addMainBinding.toString();
 | 
				
			||||||
 | 
					    const args: bidi.Script.ChannelValue[] = [{
 | 
				
			||||||
 | 
					      type: 'channel',
 | 
				
			||||||
 | 
					      value: {
 | 
				
			||||||
 | 
					        channel: kPlaywrightBindingChannel,
 | 
				
			||||||
 | 
					        ownership: bidi.Script.ResultOwnership.Root,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }];
 | 
				
			||||||
 | 
					    await this._browser._browserSession.send('script.addPreloadScript', {
 | 
				
			||||||
 | 
					      functionDeclaration,
 | 
				
			||||||
 | 
					      arguments: args,
 | 
				
			||||||
 | 
					      userContexts: [this._browserContextId],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override possiblyUninitializedPages(): Page[] {
 | 
					  override possiblyUninitializedPages(): Page[] {
 | 
				
			||||||
    return this._bidiPages().map(bidiPage => bidiPage._page);
 | 
					    return this._bidiPages().map(bidiPage => bidiPage._page);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -293,10 +333,22 @@ export class BidiBrowserContext extends BrowserContext {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async doAddInitScript(initScript: InitScript) {
 | 
					  async doAddInitScript(initScript: InitScript) {
 | 
				
			||||||
    await Promise.all(this.pages().map(page => (page._delegate as BidiPage).addInitScript(initScript)));
 | 
					    // TODO: support persistent context.
 | 
				
			||||||
 | 
					    if (!this._browserContextId)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    const { script } = await this._browser._browserSession.send('script.addPreloadScript', {
 | 
				
			||||||
 | 
					      // TODO: remove function call from the source.
 | 
				
			||||||
 | 
					      functionDeclaration: `() => { return ${initScript.source} }`,
 | 
				
			||||||
 | 
					      userContexts: [this._browserContextId],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (!initScript.internal)
 | 
				
			||||||
 | 
					      this._initScriptIds.push(script);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async doRemoveNonInternalInitScripts() {
 | 
					  async doRemoveNonInternalInitScripts() {
 | 
				
			||||||
 | 
					    const promise = Promise.all(this._initScriptIds.map(script => this._browser._browserSession.send('script.removePreloadScript', { script })));
 | 
				
			||||||
 | 
					    this._initScriptIds = [];
 | 
				
			||||||
 | 
					    await promise;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async doUpdateRequestInterception(): Promise<void> {
 | 
					  async doUpdateRequestInterception(): Promise<void> {
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ import type { BidiSession } from './bidiConnection';
 | 
				
			|||||||
import type * as channels from '@protocol/channels';
 | 
					import type * as channels from '@protocol/channels';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
 | 
					const UTILITY_WORLD_NAME = '__playwright_utility_world__';
 | 
				
			||||||
const kPlaywrightBindingChannel = 'playwrightChannel';
 | 
					export const kPlaywrightBindingChannel = 'playwrightChannel';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class BidiPage implements PageDelegate {
 | 
					export class BidiPage implements PageDelegate {
 | 
				
			||||||
  readonly rawMouse: RawMouseImpl;
 | 
					  readonly rawMouse: RawMouseImpl;
 | 
				
			||||||
@ -51,7 +51,7 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
  readonly _browserContext: BidiBrowserContext;
 | 
					  readonly _browserContext: BidiBrowserContext;
 | 
				
			||||||
  readonly _networkManager: BidiNetworkManager;
 | 
					  readonly _networkManager: BidiNetworkManager;
 | 
				
			||||||
  private readonly _pdf: BidiPDF;
 | 
					  private readonly _pdf: BidiPDF;
 | 
				
			||||||
  private _initScriptIds: string[] = [];
 | 
					  private _initScriptIds: bidi.Script.PreloadScript[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(browserContext: BidiBrowserContext, bidiSession: BidiSession, opener: BidiPage | null) {
 | 
					  constructor(browserContext: BidiBrowserContext, bidiSession: BidiSession, opener: BidiPage | null) {
 | 
				
			||||||
    this._session = bidiSession;
 | 
					    this._session = bidiSession;
 | 
				
			||||||
@ -92,7 +92,6 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
    await Promise.all([
 | 
					    await Promise.all([
 | 
				
			||||||
      this.updateHttpCredentials(),
 | 
					      this.updateHttpCredentials(),
 | 
				
			||||||
      this.updateRequestInterception(),
 | 
					      this.updateRequestInterception(),
 | 
				
			||||||
      this._updateViewport(),
 | 
					 | 
				
			||||||
      this._installMainBinding(),
 | 
					      this._installMainBinding(),
 | 
				
			||||||
      this._addAllInitScripts(),
 | 
					      this._addAllInitScripts(),
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
@ -258,10 +257,6 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
  async updateEmulateMedia(): Promise<void> {
 | 
					  async updateEmulateMedia(): Promise<void> {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async updateEmulatedViewportSize(): Promise<void> {
 | 
					 | 
				
			||||||
    await this._updateViewport();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  async updateUserAgent(): Promise<void> {
 | 
					  async updateUserAgent(): Promise<void> {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -271,7 +266,7 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async _updateViewport(): Promise<void> {
 | 
					  async updateEmulatedViewportSize(): Promise<void> {
 | 
				
			||||||
    const options = this._browserContext._options;
 | 
					    const options = this._browserContext._options;
 | 
				
			||||||
    const deviceSize = this._page.emulatedSize();
 | 
					    const deviceSize = this._page.emulatedSize();
 | 
				
			||||||
    if (deviceSize === null)
 | 
					    if (deviceSize === null)
 | 
				
			||||||
@ -328,7 +323,11 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: consider calling this only when bindings are added.
 | 
					  // TODO: consider calling this only when bindings are added.
 | 
				
			||||||
 | 
					  // TODO: delete this method once we can add preload script for persistent context.
 | 
				
			||||||
  private async _installMainBinding() {
 | 
					  private async _installMainBinding() {
 | 
				
			||||||
 | 
					    // For non-persistent context, the main binding is installed during context creation.
 | 
				
			||||||
 | 
					    if (this._browserContext._browserContextId)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
    const functionDeclaration = addMainBinding.toString();
 | 
					    const functionDeclaration = addMainBinding.toString();
 | 
				
			||||||
    const args: bidi.Script.ChannelValue[] = [{
 | 
					    const args: bidi.Script.ChannelValue[] = [{
 | 
				
			||||||
      type: 'channel',
 | 
					      type: 'channel',
 | 
				
			||||||
@ -573,7 +572,7 @@ export class BidiPage implements PageDelegate {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function addMainBinding(callback: (arg: any) => void) {
 | 
					export function addMainBinding(callback: (arg: any) => void) {
 | 
				
			||||||
  (globalThis as any)['__playwright__binding__'] = callback;
 | 
					  (globalThis as any)['__playwright__binding__'] = callback;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user