This commit is contained in:
Yury Semikhatsky 2024-09-03 12:21:51 -07:00
parent daab42fa41
commit 294a05eafe
12 changed files with 44 additions and 57 deletions

View file

@ -16,6 +16,7 @@
[playwright.ts]
./android/
./bidi/
./chromium/
./electron/
./firefox/

View file

@ -15,19 +15,21 @@
*/
import type * as channels from '@protocol/channels';
import type * as types from '../types';
import * as network from '../network';
import type { RegisteredListener } from '../../utils/eventsHelper';
import { eventsHelper } from '../../utils/eventsHelper';
import type { BrowserOptions } from '../browser';
import { Browser } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext } from '../browserContext';
import type { SdkObject } from '../instrumentation';
import * as network from '../network';
import type { InitScript, Page, PageDelegate } from '../page';
import type { ConnectionTransport } from '../transport';
import { BidiConnection, BidiSession } from './bidiConnection';
import * as bidi from './third_party/bidiProtocol';
import { InitScript, Page, PageDelegate } from '../page';
import { eventsHelper, RegisteredListener } from '../../utils/eventsHelper';
import { BidiPage } from './bidiPage';
import type * as types from '../types';
import type { BidiSession } from './bidiConnection';
import { BidiConnection } from './bidiConnection';
import { bidiBytesValueToString } from './bidiNetworkManager';
import { BidiPage } from './bidiPage';
import * as bidi from './third_party/bidiProtocol';
export class BidiBrowser extends Browser {
private readonly _connection: BidiConnection;
@ -68,7 +70,7 @@ export class BidiBrowser extends Browser {
break;
default:
throw new Error('Invalid proxy server protocol: ' + options.proxy.server);
};
}
if (options.proxy.bypass)
proxy.noProxy = options.proxy.bypass.split(',');
// TODO: support authentication.
@ -175,7 +177,7 @@ export class BidiBrowser extends Browser {
}
const bidiPage = this._bidiPages.get(event.context);
if (!bidiPage)
return
return;
bidiPage.didClose();
this._bidiPages.delete(event.context);
}

View file

@ -38,7 +38,7 @@ export class BidiConnection {
private _lastId = 0;
private _closed = false;
readonly browserSession: BidiSession;
readonly _browsingContextToSession = new Map<string, BidiSession>;
readonly _browsingContextToSession = new Map<string, BidiSession>();
constructor(transport: ConnectionTransport, onDisconnect: () => void, protocolLogger: ProtocolLogger, browserLogsCollector: RecentLogsCollector) {
this._transport = transport;

View file

@ -14,12 +14,12 @@
* limitations under the License.
*/
import type { BidiSession } from './bidiConnection';
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
import * as js from '../javascript';
import type { BidiSession } from './bidiConnection';
import { BidiDeserializer } from './third_party/bidiDeserializer';
import * as bidi from './third_party/bidiProtocol';
import { BidiSerializer } from './third_party/bidiSerializer';
import { BidiDeserializer } from './third_party/bidiDeserializer';
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
export class BidiExecutionContext implements js.ExecutionContextDelegate {
private readonly _session: BidiSession;
@ -63,7 +63,7 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
expression,
target: this._target,
resultOwnership: bidi.Script.ResultOwnership.Root, // Necessary for the handle to be returned.
serializationOptions: { maxObjectDepth:0, maxDomDepth:0 },
serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },
awaitPromise: true,
userActivation: true,
});
@ -91,7 +91,7 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
...objectIds.map(handle => ({ handle })),
],
resultOwnership: returnByValue ? undefined : bidi.Script.ResultOwnership.Root, // Necessary for the handle to be returned.
serializationOptions: returnByValue ? {} : { maxObjectDepth:0, maxDomDepth:0 },
serializationOptions: returnByValue ? {} : { maxObjectDepth: 0, maxDomDepth: 0 },
awaitPromise: true,
userActivation: true,
});
@ -99,8 +99,7 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text + '\nFull val: ' + JSON.stringify(response.exceptionDetails));
if (response.type === 'success') {
if (returnByValue)
if (returnByValue)
return parseEvaluationResultValue(BidiDeserializer.deserialize(response.result));
return parseEvaluationResultValue(BidiDeserializer.deserialize(response.result));
const objectId = 'handle' in response.result ? response.result.handle : undefined ;
return utilityScript._context.createHandle({ objectId, ...response.result });
}
@ -131,9 +130,9 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
const response = await this._session.send('script.callFunction', {
functionDeclaration,
target: this._target,
arguments: [ arg ],
arguments: [arg],
resultOwnership: bidi.Script.ResultOwnership.Root, // Necessary for the handle to be returned.
serializationOptions: { maxObjectDepth:0, maxDomDepth:0 },
serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },
awaitPromise: true,
userActivation: true,
});

