mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 21:53:35 +03:00
chore: get rid of page state overrides (#15470)
This commit is contained in:
parent
738d71ebc2
commit
0781d04a5e
@ -98,7 +98,7 @@ export class CRPage implements PageDelegate {
|
||||
const features = opener._nextWindowOpenPopupFeatures.shift() || [];
|
||||
const viewportSize = helper.getViewportSizeFromWindowFeatures(features);
|
||||
if (viewportSize)
|
||||
this._page._state.emulatedSize = { viewport: viewportSize, screen: viewportSize };
|
||||
this._page._emulatedSize = { viewport: viewportSize, screen: viewportSize };
|
||||
}
|
||||
// Note: it is important to call |reportAsNew| before resolving pageOrError promise,
|
||||
// so that anyone who awaits pageOrError got a ready and reported page.
|
||||
@ -199,8 +199,7 @@ export class CRPage implements PageDelegate {
|
||||
await this._forAllFrameSessions(frame => frame._updateHttpCredentials(false));
|
||||
}
|
||||
|
||||
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
|
||||
assert(this._page._state.emulatedSize === emulatedSize);
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
await this._mainFrameSession._updateViewport();
|
||||
}
|
||||
|
||||
@ -972,7 +971,7 @@ class FrameSession {
|
||||
async _updateExtraHTTPHeaders(initial: boolean): Promise<void> {
|
||||
const headers = network.mergeHeaders([
|
||||
this._crPage._browserContext._options.extraHTTPHeaders,
|
||||
this._page._state.extraHTTPHeaders
|
||||
this._page.extraHTTPHeaders()
|
||||
]);
|
||||
if (!initial || headers.length)
|
||||
await this._client.send('Network.setExtraHTTPHeaders', { headers: headersArrayToObject(headers, false /* lowerCase */) });
|
||||
@ -1001,7 +1000,7 @@ class FrameSession {
|
||||
return;
|
||||
assert(this._isMainFrame());
|
||||
const options = this._crPage._browserContext._options;
|
||||
const emulatedSize = this._page._state.emulatedSize;
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (emulatedSize === null)
|
||||
return;
|
||||
const viewportSize = emulatedSize.viewport;
|
||||
@ -1059,16 +1058,17 @@ class FrameSession {
|
||||
}
|
||||
|
||||
async _updateEmulateMedia(initial: boolean): Promise<void> {
|
||||
const colorScheme = this._page._state.colorScheme === null ? '' : this._page._state.colorScheme;
|
||||
const reducedMotion = this._page._state.reducedMotion === null ? '' : this._page._state.reducedMotion;
|
||||
const forcedColors = this._page._state.forcedColors === null ? '' : this._page._state.forcedColors;
|
||||
const emulatedMedia = this._page.emulatedMedia();
|
||||
const colorScheme = emulatedMedia.colorScheme === null ? '' : emulatedMedia.colorScheme;
|
||||
const reducedMotion = emulatedMedia.reducedMotion === null ? '' : emulatedMedia.reducedMotion;
|
||||
const forcedColors = emulatedMedia.forcedColors === null ? '' : emulatedMedia.forcedColors;
|
||||
const features = [
|
||||
{ name: 'prefers-color-scheme', value: colorScheme },
|
||||
{ name: 'prefers-reduced-motion', value: reducedMotion },
|
||||
{ name: 'forced-colors', value: forcedColors },
|
||||
];
|
||||
// Empty string disables the override.
|
||||
await this._client.send('Emulation.setEmulatedMedia', { media: this._page._state.mediaType || '', features });
|
||||
await this._client.send('Emulation.setEmulatedMedia', { media: emulatedMedia.media || '', features });
|
||||
}
|
||||
|
||||
private async _setDefaultFontFamilies(session: CRSession) {
|
||||
@ -1081,7 +1081,7 @@ class FrameSession {
|
||||
}
|
||||
|
||||
async _updateFileChooserInterception(initial: boolean) {
|
||||
const enabled = this._page._state.interceptFileChooser;
|
||||
const enabled = this._page.fileChooserIntercepted();
|
||||
if (initial && !enabled)
|
||||
return;
|
||||
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||
|
@ -20,7 +20,6 @@ import * as dom from '../dom';
|
||||
import type * as frames from '../frames';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import { assert } from '../../utils';
|
||||
import type { PageBinding, PageDelegate } from '../page';
|
||||
import { Page, Worker } from '../page';
|
||||
import type * as types from '../types';
|
||||
@ -352,17 +351,12 @@ export class FFPage implements PageDelegate {
|
||||
}
|
||||
|
||||
async updateExtraHTTPHeaders(): Promise<void> {
|
||||
await this._session.send('Network.setExtraHTTPHeaders', { headers: this._page._state.extraHTTPHeaders || [] });
|
||||
await this._session.send('Network.setExtraHTTPHeaders', { headers: this._page.extraHTTPHeaders() || [] });
|
||||
}
|
||||
|
||||
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
|
||||
assert(this._page._state.emulatedSize === emulatedSize);
|
||||
await this._session.send('Page.setViewportSize', {
|
||||
viewportSize: {
|
||||
width: emulatedSize.viewport.width,
|
||||
height: emulatedSize.viewport.height,
|
||||
},
|
||||
});
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
const viewportSize = this._page.viewportSize();
|
||||
await this._session.send('Page.setViewportSize', { viewportSize });
|
||||
}
|
||||
|
||||
async bringToFront(): Promise<void> {
|
||||
@ -370,12 +364,13 @@ export class FFPage implements PageDelegate {
|
||||
}
|
||||
|
||||
async updateEmulateMedia(): Promise<void> {
|
||||
const colorScheme = this._page._state.colorScheme === null ? undefined : this._page._state.colorScheme;
|
||||
const reducedMotion = this._page._state.reducedMotion === null ? undefined : this._page._state.reducedMotion;
|
||||
const forcedColors = this._page._state.forcedColors === null ? undefined : this._page._state.forcedColors;
|
||||
const emulatedMedia = this._page.emulatedMedia();
|
||||
const colorScheme = emulatedMedia.colorScheme ?? undefined;
|
||||
const reducedMotion = emulatedMedia.reducedMotion ?? undefined;
|
||||
const forcedColors = emulatedMedia.forcedColors ?? undefined;
|
||||
await this._session.send('Page.setEmulatedMedia', {
|
||||
// Empty string means reset.
|
||||
type: this._page._state.mediaType === null ? '' : this._page._state.mediaType,
|
||||
type: emulatedMedia.media === null ? '' : emulatedMedia.media,
|
||||
colorScheme,
|
||||
reducedMotion,
|
||||
forcedColors,
|
||||
|
@ -653,7 +653,7 @@ export class Frame extends SdkObject {
|
||||
private async _gotoAction(progress: Progress, url: string, options: types.GotoOptions): Promise<network.Response | null> {
|
||||
const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
|
||||
progress.log(`navigating to "${url}", waiting until "${waitUntil}"`);
|
||||
const headers = this._page._state.extraHTTPHeaders || [];
|
||||
const headers = this._page.extraHTTPHeaders() || [];
|
||||
const refererHeader = headers.find(h => h.name.toLowerCase() === 'referer');
|
||||
let referer = refererHeader ? refererHeader.value : undefined;
|
||||
if (options.referer !== undefined) {
|
||||
|
@ -65,7 +65,7 @@ export interface PageDelegate {
|
||||
navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise<frames.GotoResult>;
|
||||
|
||||
updateExtraHTTPHeaders(): Promise<void>;
|
||||
setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void>;
|
||||
updateEmulatedViewportSize(): Promise<void>;
|
||||
updateEmulateMedia(): Promise<void>;
|
||||
updateRequestInterception(): Promise<void>;
|
||||
updateFileChooserInterception(enabled: boolean): Promise<void>;
|
||||
@ -98,14 +98,13 @@ export interface PageDelegate {
|
||||
readonly cspErrorsAsynchronousForInlineScipts?: boolean;
|
||||
}
|
||||
|
||||
type PageState = {
|
||||
emulatedSize: { screen: types.Size, viewport: types.Size } | null;
|
||||
mediaType: types.MediaType | null;
|
||||
type EmulatedSize = { screen: types.Size, viewport: types.Size };
|
||||
|
||||
type EmulatedMedia = {
|
||||
media: types.MediaType | null;
|
||||
colorScheme: types.ColorScheme | null;
|
||||
reducedMotion: types.ReducedMotion | null;
|
||||
forcedColors: types.ForcedColors | null;
|
||||
extraHTTPHeaders: types.HeadersArray | null;
|
||||
interceptFileChooser: boolean;
|
||||
};
|
||||
|
||||
type ExpectScreenshotOptions = {
|
||||
@ -152,7 +151,10 @@ export class Page extends SdkObject {
|
||||
readonly touchscreen: input.Touchscreen;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
readonly _delegate: PageDelegate;
|
||||
readonly _state: PageState;
|
||||
_emulatedSize: EmulatedSize | undefined;
|
||||
private _extraHTTPHeaders: types.HeadersArray | undefined;
|
||||
private _emulatedMedia: Partial<EmulatedMedia> = {};
|
||||
private _interceptFileChooser = false;
|
||||
private readonly _pageBindings = new Map<string, PageBinding>();
|
||||
readonly initScripts: string[] = [];
|
||||
readonly _screenshotter: Screenshotter;
|
||||
@ -176,15 +178,6 @@ export class Page extends SdkObject {
|
||||
this.attribution.page = this;
|
||||
this._delegate = delegate;
|
||||
this._browserContext = browserContext;
|
||||
this._state = {
|
||||
emulatedSize: browserContext._options.viewport ? { viewport: browserContext._options.viewport, screen: browserContext._options.screen || browserContext._options.viewport } : null,
|
||||
mediaType: null,
|
||||
colorScheme: browserContext._options.colorScheme !== undefined ? browserContext._options.colorScheme : 'light',
|
||||
reducedMotion: browserContext._options.reducedMotion !== undefined ? browserContext._options.reducedMotion : 'no-preference',
|
||||
forcedColors: browserContext._options.forcedColors !== undefined ? browserContext._options.forcedColors : 'none',
|
||||
extraHTTPHeaders: null,
|
||||
interceptFileChooser: false,
|
||||
};
|
||||
this.accessibility = new accessibility.Accessibility(delegate.getAccessibilityTree.bind(delegate));
|
||||
this.keyboard = new input.Keyboard(delegate.rawKeyboard, this);
|
||||
this.mouse = new input.Mouse(delegate.rawMouse, this);
|
||||
@ -327,10 +320,14 @@ export class Page extends SdkObject {
|
||||
}
|
||||
|
||||
setExtraHTTPHeaders(headers: types.HeadersArray) {
|
||||
this._state.extraHTTPHeaders = headers;
|
||||
this._extraHTTPHeaders = headers;
|
||||
return this._delegate.updateExtraHTTPHeaders();
|
||||
}
|
||||
|
||||
extraHTTPHeaders(): types.HeadersArray | undefined {
|
||||
return this._extraHTTPHeaders;
|
||||
}
|
||||
|
||||
async _onBindingCalled(payload: string, context: dom.FrameExecutionContext) {
|
||||
if (this._disconnected || this._closedState === 'closed')
|
||||
return;
|
||||
@ -402,27 +399,44 @@ export class Page extends SdkObject {
|
||||
}), this._timeoutSettings.navigationTimeout(options));
|
||||
}
|
||||
|
||||
async emulateMedia(options: { media?: types.MediaType | null, colorScheme?: types.ColorScheme | null, reducedMotion?: types.ReducedMotion | null, forcedColors?: types.ForcedColors | null }) {
|
||||
async emulateMedia(options: Partial<EmulatedMedia>) {
|
||||
if (options.media !== undefined)
|
||||
this._state.mediaType = options.media;
|
||||
this._emulatedMedia.media = options.media;
|
||||
if (options.colorScheme !== undefined)
|
||||
this._state.colorScheme = options.colorScheme;
|
||||
this._emulatedMedia.colorScheme = options.colorScheme;
|
||||
if (options.reducedMotion !== undefined)
|
||||
this._state.reducedMotion = options.reducedMotion;
|
||||
this._emulatedMedia.reducedMotion = options.reducedMotion;
|
||||
if (options.forcedColors !== undefined)
|
||||
this._state.forcedColors = options.forcedColors;
|
||||
this._emulatedMedia.forcedColors = options.forcedColors;
|
||||
await this._delegate.updateEmulateMedia();
|
||||
await this._doSlowMo();
|
||||
}
|
||||
|
||||
emulatedMedia(): EmulatedMedia {
|
||||
const contextOptions = this._browserContext._options;
|
||||
return {
|
||||
media: this._emulatedMedia.media || null,
|
||||
colorScheme: this._emulatedMedia.colorScheme !== undefined ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? 'light',
|
||||
reducedMotion: this._emulatedMedia.reducedMotion !== undefined ? this._emulatedMedia.reducedMotion : contextOptions.reducedMotion ?? 'no-preference',
|
||||
forcedColors: this._emulatedMedia.forcedColors !== undefined ? this._emulatedMedia.forcedColors : contextOptions.forcedColors ?? 'none',
|
||||
};
|
||||
}
|
||||
|
||||
async setViewportSize(viewportSize: types.Size) {
|
||||
this._state.emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
|
||||
await this._delegate.setEmulatedSize(this._state.emulatedSize);
|
||||
this._emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
|
||||
await this._delegate.updateEmulatedViewportSize();
|
||||
await this._doSlowMo();
|
||||
}
|
||||
|
||||
viewportSize(): types.Size | null {
|
||||
return this._state.emulatedSize?.viewport || null;
|
||||
return this.emulatedSize()?.viewport || null;
|
||||
}
|
||||
|
||||
emulatedSize(): EmulatedSize | null {
|
||||
if (this._emulatedSize)
|
||||
return this._emulatedSize;
|
||||
const contextOptions = this._browserContext._options;
|
||||
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : null;
|
||||
}
|
||||
|
||||
async bringToFront(): Promise<void> {
|
||||
@ -604,10 +618,14 @@ export class Page extends SdkObject {
|
||||
}
|
||||
|
||||
async setFileChooserIntercepted(enabled: boolean): Promise<void> {
|
||||
this._state.interceptFileChooser = enabled;
|
||||
this._interceptFileChooser = enabled;
|
||||
await this._delegate.updateFileChooserInterception(enabled);
|
||||
}
|
||||
|
||||
fileChooserIntercepted() {
|
||||
return this._interceptFileChooser;
|
||||
}
|
||||
|
||||
frameNavigatedToNewDocument(frame: frames.Frame) {
|
||||
this.emit(Page.Events.InternalFrameNavigatedToNewDocument, frame);
|
||||
const url = frame.url();
|
||||
|
@ -106,7 +106,7 @@ export class WKPage implements PageDelegate {
|
||||
const viewportSize = helper.getViewportSizeFromWindowFeatures(opener._nextWindowOpenPopupFeatures);
|
||||
opener._nextWindowOpenPopupFeatures = undefined;
|
||||
if (viewportSize)
|
||||
this._page._state.emulatedSize = { viewport: viewportSize, screen: viewportSize };
|
||||
this._page._emulatedSize = { viewport: viewportSize, screen: viewportSize };
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,18 +194,20 @@ export class WKPage implements PageDelegate {
|
||||
const contextOptions = this._browserContext._options;
|
||||
if (contextOptions.userAgent)
|
||||
promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent }));
|
||||
if (this._page._state.mediaType || this._page._state.colorScheme || this._page._state.reducedMotion)
|
||||
promises.push(WKPage._setEmulateMedia(session, this._page._state.mediaType, this._page._state.colorScheme, this._page._state.reducedMotion));
|
||||
const emulatedMedia = this._page.emulatedMedia();
|
||||
if (emulatedMedia.media || emulatedMedia.colorScheme || emulatedMedia.reducedMotion)
|
||||
promises.push(WKPage._setEmulateMedia(session, emulatedMedia.media, emulatedMedia.colorScheme, emulatedMedia.reducedMotion));
|
||||
const bootstrapScript = this._calculateBootstrapScript();
|
||||
if (bootstrapScript.length)
|
||||
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript }));
|
||||
this._page.frames().map(frame => frame.evaluateExpression(bootstrapScript, false, undefined).catch(e => {}));
|
||||
if (contextOptions.bypassCSP)
|
||||
promises.push(session.send('Page.setBypassCSP', { enabled: true }));
|
||||
if (this._page._state.emulatedSize) {
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (emulatedSize) {
|
||||
promises.push(session.send('Page.setScreenSizeOverride', {
|
||||
width: this._page._state.emulatedSize.screen.width,
|
||||
height: this._page._state.emulatedSize.screen.height,
|
||||
width: emulatedSize.screen.width,
|
||||
height: emulatedSize.screen.height,
|
||||
}));
|
||||
}
|
||||
promises.push(this.updateEmulateMedia());
|
||||
@ -217,7 +219,7 @@ export class WKPage implements PageDelegate {
|
||||
promises.push(session.send('Page.setTimeZone', { timeZone: contextOptions.timezoneId }).
|
||||
catch(e => { throw new Error(`Invalid timezone ID: ${contextOptions.timezoneId}`); }));
|
||||
}
|
||||
if (this._page._state.interceptFileChooser)
|
||||
if (this._page.fileChooserIntercepted())
|
||||
promises.push(session.send('Page.setInterceptFileChooserDialog', { enabled: true }));
|
||||
promises.push(session.send('Page.overrideSetting', { setting: 'DeviceOrientationEventEnabled' as any, value: contextOptions.isMobile }));
|
||||
promises.push(session.send('Page.overrideSetting', { setting: 'FullScreenEnabled' as any, value: !contextOptions.isMobile }));
|
||||
@ -658,20 +660,20 @@ export class WKPage implements PageDelegate {
|
||||
const locale = this._browserContext._options.locale;
|
||||
const headers = network.mergeHeaders([
|
||||
this._browserContext._options.extraHTTPHeaders,
|
||||
this._page._state.extraHTTPHeaders,
|
||||
this._page.extraHTTPHeaders(),
|
||||
locale ? network.singleHeader('Accept-Language', locale) : undefined,
|
||||
]);
|
||||
return headers;
|
||||
}
|
||||
|
||||
async updateEmulateMedia(): Promise<void> {
|
||||
const colorScheme = this._page._state.colorScheme;
|
||||
const reducedMotion = this._page._state.reducedMotion;
|
||||
await this._forAllSessions(session => WKPage._setEmulateMedia(session, this._page._state.mediaType, colorScheme, reducedMotion));
|
||||
const emulatedMedia = this._page.emulatedMedia();
|
||||
const colorScheme = emulatedMedia.colorScheme;
|
||||
const reducedMotion = emulatedMedia.reducedMotion;
|
||||
await this._forAllSessions(session => WKPage._setEmulateMedia(session, emulatedMedia.media, colorScheme, reducedMotion));
|
||||
}
|
||||
|
||||
async setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void> {
|
||||
assert(this._page._state.emulatedSize === emulatedSize);
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
await this._updateViewport();
|
||||
}
|
||||
|
||||
@ -683,7 +685,7 @@ export class WKPage implements PageDelegate {
|
||||
|
||||
async _updateViewport(): Promise<void> {
|
||||
const options = this._browserContext._options;
|
||||
const deviceSize = this._page._state.emulatedSize;
|
||||
const deviceSize = this._page.emulatedSize();
|
||||
if (deviceSize === null)
|
||||
return;
|
||||
const viewportSize = deviceSize.viewport;
|
||||
@ -725,7 +727,7 @@ export class WKPage implements PageDelegate {
|
||||
}
|
||||
|
||||
async updateFileChooserInterception() {
|
||||
const enabled = this._page._state.interceptFileChooser;
|
||||
const enabled = this._page.fileChooserIntercepted();
|
||||
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user