mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: move more things to emulation manager (#10390)
This commit is contained in:
parent
ca4ab96812
commit
e4110746f1
@ -15,6 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
import {Protocol} from 'devtools-protocol';
|
import {Protocol} from 'devtools-protocol';
|
||||||
|
|
||||||
|
import {GeolocationOptions, MediaFeature} from '../api/Page.js';
|
||||||
|
import {assert} from '../util/assert.js';
|
||||||
|
import {isErrorLike} from '../util/ErrorLike.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
import {Viewport} from './PuppeteerViewport.js';
|
import {Viewport} from './PuppeteerViewport.js';
|
||||||
|
|
||||||
@ -25,11 +29,16 @@ export class EmulationManager {
|
|||||||
#client: CDPSession;
|
#client: CDPSession;
|
||||||
#emulatingMobile = false;
|
#emulatingMobile = false;
|
||||||
#hasTouch = false;
|
#hasTouch = false;
|
||||||
|
#javascriptEnabled = true;
|
||||||
|
|
||||||
constructor(client: CDPSession) {
|
constructor(client: CDPSession) {
|
||||||
this.#client = client;
|
this.#client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get javascriptEnabled(): boolean {
|
||||||
|
return this.#javascriptEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
async emulateViewport(viewport: Viewport): Promise<boolean> {
|
async emulateViewport(viewport: Viewport): Promise<boolean> {
|
||||||
const mobile = viewport.isMobile || false;
|
const mobile = viewport.isMobile || false;
|
||||||
const width = viewport.width;
|
const width = viewport.width;
|
||||||
@ -60,4 +69,149 @@ export class EmulationManager {
|
|||||||
this.#hasTouch = hasTouch;
|
this.#hasTouch = hasTouch;
|
||||||
return reloadNeeded;
|
return reloadNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async emulateIdleState(overrides?: {
|
||||||
|
isUserActive: boolean;
|
||||||
|
isScreenUnlocked: boolean;
|
||||||
|
}): Promise<void> {
|
||||||
|
if (overrides) {
|
||||||
|
await this.#client.send('Emulation.setIdleOverride', {
|
||||||
|
isUserActive: overrides.isUserActive,
|
||||||
|
isScreenUnlocked: overrides.isScreenUnlocked,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await this.#client.send('Emulation.clearIdleOverride');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async emulateTimezone(timezoneId?: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
await this.#client.send('Emulation.setTimezoneOverride', {
|
||||||
|
timezoneId: timezoneId || '',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (isErrorLike(error) && error.message.includes('Invalid timezone')) {
|
||||||
|
throw new Error(`Invalid timezone ID: ${timezoneId}`);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async emulateVisionDeficiency(
|
||||||
|
type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type']
|
||||||
|
): Promise<void> {
|
||||||
|
const visionDeficiencies = new Set<
|
||||||
|
Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type']
|
||||||
|
>([
|
||||||
|
'none',
|
||||||
|
'achromatopsia',
|
||||||
|
'blurredVision',
|
||||||
|
'deuteranopia',
|
||||||
|
'protanopia',
|
||||||
|
'tritanopia',
|
||||||
|
]);
|
||||||
|
try {
|
||||||
|
assert(
|
||||||
|
!type || visionDeficiencies.has(type),
|
||||||
|
`Unsupported vision deficiency: ${type}`
|
||||||
|
);
|
||||||
|
await this.#client.send('Emulation.setEmulatedVisionDeficiency', {
|
||||||
|
type: type || 'none',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async emulateCPUThrottling(factor: number | null): Promise<void> {
|
||||||
|
assert(
|
||||||
|
factor === null || factor >= 1,
|
||||||
|
'Throttling rate should be greater or equal to 1'
|
||||||
|
);
|
||||||
|
await this.#client.send('Emulation.setCPUThrottlingRate', {
|
||||||
|
rate: factor ?? 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async emulateMediaFeatures(features?: MediaFeature[]): Promise<void> {
|
||||||
|
if (!features) {
|
||||||
|
await this.#client.send('Emulation.setEmulatedMedia', {});
|
||||||
|
}
|
||||||
|
if (Array.isArray(features)) {
|
||||||
|
for (const mediaFeature of features) {
|
||||||
|
const name = mediaFeature.name;
|
||||||
|
assert(
|
||||||
|
/^(?:prefers-(?:color-scheme|reduced-motion)|color-gamut)$/.test(
|
||||||
|
name
|
||||||
|
),
|
||||||
|
'Unsupported media feature: ' + name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await this.#client.send('Emulation.setEmulatedMedia', {
|
||||||
|
features: features,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async emulateMediaType(type?: string): Promise<void> {
|
||||||
|
assert(
|
||||||
|
type === 'screen' ||
|
||||||
|
type === 'print' ||
|
||||||
|
(type ?? undefined) === undefined,
|
||||||
|
'Unsupported media type: ' + type
|
||||||
|
);
|
||||||
|
await this.#client.send('Emulation.setEmulatedMedia', {
|
||||||
|
media: type || '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async setGeolocation(options: GeolocationOptions): Promise<void> {
|
||||||
|
const {longitude, latitude, accuracy = 0} = options;
|
||||||
|
if (longitude < -180 || longitude > 180) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (latitude < -90 || latitude > 90) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (accuracy < 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await this.#client.send('Emulation.setGeolocationOverride', {
|
||||||
|
longitude,
|
||||||
|
latitude,
|
||||||
|
accuracy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets default white background
|
||||||
|
*/
|
||||||
|
async resetDefaultBackgroundColor(): Promise<void> {
|
||||||
|
await this.#client.send('Emulation.setDefaultBackgroundColorOverride');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides default white background
|
||||||
|
*/
|
||||||
|
async setTransparentBackgroundColor(): Promise<void> {
|
||||||
|
await this.#client.send('Emulation.setDefaultBackgroundColorOverride', {
|
||||||
|
color: {r: 0, g: 0, b: 0, a: 0},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async setJavaScriptEnabled(enabled: boolean): Promise<void> {
|
||||||
|
if (this.#javascriptEnabled === enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#javascriptEnabled = enabled;
|
||||||
|
await this.#client.send('Emulation.setScriptExecutionDisabled', {
|
||||||
|
value: !enabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,6 @@ export class CDPPage extends Page {
|
|||||||
#bindings = new Map<string, Binding>();
|
#bindings = new Map<string, Binding>();
|
||||||
#exposedFunctions = new Map<string, string>();
|
#exposedFunctions = new Map<string, string>();
|
||||||
#coverage: Coverage;
|
#coverage: Coverage;
|
||||||
#javascriptEnabled = true;
|
|
||||||
#viewport: Viewport | null;
|
#viewport: Viewport | null;
|
||||||
#screenshotTaskQueue: TaskQueue;
|
#screenshotTaskQueue: TaskQueue;
|
||||||
#workers = new Map<string, WebWorker>();
|
#workers = new Map<string, WebWorker>();
|
||||||
@ -361,7 +360,7 @@ export class CDPPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override isJavaScriptEnabled(): boolean {
|
override isJavaScriptEnabled(): boolean {
|
||||||
return this.#javascriptEnabled;
|
return this.#emulationManager.javascriptEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
override waitForFileChooser(
|
override waitForFileChooser(
|
||||||
@ -391,27 +390,7 @@ export class CDPPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async setGeolocation(options: GeolocationOptions): Promise<void> {
|
override async setGeolocation(options: GeolocationOptions): Promise<void> {
|
||||||
const {longitude, latitude, accuracy = 0} = options;
|
return await this.#emulationManager.setGeolocation(options);
|
||||||
if (longitude < -180 || longitude > 180) {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (latitude < -90 || latitude > 90) {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (accuracy < 0) {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await this.#client.send('Emulation.setGeolocationOverride', {
|
|
||||||
longitude,
|
|
||||||
latitude,
|
|
||||||
accuracy,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override target(): Target {
|
override target(): Target {
|
||||||
@ -874,22 +853,6 @@ export class CDPPage extends Page {
|
|||||||
this.emit(PageEmittedEvents.Dialog, dialog);
|
this.emit(PageEmittedEvents.Dialog, dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets default white background
|
|
||||||
*/
|
|
||||||
async #resetDefaultBackgroundColor() {
|
|
||||||
await this.#client.send('Emulation.setDefaultBackgroundColorOverride');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides default white background
|
|
||||||
*/
|
|
||||||
async #setTransparentBackgroundColor(): Promise<void> {
|
|
||||||
await this.#client.send('Emulation.setDefaultBackgroundColorOverride', {
|
|
||||||
color: {r: 0, g: 0, b: 0, a: 0},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
override url(): string {
|
override url(): string {
|
||||||
return this.mainFrame().url();
|
return this.mainFrame().url();
|
||||||
}
|
}
|
||||||
@ -1068,13 +1031,7 @@ export class CDPPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async setJavaScriptEnabled(enabled: boolean): Promise<void> {
|
override async setJavaScriptEnabled(enabled: boolean): Promise<void> {
|
||||||
if (this.#javascriptEnabled === enabled) {
|
return await this.#emulationManager.setJavaScriptEnabled(enabled);
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.#javascriptEnabled = enabled;
|
|
||||||
await this.#client.send('Emulation.setScriptExecutionDisabled', {
|
|
||||||
value: !enabled,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async setBypassCSP(enabled: boolean): Promise<void> {
|
override async setBypassCSP(enabled: boolean): Promise<void> {
|
||||||
@ -1082,100 +1039,34 @@ export class CDPPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async emulateMediaType(type?: string): Promise<void> {
|
override async emulateMediaType(type?: string): Promise<void> {
|
||||||
assert(
|
return await this.#emulationManager.emulateMediaType(type);
|
||||||
type === 'screen' ||
|
|
||||||
type === 'print' ||
|
|
||||||
(type ?? undefined) === undefined,
|
|
||||||
'Unsupported media type: ' + type
|
|
||||||
);
|
|
||||||
await this.#client.send('Emulation.setEmulatedMedia', {
|
|
||||||
media: type || '',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async emulateCPUThrottling(factor: number | null): Promise<void> {
|
override async emulateCPUThrottling(factor: number | null): Promise<void> {
|
||||||
assert(
|
return await this.#emulationManager.emulateCPUThrottling(factor);
|
||||||
factor === null || factor >= 1,
|
|
||||||
'Throttling rate should be greater or equal to 1'
|
|
||||||
);
|
|
||||||
await this.#client.send('Emulation.setCPUThrottlingRate', {
|
|
||||||
rate: factor ?? 1,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async emulateMediaFeatures(
|
override async emulateMediaFeatures(
|
||||||
features?: MediaFeature[]
|
features?: MediaFeature[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!features) {
|
return await this.#emulationManager.emulateMediaFeatures(features);
|
||||||
await this.#client.send('Emulation.setEmulatedMedia', {});
|
|
||||||
}
|
|
||||||
if (Array.isArray(features)) {
|
|
||||||
for (const mediaFeature of features) {
|
|
||||||
const name = mediaFeature.name;
|
|
||||||
assert(
|
|
||||||
/^(?:prefers-(?:color-scheme|reduced-motion)|color-gamut)$/.test(
|
|
||||||
name
|
|
||||||
),
|
|
||||||
'Unsupported media feature: ' + name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await this.#client.send('Emulation.setEmulatedMedia', {
|
|
||||||
features: features,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async emulateTimezone(timezoneId?: string): Promise<void> {
|
override async emulateTimezone(timezoneId?: string): Promise<void> {
|
||||||
try {
|
return await this.#emulationManager.emulateTimezone(timezoneId);
|
||||||
await this.#client.send('Emulation.setTimezoneOverride', {
|
|
||||||
timezoneId: timezoneId || '',
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (isErrorLike(error) && error.message.includes('Invalid timezone')) {
|
|
||||||
throw new Error(`Invalid timezone ID: ${timezoneId}`);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async emulateIdleState(overrides?: {
|
override async emulateIdleState(overrides?: {
|
||||||
isUserActive: boolean;
|
isUserActive: boolean;
|
||||||
isScreenUnlocked: boolean;
|
isScreenUnlocked: boolean;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
if (overrides) {
|
return await this.#emulationManager.emulateIdleState(overrides);
|
||||||
await this.#client.send('Emulation.setIdleOverride', {
|
|
||||||
isUserActive: overrides.isUserActive,
|
|
||||||
isScreenUnlocked: overrides.isScreenUnlocked,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await this.#client.send('Emulation.clearIdleOverride');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async emulateVisionDeficiency(
|
override async emulateVisionDeficiency(
|
||||||
type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type']
|
type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type']
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const visionDeficiencies = new Set<
|
return await this.#emulationManager.emulateVisionDeficiency(type);
|
||||||
Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type']
|
|
||||||
>([
|
|
||||||
'none',
|
|
||||||
'achromatopsia',
|
|
||||||
'blurredVision',
|
|
||||||
'deuteranopia',
|
|
||||||
'protanopia',
|
|
||||||
'tritanopia',
|
|
||||||
]);
|
|
||||||
try {
|
|
||||||
assert(
|
|
||||||
!type || visionDeficiencies.has(type),
|
|
||||||
`Unsupported vision deficiency: ${type}`
|
|
||||||
);
|
|
||||||
await this.#client.send('Emulation.setEmulatedVisionDeficiency', {
|
|
||||||
type: type || 'none',
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async setViewport(viewport: Viewport): Promise<void> {
|
override async setViewport(viewport: Viewport): Promise<void> {
|
||||||
@ -1378,7 +1269,7 @@ export class CDPPage extends Page {
|
|||||||
const shouldSetDefaultBackground =
|
const shouldSetDefaultBackground =
|
||||||
options.omitBackground && (format === 'png' || format === 'webp');
|
options.omitBackground && (format === 'png' || format === 'webp');
|
||||||
if (shouldSetDefaultBackground) {
|
if (shouldSetDefaultBackground) {
|
||||||
await this.#setTransparentBackgroundColor();
|
await this.#emulationManager.setTransparentBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.#client.send('Page.captureScreenshot', {
|
const result = await this.#client.send('Page.captureScreenshot', {
|
||||||
@ -1392,7 +1283,7 @@ export class CDPPage extends Page {
|
|||||||
fromSurface,
|
fromSurface,
|
||||||
});
|
});
|
||||||
if (shouldSetDefaultBackground) {
|
if (shouldSetDefaultBackground) {
|
||||||
await this.#resetDefaultBackgroundColor();
|
await this.#emulationManager.resetDefaultBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.fullPage && this.#viewport) {
|
if (options.fullPage && this.#viewport) {
|
||||||
@ -1435,7 +1326,7 @@ export class CDPPage extends Page {
|
|||||||
} = this._getPDFOptions(options);
|
} = this._getPDFOptions(options);
|
||||||
|
|
||||||
if (omitBackground) {
|
if (omitBackground) {
|
||||||
await this.#setTransparentBackgroundColor();
|
await this.#emulationManager.setTransparentBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
const printCommandPromise = this.#client.send('Page.printToPDF', {
|
const printCommandPromise = this.#client.send('Page.printToPDF', {
|
||||||
@ -1463,7 +1354,7 @@ export class CDPPage extends Page {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (omitBackground) {
|
if (omitBackground) {
|
||||||
await this.#resetDefaultBackgroundColor();
|
await this.#emulationManager.resetDefaultBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(result.stream, '`stream` is missing from `Page.printToPDF');
|
assert(result.stream, '`stream` is missing from `Page.printToPDF');
|
||||||
|
Loading…
Reference in New Issue
Block a user