View file

@ -19,7 +19,8 @@ import path from 'path';
import { assert, ManualPromise, wrapInASCIIBox } from '../../utils';
import type { Env } from '../../utils/processLauncher';
import type { BrowserOptions } from '../browser';
import { BrowserReadyState, BrowserType, kNoXServerRunningError } from '../browserType';
import type { BrowserReadyState } from '../browserType';
import { BrowserType, kNoXServerRunningError } from '../browserType';
import type { SdkObject } from '../instrumentation';
import type { ProtocolError } from '../protocolError';
import type { ConnectionTransport } from '../transport';
@ -70,11 +71,10 @@ export class BidiFirefox extends BrowserType {
if (userDataDirArg)
throw this._createUserDataDirArgMisuseError('--profile');
const firefoxArguments = ['--remote-debugging-port=0'];
if (headless) {
if (headless)
firefoxArguments.push('--headless');
} else {
else
firefoxArguments.push('--foreground');
}
firefoxArguments.push(`--profile`, userDataDir);
firefoxArguments.push(...args);
// TODO: make ephemeral context work without this argument.

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
import * as input from '../input';
import type * as input from '../input';
import type * as types from '../types';
import type { BidiSession } from './bidiConnection';
import * as bidi from './third_party/bidiProtocol';

View file

@ -21,7 +21,7 @@ import * as network from '../network';
import type * as frames from '../frames';
import type * as types from '../types';
import * as bidi from './third_party/bidiProtocol';
import { BidiSession } from './bidiConnection';
import type { BidiSession } from './bidiConnection';
export class BidiNetworkManager {
@ -223,7 +223,7 @@ class BidiRequest {
if (redirectedFrom)
redirectedFrom._redirectedTo = this;
// TODO: missing in the spec?
let postDataBuffer = null;
const postDataBuffer = null;
this.request = new network.Request(frame._page._browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigation ?? undefined,
payload.request.url, 'other', payload.request.method, postDataBuffer, fromBidiHeaders(payload.request.headers));
// "raw" headers are the same as "provisional" headers in Bidi.
@ -297,13 +297,13 @@ class BidiRouteImpl implements network.RouteDelegate {
function fromBidiHeaders(bidiHeaders: bidi.Network.Header[]): types.HeadersArray {
const result: types.HeadersArray = [];
for (const {name, value} of bidiHeaders)
for (const { name, value } of bidiHeaders)
result.push({ name, value: bidiBytesValueToString(value) });
return result;
}
function toBidiHeaders(headers: types.HeadersArray): bidi.Network.Header[] {
return headers.map(({ name, value }) => ({ name, value: { type: 'string', value} }));
return headers.map(({ name, value }) => ({ name, value: { type: 'string', value } }));
}
export function bidiBytesValueToString(value: bidi.Network.BytesValue): string {

View file

@ -25,7 +25,7 @@ import { type InitScript, Page, type PageDelegate } from '../page';
import type { Progress } from '../progress';
import type * as types from '../types';
import type { BidiBrowserContext } from './bidiBrowser';
import { BidiSession } from './bidiConnection';
import type { BidiSession } from './bidiConnection';
import { RawKeyboardImpl, RawMouseImpl, RawTouchscreenImpl } from './bidiInput';
import * as bidi from './third_party/bidiProtocol';
import { BidiExecutionContext } from './bidiExecutionContext';
@ -87,7 +87,7 @@ export class BidiPage implements PageDelegate {
}
private async _initialize() {
const { contexts } = await this._session.send('browsingContext.getTree', { root: this._session.sessionId});
const { contexts } = await this._session.send('browsingContext.getTree', { root: this._session.sessionId });
this._handleFrameTree(contexts[0]);
await Promise.all([
this.updateHttpCredentials(),
@ -96,7 +96,7 @@ export class BidiPage implements PageDelegate {
]);
}
private _handleFrameTree(frameTree: bidi.BrowsingContext.Info ) {
private _handleFrameTree(frameTree: bidi.BrowsingContext.Info) {
this._onFrameAttached(frameTree.context, frameTree.parent || null);
// this._onFrameNavigated(frameTree.context, true);
if (!frameTree.children)
@ -149,8 +149,9 @@ export class BidiPage implements PageDelegate {
worldName = 'main';
// Force creating utility world every time the main world is created (e.g. due to navigation).
this._touchUtilityWorld(realmInfo.context);
} else if (realmInfo.sandbox === UTILITY_WORLD_NAME)
} else if (realmInfo.sandbox === UTILITY_WORLD_NAME) {
worldName = 'utility';
}
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
(context as any)[contextDelegateSymbol] = delegate;
if (worldName)
@ -376,7 +377,7 @@ export class BidiPage implements PageDelegate {
if (!(element instanceof Element))
return null;
const rect = element.getBoundingClientRect();
return {x: rect.x, y: rect.y, width: rect.width, height: rect.height};
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
});
if (!box)
return null;
@ -385,7 +386,7 @@ export class BidiPage implements PageDelegate {
return null;
box.x += position.x;
box.y += position.y;
return box
return box;
}
// TODO: move to Frame.
@ -429,7 +430,7 @@ export class BidiPage implements PageDelegate {
}
async getContentQuads(handle: dom.ElementHandle<Element>): Promise<types.Quad[] | null | 'error:notconnected'> {
let quads = await handle.evaluateInUtility(([injected, node]) => {
const quads = await handle.evaluateInUtility(([injected, node]) => {
if (!node.isConnected)
return 'error:notconnected';
const rects = node.getClientRects();
@ -445,27 +446,6 @@ export class BidiPage implements PageDelegate {
if (!quads || quads === 'error:notconnected')
return quads;
// TODO: consider transforming quads to support clicks in iframes.
//
// if (handle._frame !== this._page.mainFrame()) {
// const frameElement = await handle._frame.frameElement();
// quads = await frameElement.evaluateInUtility(([injected, iframe, quads]) => {
// const transform = getComputedStyle(iframe as Element).transform;
// if (transform === 'none')
// return quads;
// const matrix = new DOMMatrixReadOnly(transform);
// for (const quad of quads) {
// for (const point of quad) {
// const p = new DOMPoint(point.x, point.y);
// const transformed = matrix.transformPoint(p);
// point.x = transformed.x;
// point.y = transformed.y;
// }
// }
// return quads;
// }, quads).catch(e => 'error:notconnected' as const);
// if (!quads || quads === 'error:notconnected')
// return null;
// }
const position = await this._framePosition(handle._frame);
if (!position)
return null;

View file

@ -8,6 +8,8 @@
import type * as Bidi from './bidiProtocol';
/* eslint-disable object-curly-spacing */
/**
* @internal
*/

View file

@ -5,6 +5,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
/* eslint-disable curly */
export const getBidiKeyValue = (key: string) => {
switch (key) {
case '\r':

View file

@ -7,6 +7,7 @@
import type * as Bidi from './bidiProtocol';
/* eslint-disable curly, indent */
/**
* @internal

View file

@ -32,7 +32,7 @@ import { ProgressController } from './progress';
import type * as types from './types';
import type * as channels from '@protocol/channels';
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings';
import { assert, debugMode } from '../utils';
import { debugMode } from '../utils';
import { existsAsync } from '../utils/fileUtils';
import { helper } from './helper';
import { RecentLogsCollector } from '../utils/debugLogger';