Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: move more things to emulation manager #10390

Merged
merged 1 commit into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions packages/puppeteer-core/src/common/EmulationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
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 {Viewport} from './PuppeteerViewport.js';

Expand All @@ -25,11 +29,16 @@ export class EmulationManager {
#client: CDPSession;
#emulatingMobile = false;
#hasTouch = false;
#javascriptEnabled = true;

constructor(client: CDPSession) {
this.#client = client;
}

get javascriptEnabled(): boolean {
return this.#javascriptEnabled;
}

async emulateViewport(viewport: Viewport): Promise<boolean> {
const mobile = viewport.isMobile || false;
const width = viewport.width;
Expand Down Expand Up @@ -60,4 +69,149 @@ export class EmulationManager {
this.#hasTouch = hasTouch;
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,
});
}
}
Loading