feat(worker): report workers network activity (#545)
This commit is contained in:
parent
c3e4f092d3
commit
ddf47bc291
|
|
@ -20,10 +20,10 @@ import * as js from '../javascript';
|
|||
import * as frames from '../frames';
|
||||
import { debugError, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { CRSession } from './crConnection';
|
||||
import { CRSession, CRConnection } from './crConnection';
|
||||
import { EVALUATION_SCRIPT_URL, CRExecutionContext } from './crExecutionContext';
|
||||
import { CRNetworkManager } from './crNetworkManager';
|
||||
import { Page, Coverage } from '../page';
|
||||
import { Page, Coverage, Worker } from '../page';
|
||||
import { Protocol } from './protocol';
|
||||
import { Events } from '../events';
|
||||
import { toConsoleMessageLocation, exceptionToError, releaseObject } from './crProtocolHelper';
|
||||
|
|
@ -33,7 +33,6 @@ import { RawMouseImpl, RawKeyboardImpl } from './crInput';
|
|||
import { getAccessibilityTree } from './crAccessibility';
|
||||
import { CRCoverage } from './crCoverage';
|
||||
import { CRPDF } from './crPdf';
|
||||
import { CRWorkers } from './crWorkers';
|
||||
import { CRBrowser } from './crBrowser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import * as types from '../types';
|
||||
|
|
@ -46,7 +45,6 @@ export class CRPage implements PageDelegate {
|
|||
_client: CRSession;
|
||||
private readonly _page: Page;
|
||||
readonly _networkManager: CRNetworkManager;
|
||||
private _workers: CRWorkers;
|
||||
private _contextIdToContext = new Map<number, dom.FrameExecutionContext>();
|
||||
private _isolatedWorlds = new Set<string>();
|
||||
private _eventListeners: RegisteredListener[];
|
||||
|
|
@ -65,7 +63,6 @@ export class CRPage implements PageDelegate {
|
|||
this._coverage = new CRCoverage(client);
|
||||
this._page = new Page(this, browserContext);
|
||||
this._networkManager = new CRNetworkManager(client, this._page);
|
||||
this._workers = new CRWorkers(client, this._page);
|
||||
|
||||
this._eventListeners = [
|
||||
helper.addEventListener(client, 'Inspector.targetCrashed', event => this._onTargetCrashed()),
|
||||
|
|
@ -84,6 +81,8 @@ export class CRPage implements PageDelegate {
|
|||
helper.addEventListener(client, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
|
||||
helper.addEventListener(client, 'Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)),
|
||||
helper.addEventListener(client, 'Runtime.executionContextsCleared', event => this._onExecutionContextsCleared()),
|
||||
helper.addEventListener(client, 'Target.attachedToTarget', event => this._onAttachedToTarget(event)),
|
||||
helper.addEventListener(client, 'Target.detachedFromTarget', event => this._onDetachedFromTarget(event)),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -223,6 +222,37 @@ export class CRPage implements PageDelegate {
|
|||
this._onExecutionContextDestroyed(contextId);
|
||||
}
|
||||
|
||||
_onAttachedToTarget(event: Protocol.Target.attachedToTargetPayload) {
|
||||
if (event.targetInfo.type !== 'worker')
|
||||
return;
|
||||
const url = event.targetInfo.url;
|
||||
const session = CRConnection.fromSession(this._client).session(event.sessionId)!;
|
||||
const worker = new Worker(url);
|
||||
this._page._addWorker(event.sessionId, worker);
|
||||
session.once('Runtime.executionContextCreated', async event => {
|
||||
worker._createExecutionContext(new CRExecutionContext(session, event.context));
|
||||
});
|
||||
Promise.all([
|
||||
session.send('Runtime.enable'),
|
||||
session.send('Network.enable'),
|
||||
]).catch(debugError); // This might fail if the target is closed before we initialize.
|
||||
session.on('Runtime.consoleAPICalled', event => {
|
||||
const args = event.args.map(o => worker._existingExecutionContext!._createHandle(o));
|
||||
this._page._addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace));
|
||||
});
|
||||
session.on('Runtime.exceptionThrown', exception => this._page.emit(Events.Page.PageError, exceptionToError(exception.exceptionDetails)));
|
||||
session.on('Fetch.requestPaused', event => this._networkManager._onRequestPaused(event));
|
||||
session.on('Fetch.authRequired', event => this._networkManager._onAuthRequired(event));
|
||||
session.on('Network.requestWillBeSent', event => this._networkManager._onRequestWillBeSent(event));
|
||||
session.on('Network.responseReceived', event => this._networkManager._onResponseReceived(event));
|
||||
session.on('Network.loadingFinished', event => this._networkManager._onLoadingFinished(event));
|
||||
session.on('Network.loadingFailed', event => this._networkManager._onLoadingFailed(event));
|
||||
}
|
||||
|
||||
_onDetachedFromTarget(event: Protocol.Target.detachedFromTargetPayload) {
|
||||
this._page._removeWorker(event.sessionId);
|
||||
}
|
||||
|
||||
async _onConsoleAPI(event: Protocol.Runtime.consoleAPICalledPayload) {
|
||||
if (event.executionContextId === 0) {
|
||||
// DevTools protocol stores the last 1000 console messages. These
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
* Modifications 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.
|
||||
*/
|
||||
|
||||
import { Events } from '../events';
|
||||
import { debugError } from '../helper';
|
||||
import { Page, Worker } from '../page';
|
||||
import { CRConnection, CRSession } from './crConnection';
|
||||
import { CRExecutionContext } from './crExecutionContext';
|
||||
import { exceptionToError, toConsoleMessageLocation } from './crProtocolHelper';
|
||||
|
||||
export class CRWorkers {
|
||||
constructor(client: CRSession, page: Page) {
|
||||
client.on('Target.attachedToTarget', event => {
|
||||
if (event.targetInfo.type !== 'worker')
|
||||
return;
|
||||
const url = event.targetInfo.url;
|
||||
const session = CRConnection.fromSession(client).session(event.sessionId)!;
|
||||
const worker = new Worker(url);
|
||||
page._addWorker(event.sessionId, worker);
|
||||
session.once('Runtime.executionContextCreated', async event => {
|
||||
worker._createExecutionContext(new CRExecutionContext(session, event.context));
|
||||
});
|
||||
// This might fail if the target is closed before we recieve all execution contexts.
|
||||
session.send('Runtime.enable', {}).catch(debugError);
|
||||
session.on('Runtime.consoleAPICalled', event => page._addConsoleMessage(event.type, event.args.map(o => worker._existingExecutionContext!._createHandle(o)), toConsoleMessageLocation(event.stackTrace)));
|
||||
session.on('Runtime.exceptionThrown', exception => page.emit(Events.Page.PageError, exceptionToError(exception.exceptionDetails)));
|
||||
});
|
||||
client.on('Target.detachedFromTarget', event => page._removeWorker(event.sessionId));
|
||||
}
|
||||
}
|
||||
|
|
@ -83,5 +83,35 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT})
|
|||
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
|
||||
expect(page.workers().length).toBe(0);
|
||||
});
|
||||
it('should report network activity', async function({page, server}) {
|
||||
const [worker] = await Promise.all([
|
||||
page.waitForEvent('workercreated'),
|
||||
page.goto(server.PREFIX + '/worker/worker.html'),
|
||||
]);
|
||||
const url = server.PREFIX + '/one-style.css';
|
||||
const requestPromise = page.waitForRequest(url);
|
||||
const responsePromise = page.waitForResponse(url);
|
||||
await worker.evaluate(url => fetch(url).then(response => response.text()).then(console.log), url);
|
||||
const request = await requestPromise;
|
||||
const response = await responsePromise;
|
||||
expect(request.url()).toBe(url);
|
||||
expect(response.request()).toBe(request);
|
||||
expect(response.ok()).toBe(true);
|
||||
});
|
||||
it.skip(CHROMIUM)('should report network activity on worker creation', async function({page, server}) {
|
||||
// Chromium needs waitForDebugger enabled for this one.
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const url = server.PREFIX + '/one-style.css';
|
||||
const requestPromise = page.waitForRequest(url);
|
||||
const responsePromise = page.waitForResponse(url);
|
||||
await page.evaluate(url => new Worker(URL.createObjectURL(new Blob([`
|
||||
fetch("${url}").then(response => response.text()).then(console.log);
|
||||
`], {type: 'application/javascript'}))), url);
|
||||
const request = await requestPromise;
|
||||
const response = await responsePromise;
|
||||
expect(request.url()).toBe(url);
|
||||
expect(response.request()).toBe(request);
|
||||
expect(response.ok()).toBe(true);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue