mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: merge PageDelegate, FrameDelegate and ScreenshotterDelegate (#213)
This commit is contained in:
parent
ce21019c7d
commit
b70eebc4b2
@ -32,7 +32,6 @@ import { toConsoleMessageLocation, exceptionToError, releaseObject } from './pro
|
||||
import * as dialog from '../dialog';
|
||||
import { PageDelegate } from '../page';
|
||||
import { RawMouseImpl, RawKeyboardImpl } from './Input';
|
||||
import { CRScreenshotDelegate } from './Screenshotter';
|
||||
import { Accessibility } from './features/accessibility';
|
||||
import { Coverage } from './features/coverage';
|
||||
import { PDF } from './features/pdf';
|
||||
@ -60,7 +59,7 @@ type FrameData = {
|
||||
id: string,
|
||||
};
|
||||
|
||||
export class FrameManager extends EventEmitter implements frames.FrameDelegate, PageDelegate {
|
||||
export class FrameManager extends EventEmitter implements PageDelegate {
|
||||
_client: CDPSession;
|
||||
private _page: Page;
|
||||
private _networkManager: NetworkManager;
|
||||
@ -70,14 +69,12 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
private _mainFrame: frames.Frame;
|
||||
rawMouse: RawMouseImpl;
|
||||
rawKeyboard: RawKeyboardImpl;
|
||||
screenshotterDelegate: CRScreenshotDelegate;
|
||||
|
||||
constructor(client: CDPSession, browserContext: BrowserContext, ignoreHTTPSErrors: boolean) {
|
||||
super();
|
||||
this._client = client;
|
||||
this.rawKeyboard = new RawKeyboardImpl(client);
|
||||
this.rawMouse = new RawMouseImpl(client);
|
||||
this.screenshotterDelegate = new CRScreenshotDelegate(client);
|
||||
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors, this);
|
||||
this._page = new Page(this, browserContext);
|
||||
(this._page as any).accessibility = new Accessibility(client);
|
||||
@ -272,7 +269,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
return;
|
||||
assert(parentFrameId);
|
||||
const parentFrame = this._frames.get(parentFrameId);
|
||||
const frame = new frames.Frame(this, this._page, parentFrame);
|
||||
const frame = new frames.Frame(this._page, parentFrame);
|
||||
const data: FrameData = {
|
||||
id: frameId,
|
||||
};
|
||||
@ -302,7 +299,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
data.id = framePayload.id;
|
||||
} else {
|
||||
// Initial main frame navigation.
|
||||
frame = new frames.Frame(this, this._page, null);
|
||||
frame = new frames.Frame(this._page, null);
|
||||
const data: FrameData = {
|
||||
id: framePayload.id,
|
||||
};
|
||||
@ -542,6 +539,34 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
else
|
||||
await (this._page.browser() as Browser)._closePage(this._page);
|
||||
}
|
||||
|
||||
async getBoundingBoxForScreenshot(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
const rect = await handle.boundingBox();
|
||||
if (!rect)
|
||||
return rect;
|
||||
const { layoutViewport: { pageX, pageY } } = await this._client.send('Page.getLayoutMetrics');
|
||||
rect.x += pageX;
|
||||
rect.y += pageY;
|
||||
return rect;
|
||||
}
|
||||
|
||||
canScreenshotOutsideViewport(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
await this._client.send('Emulation.setDefaultBackgroundColorOverride', { color });
|
||||
}
|
||||
|
||||
async takeScreenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions): Promise<Buffer> {
|
||||
const clip = options.clip ? { ...options.clip, scale: 1 } : undefined;
|
||||
const result = await this._client.send('Page.captureScreenshot', { format, quality: options.quality, clip });
|
||||
return Buffer.from(result.data, 'base64');
|
||||
}
|
||||
|
||||
async resetViewport(): Promise<void> {
|
||||
await this._client.send('Emulation.setDeviceMetricsOverride', { mobile: false, width: 0, height: 0, deviceScaleFactor: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
function assertNoLegacyNavigationOptions(options: frames.NavigateOptions) {
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as dom from '../dom';
|
||||
import { ScreenshotterDelegate } from '../screenshotter';
|
||||
import * as types from '../types';
|
||||
import { CDPSession } from './api';
|
||||
|
||||
export class CRScreenshotDelegate implements ScreenshotterDelegate {
|
||||
private _session: CDPSession;
|
||||
|
||||
constructor(session: CDPSession) {
|
||||
this._session = session;
|
||||
}
|
||||
|
||||
|
||||
async getBoundingBox(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
const rect = await handle.boundingBox();
|
||||
if (!rect)
|
||||
return rect;
|
||||
const { layoutViewport: { pageX, pageY } } = await this._session.send('Page.getLayoutMetrics');
|
||||
rect.x += pageX;
|
||||
rect.y += pageY;
|
||||
return rect;
|
||||
}
|
||||
|
||||
canCaptureOutsideViewport(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
await this._session.send('Emulation.setDefaultBackgroundColorOverride', { color });
|
||||
}
|
||||
|
||||
async screenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions): Promise<Buffer> {
|
||||
const clip = options.clip ? { ...options.clip, scale: 1 } : undefined;
|
||||
const result = await this._session.send('Page.captureScreenshot', { format, quality: options.quality, clip });
|
||||
return Buffer.from(result.data, 'base64');
|
||||
}
|
||||
|
||||
async resetViewport(): Promise<void> {
|
||||
await this._session.send('Emulation.setDeviceMetricsOverride', { mobile: false, width: 0, height: 0, deviceScaleFactor: 0 });
|
||||
}
|
||||
}
|
@ -30,8 +30,6 @@ import * as dialog from '../dialog';
|
||||
import { Protocol } from './protocol';
|
||||
import * as input from '../input';
|
||||
import { RawMouseImpl, RawKeyboardImpl } from './Input';
|
||||
import { FFScreenshotDelegate } from './Screenshotter';
|
||||
import { Browser } from './Browser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { Interception } from './features/interception';
|
||||
import { Accessibility } from './features/accessibility';
|
||||
@ -51,10 +49,9 @@ type FrameData = {
|
||||
frameId: string,
|
||||
};
|
||||
|
||||
export class FrameManager extends EventEmitter implements frames.FrameDelegate, PageDelegate {
|
||||
export class FrameManager extends EventEmitter implements PageDelegate {
|
||||
readonly rawMouse: RawMouseImpl;
|
||||
readonly rawKeyboard: RawKeyboardImpl;
|
||||
readonly screenshotterDelegate: FFScreenshotDelegate;
|
||||
readonly _session: JugglerSession;
|
||||
readonly _page: Page;
|
||||
private readonly _networkManager: NetworkManager;
|
||||
@ -68,7 +65,6 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
this._session = session;
|
||||
this.rawKeyboard = new RawKeyboardImpl(session);
|
||||
this.rawMouse = new RawMouseImpl(session);
|
||||
this.screenshotterDelegate = new FFScreenshotDelegate(session, this);
|
||||
this._networkManager = new NetworkManager(session, this);
|
||||
this._mainFrame = null;
|
||||
this._frames = new Map();
|
||||
@ -182,7 +178,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
|
||||
_onFrameAttached(params) {
|
||||
const parentFrame = this._frames.get(params.parentFrameId) || null;
|
||||
const frame = new frames.Frame(this, this._page, parentFrame);
|
||||
const frame = new frames.Frame(this._page, parentFrame);
|
||||
const data: FrameData = {
|
||||
frameId: params.frameId,
|
||||
};
|
||||
@ -399,6 +395,36 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
async closePage(runBeforeUnload: boolean): Promise<void> {
|
||||
await this._session.send('Page.close', { runBeforeUnload });
|
||||
}
|
||||
|
||||
getBoundingBoxForScreenshot(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
const frameId = this._frameData(handle.executionContext().frame()).frameId;
|
||||
return this._session.send('Page.getBoundingBox', {
|
||||
frameId,
|
||||
objectId: handle._remoteObject.objectId,
|
||||
});
|
||||
}
|
||||
|
||||
canScreenshotOutsideViewport(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
if (color)
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async takeScreenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions): Promise<Buffer> {
|
||||
const { data } = await this._session.send('Page.screenshot', {
|
||||
mimeType: ('image/' + format) as ('image/png' | 'image/jpeg'),
|
||||
fullPage: options.fullPage,
|
||||
clip: options.clip,
|
||||
});
|
||||
return Buffer.from(data, 'base64');
|
||||
}
|
||||
|
||||
async resetViewport(): Promise<void> {
|
||||
await this._session.send('Page.setViewport', { viewport: null });
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeWaitUntil(waitUntil: frames.LifecycleEvent | frames.LifecycleEvent[]): frames.LifecycleEvent[] {
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ScreenshotterDelegate } from '../screenshotter';
|
||||
import * as types from '../types';
|
||||
import * as dom from '../dom';
|
||||
import { JugglerSession } from './Connection';
|
||||
import { FrameManager } from './FrameManager';
|
||||
|
||||
export class FFScreenshotDelegate implements ScreenshotterDelegate {
|
||||
private _session: JugglerSession;
|
||||
private _frameManager: FrameManager;
|
||||
|
||||
constructor(session: JugglerSession, frameManager: FrameManager) {
|
||||
this._session = session;
|
||||
this._frameManager = frameManager;
|
||||
}
|
||||
|
||||
getBoundingBox(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
const frameId = this._frameManager._frameData(handle.executionContext().frame()).frameId;
|
||||
return this._session.send('Page.getBoundingBox', {
|
||||
frameId,
|
||||
objectId: handle._remoteObject.objectId,
|
||||
});
|
||||
}
|
||||
|
||||
canCaptureOutsideViewport(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
}
|
||||
|
||||
async screenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions): Promise<Buffer> {
|
||||
const { data } = await this._session.send('Page.screenshot', {
|
||||
mimeType: ('image/' + format) as ('image/png' | 'image/jpeg'),
|
||||
fullPage: options.fullPage,
|
||||
clip: options.clip,
|
||||
});
|
||||
return Buffer.from(data, 'base64');
|
||||
}
|
||||
|
||||
async resetViewport(): Promise<void> {
|
||||
await this._session.send('Page.setViewport', { viewport: null });
|
||||
}
|
||||
}
|
@ -22,10 +22,9 @@ import * as dom from './dom';
|
||||
import * as network from './network';
|
||||
import { helper, assert, RegisteredListener } from './helper';
|
||||
import { ClickOptions, MultiClickOptions, PointerActionOptions, SelectOption } from './input';
|
||||
import { TimeoutSettings } from './TimeoutSettings';
|
||||
import { TimeoutError } from './Errors';
|
||||
import { Events } from './events';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Page } from './page';
|
||||
|
||||
const readFileAsync = helper.promisify(fs.readFile);
|
||||
|
||||
@ -46,22 +45,9 @@ export type GotoOptions = NavigateOptions & {
|
||||
referer?: string,
|
||||
};
|
||||
|
||||
export interface FrameDelegate {
|
||||
navigateFrame(frame: Frame, url: string, options?: GotoOptions): Promise<network.Response | null>;
|
||||
waitForFrameNavigation(frame: Frame, options?: NavigateOptions): Promise<network.Response | null>;
|
||||
setFrameContent(frame: Frame, html: string, options?: NavigateOptions): Promise<void>;
|
||||
}
|
||||
|
||||
interface Page extends EventEmitter {
|
||||
_lifecycleWatchers: Set<LifecycleWatcher>;
|
||||
_timeoutSettings: TimeoutSettings;
|
||||
_disconnectedPromise: Promise<Error>;
|
||||
}
|
||||
|
||||
export type LifecycleEvent = 'load' | 'domcontentloaded';
|
||||
|
||||
export class Frame {
|
||||
readonly _delegate: FrameDelegate;
|
||||
readonly _firedLifecycleEvents: Set<LifecycleEvent>;
|
||||
_lastDocumentId: string;
|
||||
readonly _page: Page;
|
||||
@ -72,8 +58,7 @@ export class Frame {
|
||||
private _childFrames = new Set<Frame>();
|
||||
private _name: string;
|
||||
|
||||
constructor(delegate: FrameDelegate, page: Page, parentFrame: Frame | null) {
|
||||
this._delegate = delegate;
|
||||
constructor(page: Page, parentFrame: Frame | null) {
|
||||
this._firedLifecycleEvents = new Set();
|
||||
this._lastDocumentId = '';
|
||||
this._page = page;
|
||||
@ -89,11 +74,11 @@ export class Frame {
|
||||
}
|
||||
|
||||
async goto(url: string, options?: GotoOptions): Promise<network.Response | null> {
|
||||
return this._delegate.navigateFrame(this, url, options);
|
||||
return this._page._delegate.navigateFrame(this, url, options);
|
||||
}
|
||||
|
||||
async waitForNavigation(options?: NavigateOptions): Promise<network.Response | null> {
|
||||
return this._delegate.waitForFrameNavigation(this, options);
|
||||
return this._page._delegate.waitForFrameNavigation(this, options);
|
||||
}
|
||||
|
||||
_mainContext(): Promise<js.ExecutionContext> {
|
||||
@ -174,7 +159,7 @@ export class Frame {
|
||||
}
|
||||
|
||||
async setContent(html: string, options?: NavigateOptions): Promise<void> {
|
||||
return this._delegate.setFrameContent(this, html, options);
|
||||
return this._page._delegate.setFrameContent(this, html, options);
|
||||
}
|
||||
|
||||
name(): string {
|
||||
|
20
src/page.ts
20
src/page.ts
@ -22,7 +22,7 @@ import { assert, debugError, helper } from './helper';
|
||||
import * as input from './input';
|
||||
import * as js from './javascript';
|
||||
import * as network from './network';
|
||||
import { Screenshotter, ScreenshotterDelegate } from './screenshotter';
|
||||
import { Screenshotter } from './screenshotter';
|
||||
import { TimeoutSettings } from './TimeoutSettings';
|
||||
import * as types from './types';
|
||||
import { Events } from './events';
|
||||
@ -32,9 +32,7 @@ import { ConsoleMessage, ConsoleMessageLocation } from './console';
|
||||
export interface PageDelegate {
|
||||
readonly rawMouse: input.RawMouse;
|
||||
readonly rawKeyboard: input.RawKeyboard;
|
||||
readonly screenshotterDelegate: ScreenshotterDelegate;
|
||||
mainFrame(): frames.Frame;
|
||||
frames(): frames.Frame[];
|
||||
|
||||
reload(options?: frames.NavigateOptions): Promise<network.Response | null>;
|
||||
goBack(options?: frames.NavigateOptions): Promise<network.Response | null>;
|
||||
goForward(options?: frames.NavigateOptions): Promise<network.Response | null>;
|
||||
@ -44,6 +42,12 @@ export interface PageDelegate {
|
||||
// TODO: reverse didClose call sequence.
|
||||
didClose(): void;
|
||||
|
||||
mainFrame(): frames.Frame;
|
||||
frames(): frames.Frame[];
|
||||
navigateFrame(frame: frames.Frame, url: string, options?: frames.GotoOptions): Promise<network.Response | null>;
|
||||
waitForFrameNavigation(frame: frames.Frame, options?: frames.NavigateOptions): Promise<network.Response | null>;
|
||||
setFrameContent(frame: frames.Frame, html: string, options?: frames.NavigateOptions): Promise<void>;
|
||||
|
||||
setExtraHTTPHeaders(extraHTTPHeaders: network.Headers): Promise<void>;
|
||||
setUserAgent(userAgent: string): Promise<void>;
|
||||
setJavaScriptEnabled(enabled: boolean): Promise<void>;
|
||||
@ -51,6 +55,12 @@ export interface PageDelegate {
|
||||
setViewport(viewport: types.Viewport): Promise<void>;
|
||||
setEmulateMedia(mediaType: input.MediaType | null, mediaColorScheme: input.MediaColorScheme | null): Promise<void>;
|
||||
setCacheEnabled(enabled: boolean): Promise<void>;
|
||||
|
||||
getBoundingBoxForScreenshot(handle: dom.ElementHandle<Node>): Promise<types.Rect | null>;
|
||||
canScreenshotOutsideViewport(): boolean;
|
||||
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
|
||||
takeScreenshot(format: string, options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer>;
|
||||
resetViewport(oldSize: types.Size): Promise<void>;
|
||||
}
|
||||
|
||||
type PageState = {
|
||||
@ -106,7 +116,7 @@ export class Page extends EventEmitter {
|
||||
this.keyboard = new input.Keyboard(delegate.rawKeyboard);
|
||||
this.mouse = new input.Mouse(delegate.rawMouse, this.keyboard);
|
||||
this._timeoutSettings = new TimeoutSettings();
|
||||
this._screenshotter = new Screenshotter(this, delegate.screenshotterDelegate, browserContext.browser());
|
||||
this._screenshotter = new Screenshotter(this);
|
||||
}
|
||||
|
||||
_didClose() {
|
||||
|
@ -20,36 +20,22 @@ import * as mime from 'mime';
|
||||
import * as dom from './dom';
|
||||
import { assert, helper } from './helper';
|
||||
import * as types from './types';
|
||||
import { Page } from './page';
|
||||
|
||||
const writeFileAsync = helper.promisify(fs.writeFile);
|
||||
|
||||
export interface Page {
|
||||
viewport(): types.Viewport | null;
|
||||
setViewport(v: types.Viewport): Promise<void>;
|
||||
evaluate(f: () => any): Promise<types.Rect>;
|
||||
}
|
||||
|
||||
export interface ScreenshotterDelegate {
|
||||
getBoundingBox(handle: dom.ElementHandle<Node>): Promise<types.Rect | null>;
|
||||
canCaptureOutsideViewport(): boolean;
|
||||
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
|
||||
screenshot(format: string, options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer>;
|
||||
resetViewport(oldSize: types.Size): Promise<void>;
|
||||
}
|
||||
|
||||
export class Screenshotter {
|
||||
private _queue = new TaskQueue();
|
||||
private _delegate: ScreenshotterDelegate;
|
||||
private _page: Page;
|
||||
|
||||
constructor(page: Page, delegate: ScreenshotterDelegate, browserObject: any) {
|
||||
this._delegate = delegate;
|
||||
constructor(page: Page) {
|
||||
this._page = page;
|
||||
|
||||
this._queue = browserObject[taskQueueSymbol];
|
||||
const browser = page.browser();
|
||||
this._queue = browser[taskQueueSymbol];
|
||||
if (!this._queue) {
|
||||
this._queue = new TaskQueue();
|
||||
browserObject[taskQueueSymbol] = this._queue;
|
||||
browser[taskQueueSymbol] = this._queue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +51,7 @@ export class Screenshotter {
|
||||
height: Math.max(document.body.offsetHeight, document.documentElement.offsetHeight)
|
||||
}));
|
||||
}
|
||||
if (options.fullPage && !this._delegate.canCaptureOutsideViewport()) {
|
||||
if (options.fullPage && !this._page._delegate.canScreenshotOutsideViewport()) {
|
||||
const fullPageRect = await this._page.evaluate(() => ({
|
||||
width: Math.max(
|
||||
document.body.scrollWidth, document.documentElement.scrollWidth,
|
||||
@ -90,7 +76,7 @@ export class Screenshotter {
|
||||
if (viewport)
|
||||
await this._page.setViewport(viewport);
|
||||
else
|
||||
await this._delegate.resetViewport(viewportSize);
|
||||
await this._page._delegate.resetViewport(viewportSize);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
@ -102,14 +88,14 @@ export class Screenshotter {
|
||||
return this._queue.postTask(async () => {
|
||||
let overridenViewport: types.Viewport | undefined;
|
||||
|
||||
let boundingBox = await this._delegate.getBoundingBox(handle);
|
||||
let boundingBox = await this._page._delegate.getBoundingBoxForScreenshot(handle);
|
||||
assert(boundingBox, 'Node is either not visible or not an HTMLElement');
|
||||
assert(boundingBox.width !== 0, 'Node has 0 width.');
|
||||
assert(boundingBox.height !== 0, 'Node has 0 height.');
|
||||
boundingBox = enclosingIntRect(boundingBox);
|
||||
const viewport = this._page.viewport();
|
||||
|
||||
if (!this._delegate.canCaptureOutsideViewport()) {
|
||||
if (!this._page._delegate.canScreenshotOutsideViewport()) {
|
||||
if (boundingBox.width > viewport.width || boundingBox.height > viewport.height) {
|
||||
overridenViewport = {
|
||||
...viewport,
|
||||
@ -120,7 +106,7 @@ export class Screenshotter {
|
||||
}
|
||||
|
||||
await handle._scrollIntoViewIfNeeded();
|
||||
boundingBox = enclosingIntRect(await this._delegate.getBoundingBox(handle));
|
||||
boundingBox = enclosingIntRect(await this._page._delegate.getBoundingBoxForScreenshot(handle));
|
||||
}
|
||||
|
||||
if (!overridenViewport)
|
||||
@ -138,10 +124,10 @@ export class Screenshotter {
|
||||
private async _screenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer> {
|
||||
const shouldSetDefaultBackground = options.omitBackground && format === 'png';
|
||||
if (shouldSetDefaultBackground)
|
||||
await this._delegate.setBackgroundColor({ r: 0, g: 0, b: 0, a: 0});
|
||||
const buffer = await this._delegate.screenshot(format, options, viewport);
|
||||
await this._page._delegate.setBackgroundColor({ r: 0, g: 0, b: 0, a: 0});
|
||||
const buffer = await this._page._delegate.takeScreenshot(format, options, viewport);
|
||||
if (shouldSetDefaultBackground)
|
||||
await this._delegate.setBackgroundColor();
|
||||
await this._page._delegate.setBackgroundColor();
|
||||
if (options.path)
|
||||
await writeFileAsync(options.path, buffer);
|
||||
return buffer;
|
||||
|
@ -32,9 +32,10 @@ import * as dialog from '../dialog';
|
||||
import { Browser } from './Browser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { RawMouseImpl, RawKeyboardImpl } from './Input';
|
||||
import { WKScreenshotDelegate } from './Screenshotter';
|
||||
import * as input from '../input';
|
||||
import * as types from '../types';
|
||||
import * as jpeg from 'jpeg-js';
|
||||
import { PNG } from 'pngjs';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
const BINDING_CALL_MESSAGE = '__playwright_binding_call__';
|
||||
@ -54,10 +55,9 @@ type FrameData = {
|
||||
|
||||
let lastDocumentId = 0;
|
||||
|
||||
export class FrameManager extends EventEmitter implements frames.FrameDelegate, PageDelegate {
|
||||
export class FrameManager extends EventEmitter implements PageDelegate {
|
||||
readonly rawMouse: RawMouseImpl;
|
||||
readonly rawKeyboard: RawKeyboardImpl;
|
||||
readonly screenshotterDelegate: WKScreenshotDelegate;
|
||||
_session: TargetSession;
|
||||
readonly _page: Page;
|
||||
private readonly _networkManager: NetworkManager;
|
||||
@ -72,7 +72,6 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
super();
|
||||
this.rawKeyboard = new RawKeyboardImpl();
|
||||
this.rawMouse = new RawMouseImpl();
|
||||
this.screenshotterDelegate = new WKScreenshotDelegate();
|
||||
this._networkManager = new NetworkManager(this);
|
||||
this._frames = new Map();
|
||||
this._contextIdToContext = new Map();
|
||||
@ -90,7 +89,6 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
this._session = session;
|
||||
this.rawKeyboard.setSession(session);
|
||||
this.rawMouse.setSession(session);
|
||||
this.screenshotterDelegate.setSession(session);
|
||||
this._addSessionListeners();
|
||||
this._networkManager.setSession(session);
|
||||
this._isolatedWorlds = new Set();
|
||||
@ -222,7 +220,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
return;
|
||||
assert(parentFrameId);
|
||||
const parentFrame = this._frames.get(parentFrameId);
|
||||
const frame = new frames.Frame(this, this._page, parentFrame);
|
||||
const frame = new frames.Frame(this._page, parentFrame);
|
||||
const data: FrameData = {
|
||||
id: frameId,
|
||||
};
|
||||
@ -250,7 +248,7 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
}
|
||||
} else if (isMainFrame) {
|
||||
// Initial frame navigation.
|
||||
frame = new frames.Frame(this, this._page, null);
|
||||
frame = new frames.Frame(this._page, null);
|
||||
const data: FrameData = {
|
||||
id: framePayload.id,
|
||||
};
|
||||
@ -526,4 +524,31 @@ export class FrameManager extends EventEmitter implements frames.FrameDelegate,
|
||||
throw new Error('Not implemented');
|
||||
(this._page.browser() as Browser)._closePage(this._page);
|
||||
}
|
||||
|
||||
getBoundingBoxForScreenshot(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
return handle.boundingBox();
|
||||
}
|
||||
|
||||
canScreenshotOutsideViewport(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
// TODO: line below crashes, sort it out.
|
||||
this._session.send('Page.setDefaultBackgroundColorOverride', { color });
|
||||
}
|
||||
|
||||
async takeScreenshot(format: string, options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer> {
|
||||
const rect = options.clip || { x: 0, y: 0, width: viewport.width, height: viewport.height };
|
||||
const result = await this._session.send('Page.snapshotRect', { ...rect, coordinateSystem: options.fullPage ? 'Page' : 'Viewport' });
|
||||
const prefix = 'data:image/png;base64,';
|
||||
let buffer = Buffer.from(result.dataURL.substr(prefix.length), 'base64');
|
||||
if (format === 'jpeg')
|
||||
buffer = jpeg.encode(PNG.sync.read(buffer)).data;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
async resetViewport(oldSize: types.Size): Promise<void> {
|
||||
await this._session.send('Emulation.setDeviceMetricsOverride', { ...oldSize, deviceScaleFactor: 0 });
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as jpeg from 'jpeg-js';
|
||||
import { PNG } from 'pngjs';
|
||||
import * as dom from '../dom';
|
||||
import { ScreenshotterDelegate } from '../screenshotter';
|
||||
import * as types from '../types';
|
||||
import { TargetSession } from './Connection';
|
||||
|
||||
export class WKScreenshotDelegate implements ScreenshotterDelegate {
|
||||
private _session: TargetSession;
|
||||
|
||||
setSession(session: TargetSession) {
|
||||
this._session = session;
|
||||
}
|
||||
|
||||
getBoundingBox(handle: dom.ElementHandle<Node>): Promise<types.Rect | null> {
|
||||
return handle.boundingBox();
|
||||
}
|
||||
|
||||
canCaptureOutsideViewport(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void> {
|
||||
// TODO: line below crashes, sort it out.
|
||||
this._session.send('Page.setDefaultBackgroundColorOverride', { color });
|
||||
}
|
||||
|
||||
async screenshot(format: string, options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer> {
|
||||
const rect = options.clip || { x: 0, y: 0, width: viewport.width, height: viewport.height };
|
||||
const result = await this._session.send('Page.snapshotRect', { ...rect, coordinateSystem: options.fullPage ? 'Page' : 'Viewport' });
|
||||
const prefix = 'data:image/png;base64,';
|
||||
let buffer = Buffer.from(result.dataURL.substr(prefix.length), 'base64');
|
||||
if (format === 'jpeg')
|
||||
buffer = jpeg.encode(PNG.sync.read(buffer)).data;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
async resetViewport(oldSize: types.Size): Promise<void> {
|
||||
await this._session.send('Emulation.setDeviceMetricsOverride', { ...oldSize, deviceScaleFactor: 0 });
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user