init commit
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.AndroidSocketDispatcher = exports.AndroidDispatcher = exports.AndroidDeviceDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _android = require("../android/android");
|
||||
var _browserContextDispatcher = require("./browserContextDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class AndroidDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, android) {
|
||||
super(scope, android, 'Android', {});
|
||||
this._type_Android = true;
|
||||
}
|
||||
async devices(params) {
|
||||
const devices = await this._object.devices(params);
|
||||
return {
|
||||
devices: devices.map(d => AndroidDeviceDispatcher.from(this, d))
|
||||
};
|
||||
}
|
||||
async setDefaultTimeoutNoReply(params) {
|
||||
this._object.setDefaultTimeout(params.timeout);
|
||||
}
|
||||
}
|
||||
exports.AndroidDispatcher = AndroidDispatcher;
|
||||
class AndroidDeviceDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, device) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(device);
|
||||
return result || new AndroidDeviceDispatcher(scope, device);
|
||||
}
|
||||
constructor(scope, device) {
|
||||
super(scope, device, 'AndroidDevice', {
|
||||
model: device.model,
|
||||
serial: device.serial
|
||||
});
|
||||
this._type_EventTarget = true;
|
||||
this._type_AndroidDevice = true;
|
||||
for (const webView of device.webViews()) this._dispatchEvent('webViewAdded', {
|
||||
webView
|
||||
});
|
||||
this.addObjectListener(_android.AndroidDevice.Events.WebViewAdded, webView => this._dispatchEvent('webViewAdded', {
|
||||
webView
|
||||
}));
|
||||
this.addObjectListener(_android.AndroidDevice.Events.WebViewRemoved, socketName => this._dispatchEvent('webViewRemoved', {
|
||||
socketName
|
||||
}));
|
||||
this.addObjectListener(_android.AndroidDevice.Events.Close, socketName => this._dispatchEvent('close'));
|
||||
}
|
||||
async wait(params) {
|
||||
await this._object.send('wait', params);
|
||||
}
|
||||
async fill(params) {
|
||||
await this._object.send('click', {
|
||||
selector: params.selector
|
||||
});
|
||||
await this._object.send('fill', params);
|
||||
}
|
||||
async tap(params) {
|
||||
await this._object.send('click', params);
|
||||
}
|
||||
async drag(params) {
|
||||
await this._object.send('drag', params);
|
||||
}
|
||||
async fling(params) {
|
||||
await this._object.send('fling', params);
|
||||
}
|
||||
async longTap(params) {
|
||||
await this._object.send('longClick', params);
|
||||
}
|
||||
async pinchClose(params) {
|
||||
await this._object.send('pinchClose', params);
|
||||
}
|
||||
async pinchOpen(params) {
|
||||
await this._object.send('pinchOpen', params);
|
||||
}
|
||||
async scroll(params) {
|
||||
await this._object.send('scroll', params);
|
||||
}
|
||||
async swipe(params) {
|
||||
await this._object.send('swipe', params);
|
||||
}
|
||||
async info(params) {
|
||||
return {
|
||||
info: await this._object.send('info', params)
|
||||
};
|
||||
}
|
||||
async inputType(params) {
|
||||
const text = params.text;
|
||||
const keyCodes = [];
|
||||
for (let i = 0; i < text.length; ++i) {
|
||||
const code = keyMap.get(text[i].toUpperCase());
|
||||
if (code === undefined) throw new Error('No mapping for ' + text[i] + ' found');
|
||||
keyCodes.push(code);
|
||||
}
|
||||
await Promise.all(keyCodes.map(keyCode => this._object.send('inputPress', {
|
||||
keyCode
|
||||
})));
|
||||
}
|
||||
async inputPress(params) {
|
||||
if (!keyMap.has(params.key)) throw new Error('Unknown key: ' + params.key);
|
||||
await this._object.send('inputPress', {
|
||||
keyCode: keyMap.get(params.key)
|
||||
});
|
||||
}
|
||||
async inputTap(params) {
|
||||
await this._object.send('inputClick', params);
|
||||
}
|
||||
async inputSwipe(params) {
|
||||
await this._object.send('inputSwipe', params);
|
||||
}
|
||||
async inputDrag(params) {
|
||||
await this._object.send('inputDrag', params);
|
||||
}
|
||||
async screenshot(params) {
|
||||
return {
|
||||
binary: await this._object.screenshot()
|
||||
};
|
||||
}
|
||||
async shell(params) {
|
||||
return {
|
||||
result: await this._object.shell(params.command)
|
||||
};
|
||||
}
|
||||
async open(params, metadata) {
|
||||
const socket = await this._object.open(params.command);
|
||||
return {
|
||||
socket: new AndroidSocketDispatcher(this, socket)
|
||||
};
|
||||
}
|
||||
async installApk(params) {
|
||||
await this._object.installApk(params.file, {
|
||||
args: params.args
|
||||
});
|
||||
}
|
||||
async push(params) {
|
||||
await this._object.push(params.file, params.path, params.mode);
|
||||
}
|
||||
async launchBrowser(params) {
|
||||
const context = await this._object.launchBrowser(params.pkg, params);
|
||||
return {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
|
||||
};
|
||||
}
|
||||
async close(params) {
|
||||
await this._object.close();
|
||||
}
|
||||
async setDefaultTimeoutNoReply(params) {
|
||||
this._object.setDefaultTimeout(params.timeout);
|
||||
}
|
||||
async connectToWebView(params) {
|
||||
return {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(this, await this._object.connectToWebView(params.socketName))
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.AndroidDeviceDispatcher = AndroidDeviceDispatcher;
|
||||
class AndroidSocketDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, socket) {
|
||||
super(scope, socket, 'AndroidSocket', {});
|
||||
this._type_AndroidSocket = true;
|
||||
this.addObjectListener('data', data => this._dispatchEvent('data', {
|
||||
data
|
||||
}));
|
||||
this.addObjectListener('close', () => {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
});
|
||||
}
|
||||
async write(params, metadata) {
|
||||
await this._object.write(params.data);
|
||||
}
|
||||
async close(params, metadata) {
|
||||
this._object.close();
|
||||
}
|
||||
}
|
||||
exports.AndroidSocketDispatcher = AndroidSocketDispatcher;
|
||||
const keyMap = new Map([['Unknown', 0], ['SoftLeft', 1], ['SoftRight', 2], ['Home', 3], ['Back', 4], ['Call', 5], ['EndCall', 6], ['0', 7], ['1', 8], ['2', 9], ['3', 10], ['4', 11], ['5', 12], ['6', 13], ['7', 14], ['8', 15], ['9', 16], ['Star', 17], ['*', 17], ['Pound', 18], ['#', 18], ['DialUp', 19], ['DialDown', 20], ['DialLeft', 21], ['DialRight', 22], ['DialCenter', 23], ['VolumeUp', 24], ['VolumeDown', 25], ['Power', 26], ['Camera', 27], ['Clear', 28], ['A', 29], ['B', 30], ['C', 31], ['D', 32], ['E', 33], ['F', 34], ['G', 35], ['H', 36], ['I', 37], ['J', 38], ['K', 39], ['L', 40], ['M', 41], ['N', 42], ['O', 43], ['P', 44], ['Q', 45], ['R', 46], ['S', 47], ['T', 48], ['U', 49], ['V', 50], ['W', 51], ['X', 52], ['Y', 53], ['Z', 54], ['Comma', 55], [',', 55], ['Period', 56], ['.', 56], ['AltLeft', 57], ['AltRight', 58], ['ShiftLeft', 59], ['ShiftRight', 60], ['Tab', 61], ['\t', 61], ['Space', 62], [' ', 62], ['Sym', 63], ['Explorer', 64], ['Envelop', 65], ['Enter', 66], ['Del', 67], ['Grave', 68], ['Minus', 69], ['-', 69], ['Equals', 70], ['=', 70], ['LeftBracket', 71], ['(', 71], ['RightBracket', 72], [')', 72], ['Backslash', 73], ['\\', 73], ['Semicolon', 74], [';', 74], ['Apostrophe', 75], ['`', 75], ['Slash', 76], ['/', 76], ['At', 77], ['@', 77], ['Num', 78], ['HeadsetHook', 79], ['Focus', 80], ['Plus', 81], ['Menu', 82], ['Notification', 83], ['Search', 84], ['AppSwitch', 187], ['Assist', 219], ['Cut', 277], ['Copy', 278], ['Paste', 279]]);
|
||||
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ArtifactDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _streamDispatcher = require("./streamDispatcher");
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _fileUtils = require("../../utils/fileUtils");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ArtifactDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(parentScope, artifact) {
|
||||
return ArtifactDispatcher.fromNullable(parentScope, artifact);
|
||||
}
|
||||
static fromNullable(parentScope, artifact) {
|
||||
if (!artifact) return undefined;
|
||||
const result = (0, _dispatcher.existingDispatcher)(artifact);
|
||||
return result || new ArtifactDispatcher(parentScope, artifact);
|
||||
}
|
||||
constructor(scope, artifact) {
|
||||
super(scope, artifact, 'Artifact', {
|
||||
absolutePath: artifact.localPath()
|
||||
});
|
||||
this._type_Artifact = true;
|
||||
}
|
||||
async pathAfterFinished() {
|
||||
const path = await this._object.localPathAfterFinished();
|
||||
return {
|
||||
value: path || undefined
|
||||
};
|
||||
}
|
||||
async saveAs(params) {
|
||||
return await new Promise((resolve, reject) => {
|
||||
this._object.saveAs(async (localPath, error) => {
|
||||
if (error !== undefined) {
|
||||
reject(new Error(error));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await (0, _fileUtils.mkdirIfNeeded)(params.path);
|
||||
await _fs.default.promises.copyFile(localPath, params.path);
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
async saveAsStream() {
|
||||
return await new Promise((resolve, reject) => {
|
||||
this._object.saveAs(async (localPath, error) => {
|
||||
if (error !== undefined) {
|
||||
reject(new Error(error));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const readable = _fs.default.createReadStream(localPath, {
|
||||
highWaterMark: 1024 * 1024
|
||||
});
|
||||
const stream = new _streamDispatcher.StreamDispatcher(this, readable);
|
||||
// Resolve with a stream, so that client starts saving the data.
|
||||
resolve({
|
||||
stream
|
||||
});
|
||||
// Block the Artifact until the stream is consumed.
|
||||
await new Promise(resolve => {
|
||||
readable.on('close', resolve);
|
||||
readable.on('end', resolve);
|
||||
readable.on('error', resolve);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
async stream() {
|
||||
const fileName = await this._object.localPathAfterFinished();
|
||||
if (!fileName) return {};
|
||||
const readable = _fs.default.createReadStream(fileName, {
|
||||
highWaterMark: 1024 * 1024
|
||||
});
|
||||
return {
|
||||
stream: new _streamDispatcher.StreamDispatcher(this, readable)
|
||||
};
|
||||
}
|
||||
async failure() {
|
||||
const error = await this._object.failureError();
|
||||
return {
|
||||
error: error || undefined
|
||||
};
|
||||
}
|
||||
async cancel() {
|
||||
await this._object.cancel();
|
||||
}
|
||||
async delete() {
|
||||
await this._object.delete();
|
||||
this._dispose();
|
||||
}
|
||||
}
|
||||
exports.ArtifactDispatcher = ArtifactDispatcher;
|
||||
@@ -0,0 +1,290 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.BrowserContextDispatcher = void 0;
|
||||
var _browserContext = require("../browserContext");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _pageDispatcher = require("./pageDispatcher");
|
||||
var _networkDispatchers = require("./networkDispatchers");
|
||||
var _crBrowser = require("../chromium/crBrowser");
|
||||
var _cdpSessionDispatcher = require("./cdpSessionDispatcher");
|
||||
var _recorder = require("../recorder");
|
||||
var _artifactDispatcher = require("./artifactDispatcher");
|
||||
var _tracingDispatcher = require("./tracingDispatcher");
|
||||
var fs = _interopRequireWildcard(require("fs"));
|
||||
var path = _interopRequireWildcard(require("path"));
|
||||
var _utils = require("../../utils");
|
||||
var _writableStreamDispatcher = require("./writableStreamDispatcher");
|
||||
var _consoleMessageDispatcher = require("./consoleMessageDispatcher");
|
||||
var _dialogDispatcher = require("./dialogDispatcher");
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class BrowserContextDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(parentScope, context) {
|
||||
// We will reparent these to the context below.
|
||||
const requestContext = _networkDispatchers.APIRequestContextDispatcher.from(parentScope, context.fetchRequest);
|
||||
const tracing = _tracingDispatcher.TracingDispatcher.from(parentScope, context.tracing);
|
||||
super(parentScope, context, 'BrowserContext', {
|
||||
isChromium: context._browser.options.isChromium,
|
||||
requestContext,
|
||||
tracing
|
||||
});
|
||||
this._type_EventTarget = true;
|
||||
this._type_BrowserContext = true;
|
||||
this._context = void 0;
|
||||
this._subscriptions = new Set();
|
||||
this.adopt(requestContext);
|
||||
this.adopt(tracing);
|
||||
this._context = context;
|
||||
// Note: when launching persistent context, dispatcher is created very late,
|
||||
// so we can already have pages, videos and everything else.
|
||||
|
||||
const onVideo = artifact => {
|
||||
// Note: Video must outlive Page and BrowserContext, so that client can saveAs it
|
||||
// after closing the context. We use |scope| for it.
|
||||
const artifactDispatcher = _artifactDispatcher.ArtifactDispatcher.from(parentScope, artifact);
|
||||
this._dispatchEvent('video', {
|
||||
artifact: artifactDispatcher
|
||||
});
|
||||
};
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.VideoStarted, onVideo);
|
||||
for (const video of context._browser._idToVideo.values()) {
|
||||
if (video.context === context) onVideo(video.artifact);
|
||||
}
|
||||
for (const page of context.pages()) this._dispatchEvent('page', {
|
||||
page: _pageDispatcher.PageDispatcher.from(this, page)
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Page, page => {
|
||||
this._dispatchEvent('page', {
|
||||
page: _pageDispatcher.PageDispatcher.from(this, page)
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Close, () => {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Console, message => {
|
||||
if (this._shouldDispatchEvent(message.page(), 'console')) this._dispatchEvent('console', {
|
||||
message: new _consoleMessageDispatcher.ConsoleMessageDispatcher(_pageDispatcher.PageDispatcher.from(this, message.page()), message)
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Dialog, dialog => {
|
||||
if (this._shouldDispatchEvent(dialog.page(), 'dialog')) this._dispatchEvent('dialog', {
|
||||
dialog: new _dialogDispatcher.DialogDispatcher(this, dialog)
|
||||
});else dialog.close().catch(() => {});
|
||||
});
|
||||
if (context._browser.options.name === 'chromium') {
|
||||
for (const page of context.backgroundPages()) this._dispatchEvent('backgroundPage', {
|
||||
page: _pageDispatcher.PageDispatcher.from(this, page)
|
||||
});
|
||||
this.addObjectListener(_crBrowser.CRBrowserContext.CREvents.BackgroundPage, page => this._dispatchEvent('backgroundPage', {
|
||||
page: _pageDispatcher.PageDispatcher.from(this, page)
|
||||
}));
|
||||
for (const serviceWorker of context.serviceWorkers()) this._dispatchEvent('serviceWorker', {
|
||||
worker: new _pageDispatcher.WorkerDispatcher(this, serviceWorker)
|
||||
});
|
||||
this.addObjectListener(_crBrowser.CRBrowserContext.CREvents.ServiceWorker, serviceWorker => this._dispatchEvent('serviceWorker', {
|
||||
worker: new _pageDispatcher.WorkerDispatcher(this, serviceWorker)
|
||||
}));
|
||||
}
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Request, request => {
|
||||
var _request$frame;
|
||||
// Create dispatcher, if:
|
||||
// - There are listeners to the requests.
|
||||
// - We are redirected from a reported request so that redirectedTo was updated on client.
|
||||
// - We are a navigation request and dispatcher will be reported as a part of the goto return value and newDocument param anyways.
|
||||
// By the time requestFinished is triggered to update the request, we should have a request on the client already.
|
||||
const redirectFromDispatcher = request.redirectedFrom() && (0, _dispatcher.existingDispatcher)(request.redirectedFrom());
|
||||
if (!redirectFromDispatcher && !this._shouldDispatchNetworkEvent(request, 'request') && !request.isNavigationRequest()) return;
|
||||
const requestDispatcher = _networkDispatchers.RequestDispatcher.from(this, request);
|
||||
this._dispatchEvent('request', {
|
||||
request: requestDispatcher,
|
||||
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame = request.frame()) === null || _request$frame === void 0 ? void 0 : _request$frame._page.initializedOrUndefined())
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.Response, response => {
|
||||
var _response$frame;
|
||||
const requestDispatcher = (0, _dispatcher.existingDispatcher)(response.request());
|
||||
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(response.request(), 'response')) return;
|
||||
this._dispatchEvent('response', {
|
||||
response: _networkDispatchers.ResponseDispatcher.from(this, response),
|
||||
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_response$frame = response.frame()) === null || _response$frame === void 0 ? void 0 : _response$frame._page.initializedOrUndefined())
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.RequestFailed, request => {
|
||||
var _request$frame2;
|
||||
const requestDispatcher = (0, _dispatcher.existingDispatcher)(request);
|
||||
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(request, 'requestFailed')) return;
|
||||
this._dispatchEvent('requestFailed', {
|
||||
request: _networkDispatchers.RequestDispatcher.from(this, request),
|
||||
failureText: request._failureText || undefined,
|
||||
responseEndTiming: request._responseEndTiming,
|
||||
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame2 = request.frame()) === null || _request$frame2 === void 0 ? void 0 : _request$frame2._page.initializedOrUndefined())
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_browserContext.BrowserContext.Events.RequestFinished, ({
|
||||
request,
|
||||
response
|
||||
}) => {
|
||||
var _request$frame3;
|
||||
const requestDispatcher = (0, _dispatcher.existingDispatcher)(request);
|
||||
if (!requestDispatcher && !this._shouldDispatchNetworkEvent(request, 'requestFinished')) return;
|
||||
this._dispatchEvent('requestFinished', {
|
||||
request: _networkDispatchers.RequestDispatcher.from(this, request),
|
||||
response: _networkDispatchers.ResponseDispatcher.fromNullable(this, response),
|
||||
responseEndTiming: request._responseEndTiming,
|
||||
page: _pageDispatcher.PageDispatcher.fromNullable(this, (_request$frame3 = request.frame()) === null || _request$frame3 === void 0 ? void 0 : _request$frame3._page.initializedOrUndefined())
|
||||
});
|
||||
});
|
||||
}
|
||||
_shouldDispatchNetworkEvent(request, event) {
|
||||
var _request$frame4, _request$frame4$_page;
|
||||
return this._shouldDispatchEvent((_request$frame4 = request.frame()) === null || _request$frame4 === void 0 ? void 0 : (_request$frame4$_page = _request$frame4._page) === null || _request$frame4$_page === void 0 ? void 0 : _request$frame4$_page.initializedOrUndefined(), event);
|
||||
}
|
||||
_shouldDispatchEvent(page, event) {
|
||||
if (this._subscriptions.has(event)) return true;
|
||||
const pageDispatcher = page ? (0, _dispatcher.existingDispatcher)(page) : undefined;
|
||||
if (pageDispatcher !== null && pageDispatcher !== void 0 && pageDispatcher._subscriptions.has(event)) return true;
|
||||
return false;
|
||||
}
|
||||
async createTempFile(params) {
|
||||
const dir = this._context._browser.options.artifactsDir;
|
||||
const tmpDir = path.join(dir, 'upload-' + (0, _utils.createGuid)());
|
||||
await fs.promises.mkdir(tmpDir);
|
||||
this._context._tempDirs.push(tmpDir);
|
||||
const file = fs.createWriteStream(path.join(tmpDir, params.name));
|
||||
return {
|
||||
writableStream: new _writableStreamDispatcher.WritableStreamDispatcher(this, file)
|
||||
};
|
||||
}
|
||||
async setDefaultNavigationTimeoutNoReply(params) {
|
||||
this._context.setDefaultNavigationTimeout(params.timeout);
|
||||
}
|
||||
async setDefaultTimeoutNoReply(params) {
|
||||
this._context.setDefaultTimeout(params.timeout);
|
||||
}
|
||||
async exposeBinding(params) {
|
||||
await this._context.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
|
||||
// When reusing the context, we might have some bindings called late enough,
|
||||
// after context and page dispatchers have been disposed.
|
||||
if (this._disposed) return;
|
||||
const pageDispatcher = _pageDispatcher.PageDispatcher.from(this, source.page);
|
||||
const binding = new _pageDispatcher.BindingCallDispatcher(pageDispatcher, params.name, !!params.needsHandle, source, args);
|
||||
this._dispatchEvent('bindingCall', {
|
||||
binding
|
||||
});
|
||||
return binding.promise();
|
||||
});
|
||||
}
|
||||
async newPage(params, metadata) {
|
||||
return {
|
||||
page: _pageDispatcher.PageDispatcher.from(this, await this._context.newPage(metadata))
|
||||
};
|
||||
}
|
||||
async cookies(params) {
|
||||
return {
|
||||
cookies: await this._context.cookies(params.urls)
|
||||
};
|
||||
}
|
||||
async addCookies(params) {
|
||||
await this._context.addCookies(params.cookies);
|
||||
}
|
||||
async clearCookies() {
|
||||
await this._context.clearCookies();
|
||||
}
|
||||
async grantPermissions(params) {
|
||||
await this._context.grantPermissions(params.permissions, params.origin);
|
||||
}
|
||||
async clearPermissions() {
|
||||
await this._context.clearPermissions();
|
||||
}
|
||||
async setGeolocation(params) {
|
||||
await this._context.setGeolocation(params.geolocation);
|
||||
}
|
||||
async setExtraHTTPHeaders(params) {
|
||||
await this._context.setExtraHTTPHeaders(params.headers);
|
||||
}
|
||||
async setOffline(params) {
|
||||
await this._context.setOffline(params.offline);
|
||||
}
|
||||
async setHTTPCredentials(params) {
|
||||
await this._context.setHTTPCredentials(params.httpCredentials);
|
||||
}
|
||||
async addInitScript(params) {
|
||||
await this._context.addInitScript(params.source);
|
||||
}
|
||||
async setNetworkInterceptionPatterns(params) {
|
||||
if (!params.patterns.length) {
|
||||
await this._context.setRequestInterceptor(undefined);
|
||||
return;
|
||||
}
|
||||
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob);
|
||||
await this._context.setRequestInterceptor((route, request) => {
|
||||
const matchesSome = urlMatchers.some(urlMatch => (0, _utils.urlMatches)(this._context._options.baseURL, request.url(), urlMatch));
|
||||
if (!matchesSome) return false;
|
||||
this._dispatchEvent('route', {
|
||||
route: _networkDispatchers.RouteDispatcher.from(_networkDispatchers.RequestDispatcher.from(this, request), route)
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
async storageState(params, metadata) {
|
||||
return await this._context.storageState();
|
||||
}
|
||||
async close(params, metadata) {
|
||||
await this._context.close(metadata);
|
||||
}
|
||||
async recorderSupplementEnable(params) {
|
||||
await _recorder.Recorder.show(this._context, params);
|
||||
}
|
||||
async pause(params, metadata) {
|
||||
// Debugger will take care of this.
|
||||
}
|
||||
async newCDPSession(params) {
|
||||
if (!this._object._browser.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
|
||||
if (!params.page && !params.frame || params.page && params.frame) throw new Error(`CDP session must be initiated with either Page or Frame, not none or both`);
|
||||
const crBrowserContext = this._object;
|
||||
return {
|
||||
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowserContext.newCDPSession((params.page ? params.page : params.frame)._object))
|
||||
};
|
||||
}
|
||||
async harStart(params) {
|
||||
const harId = await this._context._harStart(params.page ? params.page._object : null, params.options);
|
||||
return {
|
||||
harId
|
||||
};
|
||||
}
|
||||
async harExport(params) {
|
||||
const artifact = await this._context._harExport(params.harId);
|
||||
if (!artifact) throw new Error('No HAR artifact. Ensure record.harPath is set.');
|
||||
return {
|
||||
artifact: _artifactDispatcher.ArtifactDispatcher.from(this, artifact)
|
||||
};
|
||||
}
|
||||
async updateSubscription(params) {
|
||||
if (params.enabled) this._subscriptions.add(params.event);else this._subscriptions.delete(params.event);
|
||||
}
|
||||
_onDispose() {
|
||||
// Avoid protocol calls for the closed context.
|
||||
if (!this._context.isClosingOrClosed()) this._context.setRequestInterceptor(undefined).catch(() => {});
|
||||
}
|
||||
}
|
||||
exports.BrowserContextDispatcher = BrowserContextDispatcher;
|
||||
@@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ConnectedBrowserDispatcher = exports.BrowserDispatcher = void 0;
|
||||
var _browser = require("../browser");
|
||||
var _browserContextDispatcher = require("./browserContextDispatcher");
|
||||
var _cdpSessionDispatcher = require("./cdpSessionDispatcher");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _instrumentation = require("../instrumentation");
|
||||
var _browserContext = require("../browserContext");
|
||||
var _selectors = require("../selectors");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class BrowserDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, browser) {
|
||||
super(scope, browser, 'Browser', {
|
||||
version: browser.version(),
|
||||
name: browser.options.name
|
||||
});
|
||||
this._type_Browser = true;
|
||||
this.addObjectListener(_browser.Browser.Events.Disconnected, () => this._didClose());
|
||||
}
|
||||
_didClose() {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
}
|
||||
async newContext(params, metadata) {
|
||||
const context = await this._object.newContext(metadata, params);
|
||||
return {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
|
||||
};
|
||||
}
|
||||
async newContextForReuse(params, metadata) {
|
||||
return await newContextForReuse(this._object, this, params, null, metadata);
|
||||
}
|
||||
async close() {
|
||||
await this._object.close();
|
||||
}
|
||||
async killForTests() {
|
||||
await this._object.killForTests();
|
||||
}
|
||||
async defaultUserAgentForTest() {
|
||||
return {
|
||||
userAgent: this._object.userAgent()
|
||||
};
|
||||
}
|
||||
async newBrowserCDPSession() {
|
||||
if (!this._object.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
return {
|
||||
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowser.newBrowserCDPSession())
|
||||
};
|
||||
}
|
||||
async startTracing(params) {
|
||||
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
await crBrowser.startTracing(params.page ? params.page._object : undefined, params);
|
||||
}
|
||||
async stopTracing() {
|
||||
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
return {
|
||||
binary: await crBrowser.stopTracing()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// This class implements multiplexing browser dispatchers over a single Browser instance.
|
||||
exports.BrowserDispatcher = BrowserDispatcher;
|
||||
class ConnectedBrowserDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, browser) {
|
||||
super(scope, browser, 'Browser', {
|
||||
version: browser.version(),
|
||||
name: browser.options.name
|
||||
});
|
||||
// When we have a remotely-connected browser, each client gets a fresh Selector instance,
|
||||
// so that two clients do not interfere between each other.
|
||||
this._type_Browser = true;
|
||||
this._contexts = new Set();
|
||||
this.selectors = void 0;
|
||||
this.selectors = new _selectors.Selectors();
|
||||
}
|
||||
async newContext(params, metadata) {
|
||||
if (params.recordVideo) params.recordVideo.dir = this._object.options.artifactsDir;
|
||||
const context = await this._object.newContext(metadata, params);
|
||||
this._contexts.add(context);
|
||||
context.setSelectors(this.selectors);
|
||||
context.on(_browserContext.BrowserContext.Events.Close, () => this._contexts.delete(context));
|
||||
return {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(this, context)
|
||||
};
|
||||
}
|
||||
async newContextForReuse(params, metadata) {
|
||||
return await newContextForReuse(this._object, this, params, this.selectors, metadata);
|
||||
}
|
||||
async close() {
|
||||
// Client should not send us Browser.close.
|
||||
}
|
||||
async killForTests() {
|
||||
// Client should not send us Browser.killForTests.
|
||||
}
|
||||
async defaultUserAgentForTest() {
|
||||
throw new Error('Client should not send us Browser.defaultUserAgentForTest');
|
||||
}
|
||||
async newBrowserCDPSession() {
|
||||
if (!this._object.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
return {
|
||||
session: new _cdpSessionDispatcher.CDPSessionDispatcher(this, await crBrowser.newBrowserCDPSession())
|
||||
};
|
||||
}
|
||||
async startTracing(params) {
|
||||
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
await crBrowser.startTracing(params.page ? params.page._object : undefined, params);
|
||||
}
|
||||
async stopTracing() {
|
||||
if (!this._object.options.isChromium) throw new Error(`Tracing is only available in Chromium`);
|
||||
const crBrowser = this._object;
|
||||
return {
|
||||
binary: await crBrowser.stopTracing()
|
||||
};
|
||||
}
|
||||
async cleanupContexts() {
|
||||
await Promise.all(Array.from(this._contexts).map(context => context.close((0, _instrumentation.serverSideCallMetadata)())));
|
||||
}
|
||||
}
|
||||
exports.ConnectedBrowserDispatcher = ConnectedBrowserDispatcher;
|
||||
async function newContextForReuse(browser, scope, params, selectors, metadata) {
|
||||
const {
|
||||
context,
|
||||
needsReset
|
||||
} = await browser.newContextForReuse(params, metadata);
|
||||
if (needsReset) {
|
||||
const oldContextDispatcher = (0, _dispatcher.existingDispatcher)(context);
|
||||
if (oldContextDispatcher) oldContextDispatcher._dispose();
|
||||
await context.resetForReuse(metadata, params);
|
||||
}
|
||||
if (selectors) context.setSelectors(selectors);
|
||||
const contextDispatcher = new _browserContextDispatcher.BrowserContextDispatcher(scope, context);
|
||||
return {
|
||||
context: contextDispatcher
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.BrowserTypeDispatcher = void 0;
|
||||
var _browserDispatcher = require("./browserDispatcher");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _browserContextDispatcher = require("./browserContextDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class BrowserTypeDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, browserType) {
|
||||
super(scope, browserType, 'BrowserType', {
|
||||
executablePath: browserType.executablePath(),
|
||||
name: browserType.name()
|
||||
});
|
||||
this._type_BrowserType = true;
|
||||
}
|
||||
async launch(params, metadata) {
|
||||
const browser = await this._object.launch(metadata, params);
|
||||
return {
|
||||
browser: new _browserDispatcher.BrowserDispatcher(this, browser)
|
||||
};
|
||||
}
|
||||
async launchPersistentContext(params, metadata) {
|
||||
const browserContext = await this._object.launchPersistentContext(metadata, params.userDataDir, params);
|
||||
return {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(this, browserContext)
|
||||
};
|
||||
}
|
||||
async connectOverCDP(params, metadata) {
|
||||
const browser = await this._object.connectOverCDP(metadata, params.endpointURL, params, params.timeout);
|
||||
const browserDispatcher = new _browserDispatcher.BrowserDispatcher(this, browser);
|
||||
return {
|
||||
browser: browserDispatcher,
|
||||
defaultContext: browser._defaultContext ? new _browserContextDispatcher.BrowserContextDispatcher(browserDispatcher, browser._defaultContext) : undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.BrowserTypeDispatcher = BrowserTypeDispatcher;
|
||||
@@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.CDPSessionDispatcher = void 0;
|
||||
var _crConnection = require("../chromium/crConnection");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class CDPSessionDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, crSession) {
|
||||
super(scope, crSession, 'CDPSession', {});
|
||||
this._type_CDPSession = true;
|
||||
crSession._eventListener = (method, params) => {
|
||||
this._dispatchEvent('event', {
|
||||
method,
|
||||
params
|
||||
});
|
||||
};
|
||||
this.addObjectListener(_crConnection.CRSessionEvents.Disconnected, () => this._dispose());
|
||||
}
|
||||
async send(params) {
|
||||
return {
|
||||
result: await this._object.send(params.method, params.params)
|
||||
};
|
||||
}
|
||||
async detach() {
|
||||
return this._object.detach();
|
||||
}
|
||||
}
|
||||
exports.CDPSessionDispatcher = CDPSessionDispatcher;
|
||||
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ConsoleMessageDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ConsoleMessageDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(page, message) {
|
||||
super(page, message, 'ConsoleMessage', {
|
||||
type: message.type(),
|
||||
text: message.text(),
|
||||
args: message.args().map(a => _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(page, a)),
|
||||
location: message.location(),
|
||||
page
|
||||
});
|
||||
this._type_ConsoleMessage = true;
|
||||
}
|
||||
}
|
||||
exports.ConsoleMessageDispatcher = ConsoleMessageDispatcher;
|
||||
@@ -0,0 +1,97 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.DebugControllerDispatcher = void 0;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _debugController = require("../debugController");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class DebugControllerDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(connection, debugController) {
|
||||
super(connection, debugController, 'DebugController', {});
|
||||
this._type_DebugController = void 0;
|
||||
this._listeners = void 0;
|
||||
this._type_DebugController = true;
|
||||
this._listeners = [_utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.StateChanged, params => {
|
||||
this._dispatchEvent('stateChanged', params);
|
||||
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.InspectRequested, ({
|
||||
selector,
|
||||
locator
|
||||
}) => {
|
||||
this._dispatchEvent('inspectRequested', {
|
||||
selector,
|
||||
locator
|
||||
});
|
||||
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.SourceChanged, ({
|
||||
text,
|
||||
header,
|
||||
footer,
|
||||
actions
|
||||
}) => {
|
||||
this._dispatchEvent('sourceChanged', {
|
||||
text,
|
||||
header,
|
||||
footer,
|
||||
actions
|
||||
});
|
||||
}), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.Paused, ({
|
||||
paused
|
||||
}) => {
|
||||
this._dispatchEvent('paused', {
|
||||
paused
|
||||
});
|
||||
})];
|
||||
}
|
||||
async initialize(params) {
|
||||
this._object.initialize(params.codegenId, params.sdkLanguage);
|
||||
}
|
||||
async setReportStateChanged(params) {
|
||||
this._object.setReportStateChanged(params.enabled);
|
||||
}
|
||||
async resetForReuse() {
|
||||
await this._object.resetForReuse();
|
||||
}
|
||||
async navigate(params) {
|
||||
await this._object.navigate(params.url);
|
||||
}
|
||||
async setRecorderMode(params) {
|
||||
await this._object.setRecorderMode(params);
|
||||
}
|
||||
async highlight(params) {
|
||||
await this._object.highlight(params.selector);
|
||||
}
|
||||
async hideHighlight() {
|
||||
await this._object.hideHighlight();
|
||||
}
|
||||
async resume() {
|
||||
await this._object.resume();
|
||||
}
|
||||
async kill() {
|
||||
await this._object.kill();
|
||||
}
|
||||
async closeAllBrowsers() {
|
||||
await this._object.closeAllBrowsers();
|
||||
}
|
||||
_onDispose() {
|
||||
_utils.eventsHelper.removeEventListeners(this._listeners);
|
||||
this._object.dispose();
|
||||
}
|
||||
}
|
||||
exports.DebugControllerDispatcher = DebugControllerDispatcher;
|
||||
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.DialogDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _pageDispatcher = require("./pageDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class DialogDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, dialog) {
|
||||
const page = _pageDispatcher.PageDispatcher.fromNullable(scope, dialog.page().initializedOrUndefined());
|
||||
// Prefer scoping to the page, unless we don't have one.
|
||||
super(page || scope, dialog, 'Dialog', {
|
||||
page,
|
||||
type: dialog.type(),
|
||||
message: dialog.message(),
|
||||
defaultValue: dialog.defaultValue()
|
||||
});
|
||||
this._type_Dialog = true;
|
||||
}
|
||||
async accept(params) {
|
||||
await this._object.accept(params.promptText);
|
||||
}
|
||||
async dismiss() {
|
||||
await this._object.dismiss();
|
||||
}
|
||||
}
|
||||
exports.DialogDispatcher = DialogDispatcher;
|
||||
@@ -0,0 +1,344 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.dispatcherSymbol = exports.RootDispatcher = exports.DispatcherConnection = exports.Dispatcher = void 0;
|
||||
exports.existingDispatcher = existingDispatcher;
|
||||
var _events = require("events");
|
||||
var _serializers = require("../../protocol/serializers");
|
||||
var _validator = require("../../protocol/validator");
|
||||
var _utils = require("../../utils");
|
||||
var _errors = require("../../common/errors");
|
||||
var _instrumentation = require("../instrumentation");
|
||||
var _stackTrace = require("../../utils/stackTrace");
|
||||
var _eventsHelper = require("../..//utils/eventsHelper");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const dispatcherSymbol = Symbol('dispatcher');
|
||||
exports.dispatcherSymbol = dispatcherSymbol;
|
||||
const metadataValidator = (0, _validator.createMetadataValidator)();
|
||||
function existingDispatcher(object) {
|
||||
return object[dispatcherSymbol];
|
||||
}
|
||||
class Dispatcher extends _events.EventEmitter {
|
||||
// Parent is always "isScope".
|
||||
|
||||
// Only "isScope" channel owners have registered dispatchers inside.
|
||||
|
||||
constructor(parent, object, type, initializer) {
|
||||
super();
|
||||
this._connection = void 0;
|
||||
this._parent = void 0;
|
||||
this._dispatchers = new Map();
|
||||
this._disposed = false;
|
||||
this._eventListeners = [];
|
||||
this._guid = void 0;
|
||||
this._type = void 0;
|
||||
this._object = void 0;
|
||||
this._connection = parent instanceof DispatcherConnection ? parent : parent._connection;
|
||||
this._parent = parent instanceof DispatcherConnection ? undefined : parent;
|
||||
const guid = object.guid;
|
||||
(0, _utils.assert)(!this._connection._dispatchers.has(guid));
|
||||
this._connection._dispatchers.set(guid, this);
|
||||
if (this._parent) {
|
||||
(0, _utils.assert)(!this._parent._dispatchers.has(guid));
|
||||
this._parent._dispatchers.set(guid, this);
|
||||
}
|
||||
this._type = type;
|
||||
this._guid = guid;
|
||||
this._object = object;
|
||||
object[dispatcherSymbol] = this;
|
||||
if (this._parent) this._connection.sendCreate(this._parent, type, guid, initializer, this._parent._object);
|
||||
}
|
||||
parentScope() {
|
||||
return this._parent;
|
||||
}
|
||||
addObjectListener(eventName, handler) {
|
||||
this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._object, eventName, handler));
|
||||
}
|
||||
adopt(child) {
|
||||
const oldParent = child._parent;
|
||||
oldParent._dispatchers.delete(child._guid);
|
||||
this._dispatchers.set(child._guid, child);
|
||||
child._parent = this;
|
||||
this._connection.sendAdopt(this, child);
|
||||
}
|
||||
_dispatchEvent(method, params) {
|
||||
if (this._disposed) {
|
||||
if ((0, _utils.isUnderTest)()) throw new Error(`${this._guid} is sending "${String(method)}" event after being disposed`);
|
||||
// Just ignore this event outside of tests.
|
||||
return;
|
||||
}
|
||||
const sdkObject = this._object instanceof _instrumentation.SdkObject ? this._object : undefined;
|
||||
this._connection.sendEvent(this, method, params, sdkObject);
|
||||
}
|
||||
_dispose() {
|
||||
this._disposeRecursively();
|
||||
this._connection.sendDispose(this);
|
||||
}
|
||||
_onDispose() {}
|
||||
_disposeRecursively() {
|
||||
(0, _utils.assert)(!this._disposed, `${this._guid} is disposed more than once`);
|
||||
this._onDispose();
|
||||
this._disposed = true;
|
||||
_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
||||
|
||||
// Clean up from parent and connection.
|
||||
if (this._parent) this._parent._dispatchers.delete(this._guid);
|
||||
this._connection._dispatchers.delete(this._guid);
|
||||
|
||||
// Dispose all children.
|
||||
for (const dispatcher of [...this._dispatchers.values()]) dispatcher._disposeRecursively();
|
||||
this._dispatchers.clear();
|
||||
delete this._object[dispatcherSymbol];
|
||||
}
|
||||
_debugScopeState() {
|
||||
return {
|
||||
_guid: this._guid,
|
||||
objects: Array.from(this._dispatchers.values()).map(o => o._debugScopeState())
|
||||
};
|
||||
}
|
||||
async waitForEventInfo() {
|
||||
// Instrumentation takes care of this.
|
||||
}
|
||||
}
|
||||
exports.Dispatcher = Dispatcher;
|
||||
class RootDispatcher extends Dispatcher {
|
||||
constructor(connection, createPlaywright) {
|
||||
super(connection, {
|
||||
guid: ''
|
||||
}, 'Root', {});
|
||||
this._initialized = false;
|
||||
this.createPlaywright = createPlaywright;
|
||||
}
|
||||
async initialize(params) {
|
||||
(0, _utils.assert)(this.createPlaywright);
|
||||
(0, _utils.assert)(!this._initialized);
|
||||
this._initialized = true;
|
||||
return {
|
||||
playwright: await this.createPlaywright(this, params)
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.RootDispatcher = RootDispatcher;
|
||||
class DispatcherConnection {
|
||||
constructor(isLocal) {
|
||||
this._dispatchers = new Map();
|
||||
this.onmessage = message => {};
|
||||
this._waitOperations = new Map();
|
||||
this._isLocal = void 0;
|
||||
this._isLocal = !!isLocal;
|
||||
}
|
||||
sendEvent(dispatcher, event, params, sdkObject) {
|
||||
const validator = (0, _validator.findValidator)(dispatcher._type, event, 'Event');
|
||||
params = validator(params, '', {
|
||||
tChannelImpl: this._tChannelImplToWire.bind(this),
|
||||
binary: this._isLocal ? 'buffer' : 'toBase64'
|
||||
});
|
||||
this._sendMessageToClient(dispatcher._guid, dispatcher._type, event, params, sdkObject);
|
||||
}
|
||||
sendCreate(parent, type, guid, initializer, sdkObject) {
|
||||
const validator = (0, _validator.findValidator)(type, '', 'Initializer');
|
||||
initializer = validator(initializer, '', {
|
||||
tChannelImpl: this._tChannelImplToWire.bind(this),
|
||||
binary: this._isLocal ? 'buffer' : 'toBase64'
|
||||
});
|
||||
this._sendMessageToClient(parent._guid, type, '__create__', {
|
||||
type,
|
||||
initializer,
|
||||
guid
|
||||
}, sdkObject);
|
||||
}
|
||||
sendAdopt(parent, dispatcher) {
|
||||
this._sendMessageToClient(parent._guid, dispatcher._type, '__adopt__', {
|
||||
guid: dispatcher._guid
|
||||
});
|
||||
}
|
||||
sendDispose(dispatcher) {
|
||||
this._sendMessageToClient(dispatcher._guid, dispatcher._type, '__dispose__', {});
|
||||
}
|
||||
_sendMessageToClient(guid, type, method, params, sdkObject) {
|
||||
if (sdkObject) {
|
||||
var _sdkObject$attributio, _sdkObject$attributio2, _sdkObject$instrument;
|
||||
const event = {
|
||||
type: 'event',
|
||||
class: type,
|
||||
method,
|
||||
params: params || {},
|
||||
time: (0, _utils.monotonicTime)(),
|
||||
pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio = sdkObject.attribution) === null || _sdkObject$attributio === void 0 ? void 0 : (_sdkObject$attributio2 = _sdkObject$attributio.page) === null || _sdkObject$attributio2 === void 0 ? void 0 : _sdkObject$attributio2.guid
|
||||
};
|
||||
(_sdkObject$instrument = sdkObject.instrumentation) === null || _sdkObject$instrument === void 0 ? void 0 : _sdkObject$instrument.onEvent(sdkObject, event);
|
||||
}
|
||||
this.onmessage({
|
||||
guid,
|
||||
method,
|
||||
params
|
||||
});
|
||||
}
|
||||
_tChannelImplFromWire(names, arg, path, context) {
|
||||
if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
|
||||
const guid = arg.guid;
|
||||
const dispatcher = this._dispatchers.get(guid);
|
||||
if (!dispatcher) throw new _validator.ValidationError(`${path}: no object with guid ${guid}`);
|
||||
if (names !== '*' && !names.includes(dispatcher._type)) throw new _validator.ValidationError(`${path}: object with guid ${guid} has type ${dispatcher._type}, expected ${names.toString()}`);
|
||||
return dispatcher;
|
||||
}
|
||||
throw new _validator.ValidationError(`${path}: expected guid for ${names.toString()}`);
|
||||
}
|
||||
_tChannelImplToWire(names, arg, path, context) {
|
||||
if (arg instanceof Dispatcher) {
|
||||
if (names !== '*' && !names.includes(arg._type)) throw new _validator.ValidationError(`${path}: dispatcher with guid ${arg._guid} has type ${arg._type}, expected ${names.toString()}`);
|
||||
return {
|
||||
guid: arg._guid
|
||||
};
|
||||
}
|
||||
throw new _validator.ValidationError(`${path}: expected dispatcher ${names.toString()}`);
|
||||
}
|
||||
async dispatch(message) {
|
||||
var _sdkObject$attributio3, _sdkObject$attributio4, _sdkObject$attributio5, _sdkObject$attributio6, _params$info;
|
||||
const {
|
||||
id,
|
||||
guid,
|
||||
method,
|
||||
params,
|
||||
metadata
|
||||
} = message;
|
||||
const dispatcher = this._dispatchers.get(guid);
|
||||
if (!dispatcher) {
|
||||
this.onmessage({
|
||||
id,
|
||||
error: (0, _serializers.serializeError)(new Error(_errors.kBrowserOrContextClosedError))
|
||||
});
|
||||
return;
|
||||
}
|
||||
let validParams;
|
||||
let validMetadata;
|
||||
try {
|
||||
const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Params');
|
||||
validParams = validator(params, '', {
|
||||
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
||||
binary: this._isLocal ? 'buffer' : 'fromBase64'
|
||||
});
|
||||
validMetadata = metadataValidator(metadata, '', {
|
||||
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
||||
binary: this._isLocal ? 'buffer' : 'fromBase64'
|
||||
});
|
||||
if (typeof dispatcher[method] !== 'function') throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`);
|
||||
} catch (e) {
|
||||
this.onmessage({
|
||||
id,
|
||||
error: (0, _serializers.serializeError)(e)
|
||||
});
|
||||
return;
|
||||
}
|
||||
const sdkObject = dispatcher._object instanceof _instrumentation.SdkObject ? dispatcher._object : undefined;
|
||||
const callMetadata = {
|
||||
id: `call@${id}`,
|
||||
wallTime: validMetadata.wallTime || Date.now(),
|
||||
location: validMetadata.location,
|
||||
apiName: validMetadata.apiName,
|
||||
internal: validMetadata.internal,
|
||||
objectId: sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.guid,
|
||||
pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio3 = sdkObject.attribution) === null || _sdkObject$attributio3 === void 0 ? void 0 : (_sdkObject$attributio4 = _sdkObject$attributio3.page) === null || _sdkObject$attributio4 === void 0 ? void 0 : _sdkObject$attributio4.guid,
|
||||
frameId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio5 = sdkObject.attribution) === null || _sdkObject$attributio5 === void 0 ? void 0 : (_sdkObject$attributio6 = _sdkObject$attributio5.frame) === null || _sdkObject$attributio6 === void 0 ? void 0 : _sdkObject$attributio6.guid,
|
||||
startTime: (0, _utils.monotonicTime)(),
|
||||
endTime: 0,
|
||||
type: dispatcher._type,
|
||||
method,
|
||||
params: params || {},
|
||||
log: []
|
||||
};
|
||||
if (sdkObject && params !== null && params !== void 0 && (_params$info = params.info) !== null && _params$info !== void 0 && _params$info.waitId) {
|
||||
// Process logs for waitForNavigation/waitForLoadState/etc.
|
||||
const info = params.info;
|
||||
switch (info.phase) {
|
||||
case 'before':
|
||||
{
|
||||
this._waitOperations.set(info.waitId, callMetadata);
|
||||
await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata);
|
||||
this.onmessage({
|
||||
id
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'log':
|
||||
{
|
||||
const originalMetadata = this._waitOperations.get(info.waitId);
|
||||
originalMetadata.log.push(info.message);
|
||||
sdkObject.instrumentation.onCallLog(sdkObject, originalMetadata, 'api', info.message);
|
||||
this.onmessage({
|
||||
id
|
||||
});
|
||||
return;
|
||||
}
|
||||
case 'after':
|
||||
{
|
||||
const originalMetadata = this._waitOperations.get(info.waitId);
|
||||
originalMetadata.endTime = (0, _utils.monotonicTime)();
|
||||
originalMetadata.error = info.error ? {
|
||||
error: {
|
||||
name: 'Error',
|
||||
message: info.error
|
||||
}
|
||||
} : undefined;
|
||||
this._waitOperations.delete(info.waitId);
|
||||
await sdkObject.instrumentation.onAfterCall(sdkObject, originalMetadata);
|
||||
this.onmessage({
|
||||
id
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
let error;
|
||||
await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata));
|
||||
try {
|
||||
const result = await dispatcher[method](validParams, callMetadata);
|
||||
const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Result');
|
||||
callMetadata.result = validator(result, '', {
|
||||
tChannelImpl: this._tChannelImplToWire.bind(this),
|
||||
binary: this._isLocal ? 'buffer' : 'toBase64'
|
||||
});
|
||||
} catch (e) {
|
||||
// Dispatching error
|
||||
// We want original, unmodified error in metadata.
|
||||
callMetadata.error = (0, _serializers.serializeError)(e);
|
||||
if (callMetadata.log.length) (0, _stackTrace.rewriteErrorMessage)(e, e.message + formatLogRecording(callMetadata.log));
|
||||
error = (0, _serializers.serializeError)(e);
|
||||
} finally {
|
||||
callMetadata.endTime = (0, _utils.monotonicTime)();
|
||||
await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata));
|
||||
}
|
||||
const response = {
|
||||
id
|
||||
};
|
||||
if (callMetadata.result) response.result = callMetadata.result;
|
||||
if (error) response.error = error;
|
||||
this.onmessage(response);
|
||||
}
|
||||
}
|
||||
exports.DispatcherConnection = DispatcherConnection;
|
||||
function formatLogRecording(log) {
|
||||
if (!log.length) return '';
|
||||
const header = ` logs `;
|
||||
const headerLength = 60;
|
||||
const leftLength = (headerLength - header.length) / 2;
|
||||
const rightLength = headerLength - header.length - leftLength;
|
||||
return `\n${'='.repeat(leftLength)}${header}${'='.repeat(rightLength)}\n${log.join('\n')}\n${'='.repeat(headerLength)}`;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ElectronDispatcher = exports.ElectronApplicationDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _electron = require("../electron/electron");
|
||||
var _browserContextDispatcher = require("./browserContextDispatcher");
|
||||
var _jsHandleDispatcher = require("./jsHandleDispatcher");
|
||||
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ElectronDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, electron) {
|
||||
super(scope, electron, 'Electron', {});
|
||||
this._type_Electron = true;
|
||||
}
|
||||
async launch(params) {
|
||||
const electronApplication = await this._object.launch(params);
|
||||
return {
|
||||
electronApplication: new ElectronApplicationDispatcher(this, electronApplication)
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.ElectronDispatcher = ElectronDispatcher;
|
||||
class ElectronApplicationDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, electronApplication) {
|
||||
super(scope, electronApplication, 'ElectronApplication', {
|
||||
context: new _browserContextDispatcher.BrowserContextDispatcher(scope, electronApplication.context())
|
||||
});
|
||||
this._type_EventTarget = true;
|
||||
this._type_ElectronApplication = true;
|
||||
this.addObjectListener(_electron.ElectronApplication.Events.Close, () => {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
});
|
||||
}
|
||||
async browserWindow(params) {
|
||||
const handle = await this._object.browserWindow(params.page.page());
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, handle)
|
||||
};
|
||||
}
|
||||
async evaluateExpression(params) {
|
||||
const handle = await this._object._nodeElectronHandlePromise;
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await handle.evaluateExpression(params.expression, {
|
||||
isFunction: params.isFunction
|
||||
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async evaluateExpressionHandle(params) {
|
||||
const handle = await this._object._nodeElectronHandlePromise;
|
||||
const result = await handle.evaluateExpressionHandle(params.expression, {
|
||||
isFunction: params.isFunction
|
||||
}, (0, _jsHandleDispatcher.parseArgument)(params.arg));
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, result)
|
||||
};
|
||||
}
|
||||
async close() {
|
||||
await this._object.close();
|
||||
}
|
||||
}
|
||||
exports.ElectronApplicationDispatcher = ElectronApplicationDispatcher;
|
||||
@@ -0,0 +1,233 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ElementHandleDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _jsHandleDispatcher = require("./jsHandleDispatcher");
|
||||
var _frameDispatcher = require("./frameDispatcher");
|
||||
var _utils = require("../../utils");
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class ElementHandleDispatcher extends _jsHandleDispatcher.JSHandleDispatcher {
|
||||
static from(scope, handle) {
|
||||
return (0, _dispatcher.existingDispatcher)(handle) || new ElementHandleDispatcher(scope, handle);
|
||||
}
|
||||
static fromNullable(scope, handle) {
|
||||
if (!handle) return undefined;
|
||||
return (0, _dispatcher.existingDispatcher)(handle) || new ElementHandleDispatcher(scope, handle);
|
||||
}
|
||||
static fromJSHandle(scope, handle) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(handle);
|
||||
if (result) return result;
|
||||
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()) : new _jsHandleDispatcher.JSHandleDispatcher(scope, handle);
|
||||
}
|
||||
constructor(scope, elementHandle) {
|
||||
super(scope, elementHandle);
|
||||
this._type_ElementHandle = true;
|
||||
this._elementHandle = void 0;
|
||||
this._elementHandle = elementHandle;
|
||||
}
|
||||
async ownerFrame(params, metadata) {
|
||||
const frame = await this._elementHandle.ownerFrame();
|
||||
return {
|
||||
frame: frame ? _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) : undefined
|
||||
};
|
||||
}
|
||||
async contentFrame(params, metadata) {
|
||||
const frame = await this._elementHandle.contentFrame();
|
||||
return {
|
||||
frame: frame ? _frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) : undefined
|
||||
};
|
||||
}
|
||||
async getAttribute(params, metadata) {
|
||||
const value = await this._elementHandle.getAttribute(params.name);
|
||||
return {
|
||||
value: value === null ? undefined : value
|
||||
};
|
||||
}
|
||||
async inputValue(params, metadata) {
|
||||
const value = await this._elementHandle.inputValue();
|
||||
return {
|
||||
value
|
||||
};
|
||||
}
|
||||
async textContent(params, metadata) {
|
||||
const value = await this._elementHandle.textContent();
|
||||
return {
|
||||
value: value === null ? undefined : value
|
||||
};
|
||||
}
|
||||
async innerText(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.innerText()
|
||||
};
|
||||
}
|
||||
async innerHTML(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.innerHTML()
|
||||
};
|
||||
}
|
||||
async isChecked(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isChecked()
|
||||
};
|
||||
}
|
||||
async isDisabled(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isDisabled()
|
||||
};
|
||||
}
|
||||
async isEditable(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isEditable()
|
||||
};
|
||||
}
|
||||
async isEnabled(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isEnabled()
|
||||
};
|
||||
}
|
||||
async isHidden(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isHidden()
|
||||
};
|
||||
}
|
||||
async isVisible(params, metadata) {
|
||||
return {
|
||||
value: await this._elementHandle.isVisible()
|
||||
};
|
||||
}
|
||||
async dispatchEvent(params, metadata) {
|
||||
await this._elementHandle.dispatchEvent(params.type, (0, _jsHandleDispatcher.parseArgument)(params.eventInit));
|
||||
}
|
||||
async scrollIntoViewIfNeeded(params, metadata) {
|
||||
await this._elementHandle.scrollIntoViewIfNeeded(metadata, params);
|
||||
}
|
||||
async hover(params, metadata) {
|
||||
return await this._elementHandle.hover(metadata, params);
|
||||
}
|
||||
async click(params, metadata) {
|
||||
return await this._elementHandle.click(metadata, params);
|
||||
}
|
||||
async dblclick(params, metadata) {
|
||||
return await this._elementHandle.dblclick(metadata, params);
|
||||
}
|
||||
async tap(params, metadata) {
|
||||
return await this._elementHandle.tap(metadata, params);
|
||||
}
|
||||
async selectOption(params, metadata) {
|
||||
const elements = (params.elements || []).map(e => e._elementHandle);
|
||||
return {
|
||||
values: await this._elementHandle.selectOption(metadata, elements, params.options || [], params)
|
||||
};
|
||||
}
|
||||
async fill(params, metadata) {
|
||||
return await this._elementHandle.fill(metadata, params.value, params);
|
||||
}
|
||||
async selectText(params, metadata) {
|
||||
await this._elementHandle.selectText(metadata, params);
|
||||
}
|
||||
async setInputFiles(params, metadata) {
|
||||
return await this._elementHandle.setInputFiles(metadata, {
|
||||
files: params.files
|
||||
}, params);
|
||||
}
|
||||
async setInputFilePaths(params, metadata) {
|
||||
let {
|
||||
localPaths
|
||||
} = params;
|
||||
if (!localPaths) {
|
||||
if (!params.streams) throw new Error('Neither localPaths nor streams is specified');
|
||||
localPaths = params.streams.map(c => c.path());
|
||||
}
|
||||
for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
|
||||
return await this._elementHandle.setInputFiles(metadata, {
|
||||
localPaths
|
||||
}, params);
|
||||
}
|
||||
async focus(params, metadata) {
|
||||
await this._elementHandle.focus(metadata);
|
||||
}
|
||||
async type(params, metadata) {
|
||||
return await this._elementHandle.type(metadata, params.text, params);
|
||||
}
|
||||
async press(params, metadata) {
|
||||
return await this._elementHandle.press(metadata, params.key, params);
|
||||
}
|
||||
async check(params, metadata) {
|
||||
return await this._elementHandle.check(metadata, params);
|
||||
}
|
||||
async uncheck(params, metadata) {
|
||||
return await this._elementHandle.uncheck(metadata, params);
|
||||
}
|
||||
async boundingBox(params, metadata) {
|
||||
const value = await this._elementHandle.boundingBox();
|
||||
return {
|
||||
value: value || undefined
|
||||
};
|
||||
}
|
||||
async screenshot(params, metadata) {
|
||||
const mask = (params.mask || []).map(({
|
||||
frame,
|
||||
selector
|
||||
}) => ({
|
||||
frame: frame._object,
|
||||
selector
|
||||
}));
|
||||
return {
|
||||
binary: await this._elementHandle.screenshot(metadata, {
|
||||
...params,
|
||||
mask
|
||||
})
|
||||
};
|
||||
}
|
||||
async querySelector(params, metadata) {
|
||||
const handle = await this._elementHandle.querySelector(params.selector, params);
|
||||
return {
|
||||
element: ElementHandleDispatcher.fromNullable(this.parentScope(), handle)
|
||||
};
|
||||
}
|
||||
async querySelectorAll(params, metadata) {
|
||||
const elements = await this._elementHandle.querySelectorAll(params.selector);
|
||||
return {
|
||||
elements: elements.map(e => ElementHandleDispatcher.from(this.parentScope(), e))
|
||||
};
|
||||
}
|
||||
async evalOnSelector(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._elementHandle.evalOnSelector(params.selector, !!params.strict, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async evalOnSelectorAll(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._elementHandle.evalOnSelectorAll(params.selector, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async waitForElementState(params, metadata) {
|
||||
await this._elementHandle.waitForElementState(metadata, params.state, params);
|
||||
}
|
||||
async waitForSelector(params, metadata) {
|
||||
return {
|
||||
element: ElementHandleDispatcher.fromNullable(this.parentScope(), await this._elementHandle.waitForSelector(metadata, params.selector, params))
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.ElementHandleDispatcher = ElementHandleDispatcher;
|
||||
@@ -0,0 +1,300 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.FrameDispatcher = void 0;
|
||||
var _frames = require("../frames");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
||||
var _jsHandleDispatcher = require("./jsHandleDispatcher");
|
||||
var _networkDispatchers = require("./networkDispatchers");
|
||||
var _utils = require("../../utils");
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class FrameDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, frame) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(frame);
|
||||
return result || new FrameDispatcher(scope, frame);
|
||||
}
|
||||
static fromNullable(scope, frame) {
|
||||
if (!frame) return;
|
||||
return FrameDispatcher.from(scope, frame);
|
||||
}
|
||||
constructor(scope, frame) {
|
||||
super(scope, frame, 'Frame', {
|
||||
url: frame.url(),
|
||||
name: frame.name(),
|
||||
parentFrame: FrameDispatcher.fromNullable(scope, frame.parentFrame()),
|
||||
loadStates: Array.from(frame._firedLifecycleEvents)
|
||||
});
|
||||
this._type_Frame = true;
|
||||
this._frame = void 0;
|
||||
this._frame = frame;
|
||||
this.addObjectListener(_frames.Frame.Events.AddLifecycle, lifecycleEvent => {
|
||||
this._dispatchEvent('loadstate', {
|
||||
add: lifecycleEvent
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_frames.Frame.Events.RemoveLifecycle, lifecycleEvent => {
|
||||
this._dispatchEvent('loadstate', {
|
||||
remove: lifecycleEvent
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_frames.Frame.Events.InternalNavigation, event => {
|
||||
if (!event.isPublic) return;
|
||||
const params = {
|
||||
url: event.url,
|
||||
name: event.name,
|
||||
error: event.error ? event.error.message : undefined
|
||||
};
|
||||
if (event.newDocument) params.newDocument = {
|
||||
request: _networkDispatchers.RequestDispatcher.fromNullable(this.parentScope().parentScope(), event.newDocument.request || null)
|
||||
};
|
||||
this._dispatchEvent('navigated', params);
|
||||
});
|
||||
}
|
||||
async goto(params, metadata) {
|
||||
return {
|
||||
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope().parentScope(), await this._frame.goto(metadata, params.url, params))
|
||||
};
|
||||
}
|
||||
async frameElement() {
|
||||
return {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.frameElement())
|
||||
};
|
||||
}
|
||||
async evaluateExpression(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evaluateExpression(params.expression, {
|
||||
isFunction: params.isFunction,
|
||||
exposeUtilityScript: params.exposeUtilityScript
|
||||
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async evaluateExpressionHandle(params, metadata) {
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), await this._frame.evaluateExpressionHandle(params.expression, {
|
||||
isFunction: params.isFunction
|
||||
}, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async waitForSelector(params, metadata) {
|
||||
return {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.fromNullable(this.parentScope(), await this._frame.waitForSelector(metadata, params.selector, params))
|
||||
};
|
||||
}
|
||||
async dispatchEvent(params, metadata) {
|
||||
return this._frame.dispatchEvent(metadata, params.selector, params.type, (0, _jsHandleDispatcher.parseArgument)(params.eventInit), params);
|
||||
}
|
||||
async evalOnSelector(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evalOnSelector(params.selector, !!params.strict, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async evalOnSelectorAll(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._frame.evalOnSelectorAll(params.selector, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async querySelector(params, metadata) {
|
||||
return {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.fromNullable(this.parentScope(), await this._frame.querySelector(params.selector, params))
|
||||
};
|
||||
}
|
||||
async querySelectorAll(params, metadata) {
|
||||
const elements = await this._frame.querySelectorAll(params.selector);
|
||||
return {
|
||||
elements: elements.map(e => _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), e))
|
||||
};
|
||||
}
|
||||
async queryCount(params) {
|
||||
return {
|
||||
value: await this._frame.queryCount(params.selector)
|
||||
};
|
||||
}
|
||||
async content() {
|
||||
return {
|
||||
value: await this._frame.content()
|
||||
};
|
||||
}
|
||||
async setContent(params, metadata) {
|
||||
return await this._frame.setContent(metadata, params.html, params);
|
||||
}
|
||||
async addScriptTag(params, metadata) {
|
||||
return {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.addScriptTag(params))
|
||||
};
|
||||
}
|
||||
async addStyleTag(params, metadata) {
|
||||
return {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this.parentScope(), await this._frame.addStyleTag(params))
|
||||
};
|
||||
}
|
||||
async click(params, metadata) {
|
||||
return await this._frame.click(metadata, params.selector, params);
|
||||
}
|
||||
async dblclick(params, metadata) {
|
||||
return await this._frame.dblclick(metadata, params.selector, params);
|
||||
}
|
||||
async dragAndDrop(params, metadata) {
|
||||
return await this._frame.dragAndDrop(metadata, params.source, params.target, params);
|
||||
}
|
||||
async tap(params, metadata) {
|
||||
return await this._frame.tap(metadata, params.selector, params);
|
||||
}
|
||||
async fill(params, metadata) {
|
||||
return await this._frame.fill(metadata, params.selector, params.value, params);
|
||||
}
|
||||
async focus(params, metadata) {
|
||||
await this._frame.focus(metadata, params.selector, params);
|
||||
}
|
||||
async blur(params, metadata) {
|
||||
await this._frame.blur(metadata, params.selector, params);
|
||||
}
|
||||
async textContent(params, metadata) {
|
||||
const value = await this._frame.textContent(metadata, params.selector, params);
|
||||
return {
|
||||
value: value === null ? undefined : value
|
||||
};
|
||||
}
|
||||
async innerText(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.innerText(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async innerHTML(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.innerHTML(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async getAttribute(params, metadata) {
|
||||
const value = await this._frame.getAttribute(metadata, params.selector, params.name, params);
|
||||
return {
|
||||
value: value === null ? undefined : value
|
||||
};
|
||||
}
|
||||
async inputValue(params, metadata) {
|
||||
const value = await this._frame.inputValue(metadata, params.selector, params);
|
||||
return {
|
||||
value
|
||||
};
|
||||
}
|
||||
async isChecked(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isChecked(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async isDisabled(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isDisabled(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async isEditable(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isEditable(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async isEnabled(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isEnabled(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async isHidden(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isHidden(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async isVisible(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.isVisible(metadata, params.selector, params)
|
||||
};
|
||||
}
|
||||
async hover(params, metadata) {
|
||||
return await this._frame.hover(metadata, params.selector, params);
|
||||
}
|
||||
async selectOption(params, metadata) {
|
||||
const elements = (params.elements || []).map(e => e._elementHandle);
|
||||
return {
|
||||
values: await this._frame.selectOption(metadata, params.selector, elements, params.options || [], params)
|
||||
};
|
||||
}
|
||||
async setInputFiles(params, metadata) {
|
||||
return await this._frame.setInputFiles(metadata, params.selector, {
|
||||
files: params.files
|
||||
}, params);
|
||||
}
|
||||
async setInputFilePaths(params, metadata) {
|
||||
let {
|
||||
localPaths
|
||||
} = params;
|
||||
if (!localPaths) {
|
||||
if (!params.streams) throw new Error('Neither localPaths nor streams is specified');
|
||||
localPaths = params.streams.map(c => c.path());
|
||||
}
|
||||
for (const p of localPaths) (0, _utils.assert)(_path.default.isAbsolute(p) && _path.default.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
|
||||
return await this._frame.setInputFiles(metadata, params.selector, {
|
||||
localPaths
|
||||
}, params);
|
||||
}
|
||||
async type(params, metadata) {
|
||||
return await this._frame.type(metadata, params.selector, params.text, params);
|
||||
}
|
||||
async press(params, metadata) {
|
||||
return await this._frame.press(metadata, params.selector, params.key, params);
|
||||
}
|
||||
async check(params, metadata) {
|
||||
return await this._frame.check(metadata, params.selector, params);
|
||||
}
|
||||
async uncheck(params, metadata) {
|
||||
return await this._frame.uncheck(metadata, params.selector, params);
|
||||
}
|
||||
async waitForTimeout(params, metadata) {
|
||||
return await this._frame.waitForTimeout(metadata, params.timeout);
|
||||
}
|
||||
async waitForFunction(params, metadata) {
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), await this._frame._waitForFunctionExpression(metadata, params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg), params))
|
||||
};
|
||||
}
|
||||
async title(params, metadata) {
|
||||
return {
|
||||
value: await this._frame.title()
|
||||
};
|
||||
}
|
||||
async highlight(params, metadata) {
|
||||
return await this._frame.highlight(params.selector);
|
||||
}
|
||||
async expect(params, metadata) {
|
||||
const expectedValue = params.expectedValue ? (0, _jsHandleDispatcher.parseArgument)(params.expectedValue) : undefined;
|
||||
const result = await this._frame.expect(metadata, params.selector, {
|
||||
...params,
|
||||
expectedValue
|
||||
});
|
||||
if (result.received !== undefined) result.received = (0, _jsHandleDispatcher.serializeResult)(result.received);
|
||||
if (result.matches === params.isNot) metadata.error = {
|
||||
error: {
|
||||
name: 'Expect',
|
||||
message: 'Expect failed'
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.FrameDispatcher = FrameDispatcher;
|
||||
@@ -0,0 +1,100 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.JSHandleDispatcher = void 0;
|
||||
exports.parseArgument = parseArgument;
|
||||
exports.parseValue = parseValue;
|
||||
exports.serializeResult = serializeResult;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
||||
var _serializers = require("../../protocol/serializers");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class JSHandleDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, jsHandle) {
|
||||
// Do not call this directly, use createHandle() instead.
|
||||
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
|
||||
preview: jsHandle.toString()
|
||||
});
|
||||
this._type_JSHandle = true;
|
||||
jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', {
|
||||
preview
|
||||
}));
|
||||
}
|
||||
async evaluateExpression(params) {
|
||||
return {
|
||||
value: serializeResult(await this._object.evaluateExpression(params.expression, {
|
||||
isFunction: params.isFunction
|
||||
}, parseArgument(params.arg)))
|
||||
};
|
||||
}
|
||||
async evaluateExpressionHandle(params) {
|
||||
const jsHandle = await this._object.evaluateExpressionHandle(params.expression, {
|
||||
isFunction: params.isFunction
|
||||
}, parseArgument(params.arg));
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), jsHandle)
|
||||
};
|
||||
}
|
||||
async getProperty(params) {
|
||||
const jsHandle = await this._object.getProperty(params.name);
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), jsHandle)
|
||||
};
|
||||
}
|
||||
async getPropertyList() {
|
||||
const map = await this._object.getProperties();
|
||||
const properties = [];
|
||||
for (const [name, value] of map) properties.push({
|
||||
name,
|
||||
value: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this.parentScope(), value)
|
||||
});
|
||||
return {
|
||||
properties
|
||||
};
|
||||
}
|
||||
async jsonValue() {
|
||||
return {
|
||||
value: serializeResult(await this._object.jsonValue())
|
||||
};
|
||||
}
|
||||
async objectCount(params) {
|
||||
return {
|
||||
count: await this._object.objectCount()
|
||||
};
|
||||
}
|
||||
async dispose() {
|
||||
await this._object.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Generic channel parser converts guids to JSHandleDispatchers,
|
||||
// and this function takes care of coverting them into underlying JSHandles.
|
||||
exports.JSHandleDispatcher = JSHandleDispatcher;
|
||||
function parseArgument(arg) {
|
||||
return (0, _serializers.parseSerializedValue)(arg.value, arg.handles.map(a => a._object));
|
||||
}
|
||||
function parseValue(v) {
|
||||
return (0, _serializers.parseSerializedValue)(v, []);
|
||||
}
|
||||
function serializeResult(arg) {
|
||||
return (0, _serializers.serializeValue)(arg, value => ({
|
||||
fallThrough: value
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.JsonPipeDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _utils = require("../../utils");
|
||||
var _serializers = require("../../protocol/serializers");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class JsonPipeDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope) {
|
||||
super(scope, {
|
||||
guid: 'jsonPipe@' + (0, _utils.createGuid)()
|
||||
}, 'JsonPipe', {});
|
||||
this._type_JsonPipe = true;
|
||||
}
|
||||
async send(params) {
|
||||
this.emit('message', params.message);
|
||||
}
|
||||
async close() {
|
||||
this.emit('close');
|
||||
if (!this._disposed) {
|
||||
this._dispatchEvent('closed', {});
|
||||
this._dispose();
|
||||
}
|
||||
}
|
||||
dispatch(message) {
|
||||
if (!this._disposed) this._dispatchEvent('message', {
|
||||
message
|
||||
});
|
||||
}
|
||||
wasClosed(error) {
|
||||
if (!this._disposed) {
|
||||
const params = error ? {
|
||||
error: (0, _serializers.serializeError)(error)
|
||||
} : {};
|
||||
this._dispatchEvent('closed', params);
|
||||
this._dispose();
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
this._dispose();
|
||||
}
|
||||
}
|
||||
exports.JsonPipeDispatcher = JsonPipeDispatcher;
|
||||
@@ -0,0 +1,392 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.LocalUtilsDispatcher = void 0;
|
||||
exports.urlToWSEndpoint = urlToWSEndpoint;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _os = _interopRequireDefault(require("os"));
|
||||
var _manualPromise = require("../../utils/manualPromise");
|
||||
var _utils = require("../../utils");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _zipBundle = require("../../zipBundle");
|
||||
var _zipFile = require("../../utils/zipFile");
|
||||
var _jsonPipeDispatcher = require("../dispatchers/jsonPipeDispatcher");
|
||||
var _transport = require("../transport");
|
||||
var _socksInterceptor = require("../socksInterceptor");
|
||||
var _userAgent = require("../../utils/userAgent");
|
||||
var _progress = require("../progress");
|
||||
var _network = require("../../utils/network");
|
||||
var _instrumentation = require("../../server/instrumentation");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class LocalUtilsDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, playwright) {
|
||||
const localUtils = new _instrumentation.SdkObject(playwright, 'localUtils', 'localUtils');
|
||||
super(scope, localUtils, 'LocalUtils', {});
|
||||
this._type_LocalUtils = void 0;
|
||||
this._harBackends = new Map();
|
||||
this._stackSessions = new Map();
|
||||
this._type_LocalUtils = true;
|
||||
}
|
||||
async zip(params) {
|
||||
const promise = new _manualPromise.ManualPromise();
|
||||
const zipFile = new _zipBundle.yazl.ZipFile();
|
||||
zipFile.on('error', error => promise.reject(error));
|
||||
const addFile = (file, name) => {
|
||||
try {
|
||||
if (_fs.default.statSync(file).isFile()) zipFile.addFile(file, name);
|
||||
} catch (e) {}
|
||||
};
|
||||
for (const entry of params.entries) addFile(entry.value, entry.name);
|
||||
|
||||
// Add stacks and the sources.
|
||||
const stackSession = params.stacksId ? this._stackSessions.get(params.stacksId) : undefined;
|
||||
if (stackSession !== null && stackSession !== void 0 && stackSession.callStacks.length) {
|
||||
await stackSession.writer;
|
||||
if (process.env.PW_LIVE_TRACE_STACKS) {
|
||||
zipFile.addFile(stackSession.file, 'trace.stacks');
|
||||
} else {
|
||||
const buffer = Buffer.from(JSON.stringify((0, _utils.serializeClientSideCallMetadata)(stackSession.callStacks)));
|
||||
zipFile.addBuffer(buffer, 'trace.stacks');
|
||||
}
|
||||
}
|
||||
|
||||
// Collect sources from stacks.
|
||||
if (params.includeSources) {
|
||||
const sourceFiles = new Set();
|
||||
for (const {
|
||||
stack
|
||||
} of (stackSession === null || stackSession === void 0 ? void 0 : stackSession.callStacks) || []) {
|
||||
if (!stack) continue;
|
||||
for (const {
|
||||
file
|
||||
} of stack) sourceFiles.add(file);
|
||||
}
|
||||
for (const sourceFile of sourceFiles) addFile(sourceFile, 'resources/src@' + (0, _utils.calculateSha1)(sourceFile) + '.txt');
|
||||
}
|
||||
if (params.mode === 'write') {
|
||||
// New file, just compress the entries.
|
||||
await _fs.default.promises.mkdir(_path.default.dirname(params.zipFile), {
|
||||
recursive: true
|
||||
});
|
||||
zipFile.end(undefined, () => {
|
||||
zipFile.outputStream.pipe(_fs.default.createWriteStream(params.zipFile)).on('close', () => promise.resolve());
|
||||
});
|
||||
await promise;
|
||||
await this._deleteStackSession(params.stacksId);
|
||||
return;
|
||||
}
|
||||
|
||||
// File already exists. Repack and add new entries.
|
||||
const tempFile = params.zipFile + '.tmp';
|
||||
await _fs.default.promises.rename(params.zipFile, tempFile);
|
||||
_zipBundle.yauzl.open(tempFile, (err, inZipFile) => {
|
||||
if (err) {
|
||||
promise.reject(err);
|
||||
return;
|
||||
}
|
||||
(0, _utils.assert)(inZipFile);
|
||||
let pendingEntries = inZipFile.entryCount;
|
||||
inZipFile.on('entry', entry => {
|
||||
inZipFile.openReadStream(entry, (err, readStream) => {
|
||||
if (err) {
|
||||
promise.reject(err);
|
||||
return;
|
||||
}
|
||||
zipFile.addReadStream(readStream, entry.fileName);
|
||||
if (--pendingEntries === 0) {
|
||||
zipFile.end(undefined, () => {
|
||||
zipFile.outputStream.pipe(_fs.default.createWriteStream(params.zipFile)).on('close', () => {
|
||||
_fs.default.promises.unlink(tempFile).then(() => {
|
||||
promise.resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
await promise;
|
||||
await this._deleteStackSession(params.stacksId);
|
||||
}
|
||||
async harOpen(params, metadata) {
|
||||
let harBackend;
|
||||
if (params.file.endsWith('.zip')) {
|
||||
const zipFile = new _zipFile.ZipFile(params.file);
|
||||
const entryNames = await zipFile.entries();
|
||||
const harEntryName = entryNames.find(e => e.endsWith('.har'));
|
||||
if (!harEntryName) return {
|
||||
error: 'Specified archive does not have a .har file'
|
||||
};
|
||||
const har = await zipFile.read(harEntryName);
|
||||
const harFile = JSON.parse(har.toString());
|
||||
harBackend = new HarBackend(harFile, null, zipFile);
|
||||
} else {
|
||||
const harFile = JSON.parse(await _fs.default.promises.readFile(params.file, 'utf-8'));
|
||||
harBackend = new HarBackend(harFile, _path.default.dirname(params.file), null);
|
||||
}
|
||||
this._harBackends.set(harBackend.id, harBackend);
|
||||
return {
|
||||
harId: harBackend.id
|
||||
};
|
||||
}
|
||||
async harLookup(params, metadata) {
|
||||
const harBackend = this._harBackends.get(params.harId);
|
||||
if (!harBackend) return {
|
||||
action: 'error',
|
||||
message: `Internal error: har was not opened`
|
||||
};
|
||||
return await harBackend.lookup(params.url, params.method, params.headers, params.postData, params.isNavigationRequest);
|
||||
}
|
||||
async harClose(params, metadata) {
|
||||
const harBackend = this._harBackends.get(params.harId);
|
||||
if (harBackend) {
|
||||
this._harBackends.delete(harBackend.id);
|
||||
harBackend.dispose();
|
||||
}
|
||||
}
|
||||
async harUnzip(params, metadata) {
|
||||
const dir = _path.default.dirname(params.zipFile);
|
||||
const zipFile = new _zipFile.ZipFile(params.zipFile);
|
||||
for (const entry of await zipFile.entries()) {
|
||||
const buffer = await zipFile.read(entry);
|
||||
if (entry === 'har.har') await _fs.default.promises.writeFile(params.harFile, buffer);else await _fs.default.promises.writeFile(_path.default.join(dir, entry), buffer);
|
||||
}
|
||||
zipFile.close();
|
||||
await _fs.default.promises.unlink(params.zipFile);
|
||||
}
|
||||
async connect(params, metadata) {
|
||||
const controller = new _progress.ProgressController(metadata, this._object);
|
||||
controller.setLogName('browser');
|
||||
return await controller.run(async progress => {
|
||||
var _params$exposeNetwork;
|
||||
const wsHeaders = {
|
||||
'User-Agent': (0, _userAgent.getUserAgent)(),
|
||||
'x-playwright-proxy': (_params$exposeNetwork = params.exposeNetwork) !== null && _params$exposeNetwork !== void 0 ? _params$exposeNetwork : '',
|
||||
...params.headers
|
||||
};
|
||||
const wsEndpoint = await urlToWSEndpoint(progress, params.wsEndpoint);
|
||||
const transport = await _transport.WebSocketTransport.connect(progress, wsEndpoint, wsHeaders, true, 'x-playwright-debug-log');
|
||||
const socksInterceptor = new _socksInterceptor.SocksInterceptor(transport, params.exposeNetwork, params.socksProxyRedirectPortForTest);
|
||||
const pipe = new _jsonPipeDispatcher.JsonPipeDispatcher(this);
|
||||
transport.onmessage = json => {
|
||||
if (socksInterceptor.interceptMessage(json)) return;
|
||||
const cb = () => {
|
||||
try {
|
||||
pipe.dispatch(json);
|
||||
} catch (e) {
|
||||
transport.close();
|
||||
}
|
||||
};
|
||||
if (params.slowMo) setTimeout(cb, params.slowMo);else cb();
|
||||
};
|
||||
pipe.on('message', message => {
|
||||
transport.send(message);
|
||||
});
|
||||
transport.onclose = () => {
|
||||
socksInterceptor === null || socksInterceptor === void 0 ? void 0 : socksInterceptor.cleanup();
|
||||
pipe.wasClosed();
|
||||
};
|
||||
pipe.on('close', () => transport.close());
|
||||
return {
|
||||
pipe,
|
||||
headers: transport.headers
|
||||
};
|
||||
}, params.timeout || 0);
|
||||
}
|
||||
async tracingStarted(params, metadata) {
|
||||
let tmpDir = undefined;
|
||||
if (!params.tracesDir) tmpDir = await _fs.default.promises.mkdtemp(_path.default.join(_os.default.tmpdir(), 'playwright-tracing-'));
|
||||
const traceStacksFile = _path.default.join(params.tracesDir || tmpDir, params.traceName + '.stacks');
|
||||
this._stackSessions.set(traceStacksFile, {
|
||||
callStacks: [],
|
||||
file: traceStacksFile,
|
||||
writer: Promise.resolve(),
|
||||
tmpDir
|
||||
});
|
||||
return {
|
||||
stacksId: traceStacksFile
|
||||
};
|
||||
}
|
||||
async traceDiscarded(params, metadata) {
|
||||
await this._deleteStackSession(params.stacksId);
|
||||
}
|
||||
async addStackToTracingNoReply(params, metadata) {
|
||||
for (const session of this._stackSessions.values()) {
|
||||
session.callStacks.push(params.callData);
|
||||
if (process.env.PW_LIVE_TRACE_STACKS) {
|
||||
session.writer = session.writer.then(() => {
|
||||
const buffer = Buffer.from(JSON.stringify((0, _utils.serializeClientSideCallMetadata)(session.callStacks)));
|
||||
return _fs.default.promises.writeFile(session.file, buffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
async _deleteStackSession(stacksId) {
|
||||
const session = stacksId ? this._stackSessions.get(stacksId) : undefined;
|
||||
if (!session) return;
|
||||
await session.writer;
|
||||
if (session.tmpDir) await (0, _utils.removeFolders)([session.tmpDir]);
|
||||
this._stackSessions.delete(stacksId);
|
||||
}
|
||||
}
|
||||
exports.LocalUtilsDispatcher = LocalUtilsDispatcher;
|
||||
const redirectStatus = [301, 302, 303, 307, 308];
|
||||
class HarBackend {
|
||||
constructor(harFile, baseDir, zipFile) {
|
||||
this.id = (0, _utils.createGuid)();
|
||||
this._harFile = void 0;
|
||||
this._zipFile = void 0;
|
||||
this._baseDir = void 0;
|
||||
this._harFile = harFile;
|
||||
this._baseDir = baseDir;
|
||||
this._zipFile = zipFile;
|
||||
}
|
||||
async lookup(url, method, headers, postData, isNavigationRequest) {
|
||||
let entry;
|
||||
try {
|
||||
entry = await this._harFindResponse(url, method, headers, postData);
|
||||
} catch (e) {
|
||||
return {
|
||||
action: 'error',
|
||||
message: 'HAR error: ' + e.message
|
||||
};
|
||||
}
|
||||
if (!entry) return {
|
||||
action: 'noentry'
|
||||
};
|
||||
|
||||
// If navigation is being redirected, restart it with the final url to ensure the document's url changes.
|
||||
if (entry.request.url !== url && isNavigationRequest) return {
|
||||
action: 'redirect',
|
||||
redirectURL: entry.request.url
|
||||
};
|
||||
const response = entry.response;
|
||||
try {
|
||||
const buffer = await this._loadContent(response.content);
|
||||
return {
|
||||
action: 'fulfill',
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
body: buffer
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
action: 'error',
|
||||
message: e.message
|
||||
};
|
||||
}
|
||||
}
|
||||
async _loadContent(content) {
|
||||
const file = content._file;
|
||||
let buffer;
|
||||
if (file) {
|
||||
if (this._zipFile) buffer = await this._zipFile.read(file);else buffer = await _fs.default.promises.readFile(_path.default.resolve(this._baseDir, file));
|
||||
} else {
|
||||
buffer = Buffer.from(content.text || '', content.encoding === 'base64' ? 'base64' : 'utf-8');
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
async _harFindResponse(url, method, headers, postData) {
|
||||
const harLog = this._harFile.log;
|
||||
const visited = new Set();
|
||||
while (true) {
|
||||
const entries = [];
|
||||
for (const candidate of harLog.entries) {
|
||||
if (candidate.request.url !== url || candidate.request.method !== method) continue;
|
||||
if (method === 'POST' && postData && candidate.request.postData) {
|
||||
const buffer = await this._loadContent(candidate.request.postData);
|
||||
if (!buffer.equals(postData)) continue;
|
||||
}
|
||||
entries.push(candidate);
|
||||
}
|
||||
if (!entries.length) return;
|
||||
let entry = entries[0];
|
||||
|
||||
// Disambiguate using headers - then one with most matching headers wins.
|
||||
if (entries.length > 1) {
|
||||
const list = [];
|
||||
for (const candidate of entries) {
|
||||
const matchingHeaders = countMatchingHeaders(candidate.request.headers, headers);
|
||||
list.push({
|
||||
candidate,
|
||||
matchingHeaders
|
||||
});
|
||||
}
|
||||
list.sort((a, b) => b.matchingHeaders - a.matchingHeaders);
|
||||
entry = list[0].candidate;
|
||||
}
|
||||
if (visited.has(entry)) throw new Error(`Found redirect cycle for ${url}`);
|
||||
visited.add(entry);
|
||||
|
||||
// Follow redirects.
|
||||
const locationHeader = entry.response.headers.find(h => h.name.toLowerCase() === 'location');
|
||||
if (redirectStatus.includes(entry.response.status) && locationHeader) {
|
||||
const locationURL = new URL(locationHeader.value, url);
|
||||
url = locationURL.toString();
|
||||
if ((entry.response.status === 301 || entry.response.status === 302) && method === 'POST' || entry.response.status === 303 && !['GET', 'HEAD'].includes(method)) {
|
||||
// HTTP-redirect fetch step 13 (https://fetch.spec.whatwg.org/#http-redirect-fetch)
|
||||
method = 'GET';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
var _this$_zipFile;
|
||||
(_this$_zipFile = this._zipFile) === null || _this$_zipFile === void 0 ? void 0 : _this$_zipFile.close();
|
||||
}
|
||||
}
|
||||
function countMatchingHeaders(harHeaders, headers) {
|
||||
const set = new Set(headers.map(h => h.name.toLowerCase() + ':' + h.value));
|
||||
let matches = 0;
|
||||
for (const h of harHeaders) {
|
||||
if (set.has(h.name.toLowerCase() + ':' + h.value)) ++matches;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
async function urlToWSEndpoint(progress, endpointURL) {
|
||||
var _progress$timeUntilDe;
|
||||
if (endpointURL.startsWith('ws')) return endpointURL;
|
||||
progress === null || progress === void 0 ? void 0 : progress.log(`<ws preparing> retrieving websocket url from ${endpointURL}`);
|
||||
const fetchUrl = new URL(endpointURL);
|
||||
if (!fetchUrl.pathname.endsWith('/')) fetchUrl.pathname += '/';
|
||||
fetchUrl.pathname += 'json';
|
||||
const json = await (0, _network.fetchData)({
|
||||
url: fetchUrl.toString(),
|
||||
method: 'GET',
|
||||
timeout: (_progress$timeUntilDe = progress === null || progress === void 0 ? void 0 : progress.timeUntilDeadline()) !== null && _progress$timeUntilDe !== void 0 ? _progress$timeUntilDe : 30_000,
|
||||
headers: {
|
||||
'User-Agent': (0, _userAgent.getUserAgent)()
|
||||
}
|
||||
}, async (params, response) => {
|
||||
return new Error(`Unexpected status ${response.statusCode} when connecting to ${fetchUrl.toString()}.\n` + `This does not look like a Playwright server, try connecting via ws://.`);
|
||||
});
|
||||
progress === null || progress === void 0 ? void 0 : progress.throwIfAborted();
|
||||
const wsUrl = new URL(endpointURL);
|
||||
let wsEndpointPath = JSON.parse(json).wsEndpointPath;
|
||||
if (wsEndpointPath.startsWith('/')) wsEndpointPath = wsEndpointPath.substring(1);
|
||||
if (!wsUrl.pathname.endsWith('/')) wsUrl.pathname += '/';
|
||||
wsUrl.pathname += wsEndpointPath;
|
||||
wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
return wsUrl.toString();
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WebSocketDispatcher = exports.RouteDispatcher = exports.ResponseDispatcher = exports.RequestDispatcher = exports.APIRequestContextDispatcher = void 0;
|
||||
var _network = require("../network");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _tracingDispatcher = require("./tracingDispatcher");
|
||||
var _frameDispatcher = require("./frameDispatcher");
|
||||
var _pageDispatcher = require("./pageDispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class RequestDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, request) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(request);
|
||||
return result || new RequestDispatcher(scope, request);
|
||||
}
|
||||
static fromNullable(scope, request) {
|
||||
return request ? RequestDispatcher.from(scope, request) : undefined;
|
||||
}
|
||||
constructor(scope, request) {
|
||||
const postData = request.postDataBuffer();
|
||||
super(scope, request, 'Request', {
|
||||
frame: _frameDispatcher.FrameDispatcher.fromNullable(scope, request.frame()),
|
||||
serviceWorker: _pageDispatcher.WorkerDispatcher.fromNullable(scope, request.serviceWorker()),
|
||||
url: request.url(),
|
||||
resourceType: request.resourceType(),
|
||||
method: request.method(),
|
||||
postData: postData === null ? undefined : postData,
|
||||
headers: request.headers(),
|
||||
isNavigationRequest: request.isNavigationRequest(),
|
||||
redirectedFrom: RequestDispatcher.fromNullable(scope, request.redirectedFrom())
|
||||
});
|
||||
this._type_Request = void 0;
|
||||
this._type_Request = true;
|
||||
}
|
||||
async rawRequestHeaders(params) {
|
||||
return {
|
||||
headers: await this._object.rawRequestHeaders()
|
||||
};
|
||||
}
|
||||
async response() {
|
||||
return {
|
||||
response: ResponseDispatcher.fromNullable(this.parentScope(), await this._object.response())
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.RequestDispatcher = RequestDispatcher;
|
||||
class ResponseDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, response) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(response);
|
||||
return result || new ResponseDispatcher(scope, response);
|
||||
}
|
||||
static fromNullable(scope, response) {
|
||||
return response ? ResponseDispatcher.from(scope, response) : undefined;
|
||||
}
|
||||
constructor(scope, response) {
|
||||
super(scope, response, 'Response', {
|
||||
// TODO: responses in popups can point to non-reported requests.
|
||||
request: RequestDispatcher.from(scope, response.request()),
|
||||
url: response.url(),
|
||||
status: response.status(),
|
||||
statusText: response.statusText(),
|
||||
headers: response.headers(),
|
||||
timing: response.timing(),
|
||||
fromServiceWorker: response.fromServiceWorker()
|
||||
});
|
||||
this._type_Response = true;
|
||||
}
|
||||
async body() {
|
||||
return {
|
||||
binary: await this._object.body()
|
||||
};
|
||||
}
|
||||
async securityDetails() {
|
||||
return {
|
||||
value: (await this._object.securityDetails()) || undefined
|
||||
};
|
||||
}
|
||||
async serverAddr() {
|
||||
return {
|
||||
value: (await this._object.serverAddr()) || undefined
|
||||
};
|
||||
}
|
||||
async rawResponseHeaders(params) {
|
||||
return {
|
||||
headers: await this._object.rawResponseHeaders()
|
||||
};
|
||||
}
|
||||
async sizes(params) {
|
||||
return {
|
||||
sizes: await this._object.sizes()
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.ResponseDispatcher = ResponseDispatcher;
|
||||
class RouteDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, route) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(route);
|
||||
return result || new RouteDispatcher(scope, route);
|
||||
}
|
||||
constructor(scope, route) {
|
||||
super(scope, route, 'Route', {
|
||||
// Context route can point to a non-reported request.
|
||||
request: scope
|
||||
});
|
||||
this._type_Route = true;
|
||||
}
|
||||
async continue(params, metadata) {
|
||||
// Used to discriminate between continue in tracing.
|
||||
await this._object.continue({
|
||||
url: params.url,
|
||||
method: params.method,
|
||||
headers: params.headers,
|
||||
postData: params.postData,
|
||||
isFallback: params.isFallback
|
||||
});
|
||||
}
|
||||
async fulfill(params, metadata) {
|
||||
// Used to discriminate between fulfills in tracing.
|
||||
await this._object.fulfill(params);
|
||||
}
|
||||
async abort(params, metadata) {
|
||||
// Used to discriminate between abort in tracing.
|
||||
await this._object.abort(params.errorCode || 'failed');
|
||||
}
|
||||
async redirectNavigationRequest(params) {
|
||||
await this._object.redirectNavigationRequest(params.url);
|
||||
}
|
||||
}
|
||||
exports.RouteDispatcher = RouteDispatcher;
|
||||
class WebSocketDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, webSocket) {
|
||||
super(scope, webSocket, 'WebSocket', {
|
||||
url: webSocket.url()
|
||||
});
|
||||
this._type_EventTarget = true;
|
||||
this._type_WebSocket = true;
|
||||
this.addObjectListener(_network.WebSocket.Events.FrameSent, event => this._dispatchEvent('frameSent', event));
|
||||
this.addObjectListener(_network.WebSocket.Events.FrameReceived, event => this._dispatchEvent('frameReceived', event));
|
||||
this.addObjectListener(_network.WebSocket.Events.SocketError, error => this._dispatchEvent('socketError', {
|
||||
error
|
||||
}));
|
||||
this.addObjectListener(_network.WebSocket.Events.Close, () => this._dispatchEvent('close', {}));
|
||||
}
|
||||
}
|
||||
exports.WebSocketDispatcher = WebSocketDispatcher;
|
||||
class APIRequestContextDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, request) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(request);
|
||||
return result || new APIRequestContextDispatcher(scope, request);
|
||||
}
|
||||
static fromNullable(scope, request) {
|
||||
return request ? APIRequestContextDispatcher.from(scope, request) : undefined;
|
||||
}
|
||||
constructor(parentScope, request) {
|
||||
// We will reparent these to the context below.
|
||||
const tracing = _tracingDispatcher.TracingDispatcher.from(parentScope, request.tracing());
|
||||
super(parentScope, request, 'APIRequestContext', {
|
||||
tracing
|
||||
});
|
||||
this._type_APIRequestContext = true;
|
||||
this.adopt(tracing);
|
||||
}
|
||||
async storageState(params) {
|
||||
return this._object.storageState();
|
||||
}
|
||||
async dispose(params) {
|
||||
await this._object.dispose();
|
||||
}
|
||||
async fetch(params, metadata) {
|
||||
const fetchResponse = await this._object.fetch(params, metadata);
|
||||
return {
|
||||
response: {
|
||||
url: fetchResponse.url,
|
||||
status: fetchResponse.status,
|
||||
statusText: fetchResponse.statusText,
|
||||
headers: fetchResponse.headers,
|
||||
fetchUid: fetchResponse.fetchUid
|
||||
}
|
||||
};
|
||||
}
|
||||
async fetchResponseBody(params) {
|
||||
return {
|
||||
binary: this._object.fetchResponses.get(params.fetchUid)
|
||||
};
|
||||
}
|
||||
async fetchLog(params) {
|
||||
const log = this._object.fetchLog.get(params.fetchUid) || [];
|
||||
return {
|
||||
log
|
||||
};
|
||||
}
|
||||
async disposeAPIResponse(params) {
|
||||
this._object.disposeResponse(params.fetchUid);
|
||||
}
|
||||
}
|
||||
exports.APIRequestContextDispatcher = APIRequestContextDispatcher;
|
||||
@@ -0,0 +1,351 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WorkerDispatcher = exports.PageDispatcher = exports.BindingCallDispatcher = void 0;
|
||||
var _page = require("../page");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _serializers = require("../../protocol/serializers");
|
||||
var _frameDispatcher = require("./frameDispatcher");
|
||||
var _networkDispatchers = require("./networkDispatchers");
|
||||
var _jsHandleDispatcher = require("./jsHandleDispatcher");
|
||||
var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
|
||||
var _artifactDispatcher = require("./artifactDispatcher");
|
||||
var _utils = require("../../utils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PageDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(parentScope, page) {
|
||||
return PageDispatcher.fromNullable(parentScope, page);
|
||||
}
|
||||
static fromNullable(parentScope, page) {
|
||||
if (!page) return undefined;
|
||||
const result = (0, _dispatcher.existingDispatcher)(page);
|
||||
return result || new PageDispatcher(parentScope, page);
|
||||
}
|
||||
constructor(parentScope, page) {
|
||||
// TODO: theoretically, there could be more than one frame already.
|
||||
// If we split pageCreated and pageReady, there should be no main frame during pageCreated.
|
||||
|
||||
// We will reparent it to the page below using adopt.
|
||||
const mainFrame = _frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
|
||||
super(parentScope, page, 'Page', {
|
||||
mainFrame,
|
||||
viewportSize: page.viewportSize() || undefined,
|
||||
isClosed: page.isClosed(),
|
||||
opener: PageDispatcher.fromNullable(parentScope, page.opener())
|
||||
});
|
||||
this._type_EventTarget = true;
|
||||
this._type_Page = true;
|
||||
this._page = void 0;
|
||||
this._subscriptions = new Set();
|
||||
this.adopt(mainFrame);
|
||||
this._page = page;
|
||||
this.addObjectListener(_page.Page.Events.Close, () => {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
});
|
||||
this.addObjectListener(_page.Page.Events.Crash, () => this._dispatchEvent('crash'));
|
||||
this.addObjectListener(_page.Page.Events.Download, download => {
|
||||
// Artifact can outlive the page, so bind to the context scope.
|
||||
this._dispatchEvent('download', {
|
||||
url: download.url,
|
||||
suggestedFilename: download.suggestedFilename(),
|
||||
artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, download.artifact)
|
||||
});
|
||||
});
|
||||
this.addObjectListener(_page.Page.Events.FileChooser, fileChooser => this._dispatchEvent('fileChooser', {
|
||||
element: _elementHandlerDispatcher.ElementHandleDispatcher.from(this, fileChooser.element()),
|
||||
isMultiple: fileChooser.isMultiple()
|
||||
}));
|
||||
this.addObjectListener(_page.Page.Events.FrameAttached, frame => this._onFrameAttached(frame));
|
||||
this.addObjectListener(_page.Page.Events.FrameDetached, frame => this._onFrameDetached(frame));
|
||||
this.addObjectListener(_page.Page.Events.PageError, error => this._dispatchEvent('pageError', {
|
||||
error: (0, _serializers.serializeError)(error)
|
||||
}));
|
||||
this.addObjectListener(_page.Page.Events.WebSocket, webSocket => this._dispatchEvent('webSocket', {
|
||||
webSocket: new _networkDispatchers.WebSocketDispatcher(this, webSocket)
|
||||
}));
|
||||
this.addObjectListener(_page.Page.Events.Worker, worker => this._dispatchEvent('worker', {
|
||||
worker: new WorkerDispatcher(this, worker)
|
||||
}));
|
||||
this.addObjectListener(_page.Page.Events.Video, artifact => this._dispatchEvent('video', {
|
||||
artifact: _artifactDispatcher.ArtifactDispatcher.from(parentScope, artifact)
|
||||
}));
|
||||
if (page._video) this._dispatchEvent('video', {
|
||||
artifact: _artifactDispatcher.ArtifactDispatcher.from(this.parentScope(), page._video)
|
||||
});
|
||||
// Ensure client knows about all frames.
|
||||
const frames = page._frameManager.frames();
|
||||
for (let i = 1; i < frames.length; i++) this._onFrameAttached(frames[i]);
|
||||
}
|
||||
page() {
|
||||
return this._page;
|
||||
}
|
||||
async setDefaultNavigationTimeoutNoReply(params, metadata) {
|
||||
this._page.setDefaultNavigationTimeout(params.timeout);
|
||||
}
|
||||
async setDefaultTimeoutNoReply(params, metadata) {
|
||||
this._page.setDefaultTimeout(params.timeout);
|
||||
}
|
||||
async exposeBinding(params, metadata) {
|
||||
await this._page.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
|
||||
// When reusing the context, we might have some bindings called late enough,
|
||||
// after context and page dispatchers have been disposed.
|
||||
if (this._disposed) return;
|
||||
const binding = new BindingCallDispatcher(this, params.name, !!params.needsHandle, source, args);
|
||||
this._dispatchEvent('bindingCall', {
|
||||
binding
|
||||
});
|
||||
return binding.promise();
|
||||
});
|
||||
}
|
||||
async setExtraHTTPHeaders(params, metadata) {
|
||||
await this._page.setExtraHTTPHeaders(params.headers);
|
||||
}
|
||||
async reload(params, metadata) {
|
||||
return {
|
||||
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.reload(metadata, params))
|
||||
};
|
||||
}
|
||||
async goBack(params, metadata) {
|
||||
return {
|
||||
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goBack(metadata, params))
|
||||
};
|
||||
}
|
||||
async goForward(params, metadata) {
|
||||
return {
|
||||
response: _networkDispatchers.ResponseDispatcher.fromNullable(this.parentScope(), await this._page.goForward(metadata, params))
|
||||
};
|
||||
}
|
||||
async emulateMedia(params, metadata) {
|
||||
await this._page.emulateMedia({
|
||||
media: params.media,
|
||||
colorScheme: params.colorScheme,
|
||||
reducedMotion: params.reducedMotion,
|
||||
forcedColors: params.forcedColors
|
||||
});
|
||||
}
|
||||
async setViewportSize(params, metadata) {
|
||||
await this._page.setViewportSize(params.viewportSize);
|
||||
}
|
||||
async addInitScript(params, metadata) {
|
||||
await this._page.addInitScript(params.source);
|
||||
}
|
||||
async setNetworkInterceptionPatterns(params, metadata) {
|
||||
if (!params.patterns.length) {
|
||||
await this._page.setClientRequestInterceptor(undefined);
|
||||
return;
|
||||
}
|
||||
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob);
|
||||
await this._page.setClientRequestInterceptor((route, request) => {
|
||||
const matchesSome = urlMatchers.some(urlMatch => (0, _utils.urlMatches)(this._page._browserContext._options.baseURL, request.url(), urlMatch));
|
||||
if (!matchesSome) return false;
|
||||
this._dispatchEvent('route', {
|
||||
route: _networkDispatchers.RouteDispatcher.from(_networkDispatchers.RequestDispatcher.from(this.parentScope(), request), route)
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
async expectScreenshot(params, metadata) {
|
||||
var _params$screenshotOpt, _params$comparatorOpt;
|
||||
const mask = (((_params$screenshotOpt = params.screenshotOptions) === null || _params$screenshotOpt === void 0 ? void 0 : _params$screenshotOpt.mask) || []).map(({
|
||||
frame,
|
||||
selector
|
||||
}) => ({
|
||||
frame: frame._object,
|
||||
selector
|
||||
}));
|
||||
const locator = params.locator ? {
|
||||
frame: params.locator.frame._object,
|
||||
selector: params.locator.selector
|
||||
} : undefined;
|
||||
return await this._page.expectScreenshot(metadata, {
|
||||
...params,
|
||||
locator,
|
||||
comparatorOptions: {
|
||||
...params.comparatorOptions,
|
||||
_comparator: (_params$comparatorOpt = params.comparatorOptions) === null || _params$comparatorOpt === void 0 ? void 0 : _params$comparatorOpt.comparator
|
||||
},
|
||||
screenshotOptions: {
|
||||
...params.screenshotOptions,
|
||||
mask
|
||||
}
|
||||
});
|
||||
}
|
||||
async screenshot(params, metadata) {
|
||||
const mask = (params.mask || []).map(({
|
||||
frame,
|
||||
selector
|
||||
}) => ({
|
||||
frame: frame._object,
|
||||
selector
|
||||
}));
|
||||
return {
|
||||
binary: await this._page.screenshot(metadata, {
|
||||
...params,
|
||||
mask
|
||||
})
|
||||
};
|
||||
}
|
||||
async close(params, metadata) {
|
||||
await this._page.close(metadata, params);
|
||||
}
|
||||
async updateSubscription(params) {
|
||||
if (params.event === 'fileChooser') await this._page.setFileChooserIntercepted(params.enabled);
|
||||
if (params.enabled) this._subscriptions.add(params.event);else this._subscriptions.delete(params.event);
|
||||
}
|
||||
async keyboardDown(params, metadata) {
|
||||
await this._page.keyboard.down(params.key);
|
||||
}
|
||||
async keyboardUp(params, metadata) {
|
||||
await this._page.keyboard.up(params.key);
|
||||
}
|
||||
async keyboardInsertText(params, metadata) {
|
||||
await this._page.keyboard.insertText(params.text);
|
||||
}
|
||||
async keyboardType(params, metadata) {
|
||||
await this._page.keyboard.type(params.text, params);
|
||||
}
|
||||
async keyboardPress(params, metadata) {
|
||||
await this._page.keyboard.press(params.key, params);
|
||||
}
|
||||
async mouseMove(params, metadata) {
|
||||
await this._page.mouse.move(params.x, params.y, params);
|
||||
}
|
||||
async mouseDown(params, metadata) {
|
||||
await this._page.mouse.down(params);
|
||||
}
|
||||
async mouseUp(params, metadata) {
|
||||
await this._page.mouse.up(params);
|
||||
}
|
||||
async mouseClick(params, metadata) {
|
||||
await this._page.mouse.click(params.x, params.y, params);
|
||||
}
|
||||
async mouseWheel(params, metadata) {
|
||||
await this._page.mouse.wheel(params.deltaX, params.deltaY);
|
||||
}
|
||||
async touchscreenTap(params, metadata) {
|
||||
await this._page.touchscreen.tap(params.x, params.y);
|
||||
}
|
||||
async accessibilitySnapshot(params, metadata) {
|
||||
const rootAXNode = await this._page.accessibility.snapshot({
|
||||
interestingOnly: params.interestingOnly,
|
||||
root: params.root ? params.root._elementHandle : undefined
|
||||
});
|
||||
return {
|
||||
rootAXNode: rootAXNode || undefined
|
||||
};
|
||||
}
|
||||
async pdf(params, metadata) {
|
||||
if (!this._page.pdf) throw new Error('PDF generation is only supported for Headless Chromium');
|
||||
const buffer = await this._page.pdf(params);
|
||||
return {
|
||||
pdf: buffer
|
||||
};
|
||||
}
|
||||
async bringToFront(params, metadata) {
|
||||
await this._page.bringToFront();
|
||||
}
|
||||
async startJSCoverage(params, metadata) {
|
||||
const coverage = this._page.coverage;
|
||||
await coverage.startJSCoverage(params);
|
||||
}
|
||||
async stopJSCoverage(params, metadata) {
|
||||
const coverage = this._page.coverage;
|
||||
return await coverage.stopJSCoverage();
|
||||
}
|
||||
async startCSSCoverage(params, metadata) {
|
||||
const coverage = this._page.coverage;
|
||||
await coverage.startCSSCoverage(params);
|
||||
}
|
||||
async stopCSSCoverage(params, metadata) {
|
||||
const coverage = this._page.coverage;
|
||||
return await coverage.stopCSSCoverage();
|
||||
}
|
||||
_onFrameAttached(frame) {
|
||||
this._dispatchEvent('frameAttached', {
|
||||
frame: _frameDispatcher.FrameDispatcher.from(this, frame)
|
||||
});
|
||||
}
|
||||
_onFrameDetached(frame) {
|
||||
this._dispatchEvent('frameDetached', {
|
||||
frame: _frameDispatcher.FrameDispatcher.from(this, frame)
|
||||
});
|
||||
}
|
||||
_onDispose() {
|
||||
// Avoid protocol calls for the closed page.
|
||||
if (!this._page.isClosedOrClosingOrCrashed()) this._page.setClientRequestInterceptor(undefined).catch(() => {});
|
||||
}
|
||||
}
|
||||
exports.PageDispatcher = PageDispatcher;
|
||||
class WorkerDispatcher extends _dispatcher.Dispatcher {
|
||||
static fromNullable(scope, worker) {
|
||||
if (!worker) return undefined;
|
||||
const result = (0, _dispatcher.existingDispatcher)(worker);
|
||||
return result || new WorkerDispatcher(scope, worker);
|
||||
}
|
||||
constructor(scope, worker) {
|
||||
super(scope, worker, 'Worker', {
|
||||
url: worker.url()
|
||||
});
|
||||
this._type_Worker = true;
|
||||
this.addObjectListener(_page.Worker.Events.Close, () => this._dispatchEvent('close'));
|
||||
}
|
||||
async evaluateExpression(params, metadata) {
|
||||
return {
|
||||
value: (0, _jsHandleDispatcher.serializeResult)(await this._object.evaluateExpression(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
async evaluateExpressionHandle(params, metadata) {
|
||||
return {
|
||||
handle: _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(this, await this._object.evaluateExpressionHandle(params.expression, params.isFunction, (0, _jsHandleDispatcher.parseArgument)(params.arg)))
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.WorkerDispatcher = WorkerDispatcher;
|
||||
class BindingCallDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, name, needsHandle, source, args) {
|
||||
super(scope, {
|
||||
guid: 'bindingCall@' + (0, _utils.createGuid)()
|
||||
}, 'BindingCall', {
|
||||
frame: _frameDispatcher.FrameDispatcher.from(scope, source.frame),
|
||||
name,
|
||||
args: needsHandle ? undefined : args.map(_jsHandleDispatcher.serializeResult),
|
||||
handle: needsHandle ? _elementHandlerDispatcher.ElementHandleDispatcher.fromJSHandle(scope, args[0]) : undefined
|
||||
});
|
||||
this._type_BindingCall = true;
|
||||
this._resolve = void 0;
|
||||
this._reject = void 0;
|
||||
this._promise = void 0;
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
});
|
||||
}
|
||||
promise() {
|
||||
return this._promise;
|
||||
}
|
||||
async resolve(params, metadata) {
|
||||
this._resolve((0, _jsHandleDispatcher.parseArgument)(params.result));
|
||||
}
|
||||
async reject(params, metadata) {
|
||||
this._reject((0, _serializers.parseError)(params.error));
|
||||
}
|
||||
}
|
||||
exports.BindingCallDispatcher = BindingCallDispatcher;
|
||||
@@ -0,0 +1,111 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.PlaywrightDispatcher = void 0;
|
||||
var _fetch = require("../fetch");
|
||||
var _socksProxy = require("../../common/socksProxy");
|
||||
var _androidDispatcher = require("./androidDispatcher");
|
||||
var _browserTypeDispatcher = require("./browserTypeDispatcher");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _electronDispatcher = require("./electronDispatcher");
|
||||
var _localUtilsDispatcher = require("./localUtilsDispatcher");
|
||||
var _networkDispatchers = require("./networkDispatchers");
|
||||
var _selectorsDispatcher = require("./selectorsDispatcher");
|
||||
var _browserDispatcher = require("./browserDispatcher");
|
||||
var _utils = require("../../utils");
|
||||
var _eventsHelper = require("../../utils/eventsHelper");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PlaywrightDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, playwright, socksProxy, preLaunchedBrowser, prelaunchedAndroidDevice) {
|
||||
const descriptors = require('../deviceDescriptors');
|
||||
const deviceDescriptors = Object.entries(descriptors).map(([name, descriptor]) => ({
|
||||
name,
|
||||
descriptor
|
||||
}));
|
||||
const browserDispatcher = preLaunchedBrowser ? new _browserDispatcher.ConnectedBrowserDispatcher(scope, preLaunchedBrowser) : undefined;
|
||||
const android = new _androidDispatcher.AndroidDispatcher(scope, playwright.android);
|
||||
const prelaunchedAndroidDeviceDispatcher = prelaunchedAndroidDevice ? new _androidDispatcher.AndroidDeviceDispatcher(android, prelaunchedAndroidDevice) : undefined;
|
||||
super(scope, playwright, 'Playwright', {
|
||||
chromium: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.chromium),
|
||||
firefox: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.firefox),
|
||||
webkit: new _browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.webkit),
|
||||
android,
|
||||
electron: new _electronDispatcher.ElectronDispatcher(scope, playwright.electron),
|
||||
utils: new _localUtilsDispatcher.LocalUtilsDispatcher(scope, playwright),
|
||||
deviceDescriptors,
|
||||
selectors: new _selectorsDispatcher.SelectorsDispatcher(scope, (browserDispatcher === null || browserDispatcher === void 0 ? void 0 : browserDispatcher.selectors) || playwright.selectors),
|
||||
preLaunchedBrowser: browserDispatcher,
|
||||
preConnectedAndroidDevice: prelaunchedAndroidDeviceDispatcher,
|
||||
socksSupport: socksProxy ? new SocksSupportDispatcher(scope, socksProxy) : undefined
|
||||
});
|
||||
this._type_Playwright = void 0;
|
||||
this._browserDispatcher = void 0;
|
||||
this._type_Playwright = true;
|
||||
this._browserDispatcher = browserDispatcher;
|
||||
}
|
||||
async newRequest(params) {
|
||||
const request = new _fetch.GlobalAPIRequestContext(this._object, params);
|
||||
return {
|
||||
request: _networkDispatchers.APIRequestContextDispatcher.from(this.parentScope(), request)
|
||||
};
|
||||
}
|
||||
async cleanup() {
|
||||
var _this$_browserDispatc;
|
||||
// Cleanup contexts upon disconnect.
|
||||
await ((_this$_browserDispatc = this._browserDispatcher) === null || _this$_browserDispatc === void 0 ? void 0 : _this$_browserDispatc.cleanupContexts());
|
||||
}
|
||||
}
|
||||
exports.PlaywrightDispatcher = PlaywrightDispatcher;
|
||||
class SocksSupportDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, socksProxy) {
|
||||
super(scope, {
|
||||
guid: 'socksSupport@' + (0, _utils.createGuid)()
|
||||
}, 'SocksSupport', {});
|
||||
this._type_SocksSupport = void 0;
|
||||
this._socksProxy = void 0;
|
||||
this._socksListeners = void 0;
|
||||
this._type_SocksSupport = true;
|
||||
this._socksProxy = socksProxy;
|
||||
this._socksListeners = [_eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksRequested, payload => this._dispatchEvent('socksRequested', payload)), _eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksData, payload => this._dispatchEvent('socksData', payload)), _eventsHelper.eventsHelper.addEventListener(socksProxy, _socksProxy.SocksProxy.Events.SocksClosed, payload => this._dispatchEvent('socksClosed', payload))];
|
||||
}
|
||||
async socksConnected(params) {
|
||||
var _this$_socksProxy;
|
||||
(_this$_socksProxy = this._socksProxy) === null || _this$_socksProxy === void 0 ? void 0 : _this$_socksProxy.socketConnected(params);
|
||||
}
|
||||
async socksFailed(params) {
|
||||
var _this$_socksProxy2;
|
||||
(_this$_socksProxy2 = this._socksProxy) === null || _this$_socksProxy2 === void 0 ? void 0 : _this$_socksProxy2.socketFailed(params);
|
||||
}
|
||||
async socksData(params) {
|
||||
var _this$_socksProxy3;
|
||||
(_this$_socksProxy3 = this._socksProxy) === null || _this$_socksProxy3 === void 0 ? void 0 : _this$_socksProxy3.sendSocketData(params);
|
||||
}
|
||||
async socksError(params) {
|
||||
var _this$_socksProxy4;
|
||||
(_this$_socksProxy4 = this._socksProxy) === null || _this$_socksProxy4 === void 0 ? void 0 : _this$_socksProxy4.sendSocketError(params);
|
||||
}
|
||||
async socksEnd(params) {
|
||||
var _this$_socksProxy5;
|
||||
(_this$_socksProxy5 = this._socksProxy) === null || _this$_socksProxy5 === void 0 ? void 0 : _this$_socksProxy5.sendSocketEnd(params);
|
||||
}
|
||||
_onDispose() {
|
||||
_eventsHelper.eventsHelper.removeEventListeners(this._socksListeners);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.SelectorsDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class SelectorsDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, selectors) {
|
||||
super(scope, selectors, 'Selectors', {});
|
||||
this._type_Selectors = true;
|
||||
}
|
||||
async register(params) {
|
||||
await this._object.register(params.name, params.source, params.contentScript);
|
||||
}
|
||||
async setTestIdAttributeName(params) {
|
||||
this._object.setTestIdAttributeName(params.testIdAttributeName);
|
||||
}
|
||||
}
|
||||
exports.SelectorsDispatcher = SelectorsDispatcher;
|
||||
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.StreamDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _utils = require("../../utils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class StreamDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, stream) {
|
||||
super(scope, {
|
||||
guid: 'stream@' + (0, _utils.createGuid)(),
|
||||
stream
|
||||
}, 'Stream', {});
|
||||
// In Node v12.9.0+ we can use readableEnded.
|
||||
this._type_Stream = true;
|
||||
this._ended = false;
|
||||
stream.once('end', () => this._ended = true);
|
||||
stream.once('error', () => this._ended = true);
|
||||
}
|
||||
async read(params) {
|
||||
const stream = this._object.stream;
|
||||
if (this._ended) return {
|
||||
binary: Buffer.from('')
|
||||
};
|
||||
if (!stream.readableLength) {
|
||||
await new Promise((fulfill, reject) => {
|
||||
stream.once('readable', fulfill);
|
||||
stream.once('end', fulfill);
|
||||
stream.once('error', reject);
|
||||
});
|
||||
}
|
||||
const buffer = stream.read(Math.min(stream.readableLength, params.size || stream.readableLength));
|
||||
return {
|
||||
binary: buffer || Buffer.from('')
|
||||
};
|
||||
}
|
||||
async close() {
|
||||
this._object.stream.destroy();
|
||||
}
|
||||
}
|
||||
exports.StreamDispatcher = StreamDispatcher;
|
||||
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.TracingDispatcher = void 0;
|
||||
var _artifactDispatcher = require("./artifactDispatcher");
|
||||
var _dispatcher = require("./dispatcher");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class TracingDispatcher extends _dispatcher.Dispatcher {
|
||||
static from(scope, tracing) {
|
||||
const result = (0, _dispatcher.existingDispatcher)(tracing);
|
||||
return result || new TracingDispatcher(scope, tracing);
|
||||
}
|
||||
constructor(scope, tracing) {
|
||||
super(scope, tracing, 'Tracing', {});
|
||||
this._type_Tracing = true;
|
||||
}
|
||||
async tracingStart(params) {
|
||||
await this._object.start(params);
|
||||
}
|
||||
async tracingStartChunk(params) {
|
||||
return await this._object.startChunk(params);
|
||||
}
|
||||
async tracingStopChunk(params) {
|
||||
const {
|
||||
artifact,
|
||||
entries
|
||||
} = await this._object.stopChunk(params);
|
||||
return {
|
||||
artifact: artifact ? _artifactDispatcher.ArtifactDispatcher.from(this, artifact) : undefined,
|
||||
entries
|
||||
};
|
||||
}
|
||||
async tracingStop(params) {
|
||||
await this._object.stop();
|
||||
}
|
||||
}
|
||||
exports.TracingDispatcher = TracingDispatcher;
|
||||
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WritableStreamDispatcher = void 0;
|
||||
var _dispatcher = require("./dispatcher");
|
||||
var _utils = require("../../utils");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class WritableStreamDispatcher extends _dispatcher.Dispatcher {
|
||||
constructor(scope, stream) {
|
||||
super(scope, {
|
||||
guid: 'writableStream@' + (0, _utils.createGuid)(),
|
||||
stream
|
||||
}, 'WritableStream', {});
|
||||
this._type_WritableStream = true;
|
||||
}
|
||||
async write(params) {
|
||||
const stream = this._object.stream;
|
||||
await new Promise((fulfill, reject) => {
|
||||
stream.write(params.binary, error => {
|
||||
if (error) reject(error);else fulfill();
|
||||
});
|
||||
});
|
||||
}
|
||||
async close() {
|
||||
const stream = this._object.stream;
|
||||
await new Promise(fulfill => stream.end(fulfill));
|
||||
}
|
||||
path() {
|
||||
return this._object.stream.path;
|
||||
}
|
||||
}
|
||||
exports.WritableStreamDispatcher = WritableStreamDispatcher;
|
||||
Reference in New Issue
Block a user