Bug 1444132 - Spawn a NetworkMonitorActor directly in the parent process. r=jryans

This allows to create NetworkEventActor directly from the parent process
and avoid most of the data being piped from the parent to the content processes.

MozReview-Commit-ID: 8p3A5yl5eVB

--HG--
extra : rebase_source : 49eb0406eff31b8262ac316884a4abd57512f6cf
This commit is contained in:
Alexandre Poirot 2018-03-08 09:13:26 -08:00
parent e52cd92858
commit 3ea819fbef
6 changed files with 148 additions and 51 deletions

View File

@ -44,6 +44,7 @@ DevToolsModules(
'layout.js',
'memory.js',
'network-event.js',
'network-monitor.js',
'object.js',
'pause-scoped.js',
'perf.js',

View File

@ -12,16 +12,16 @@ const { LongStringActor } = require("devtools/server/actors/string");
* Creates an actor for a network event.
*
* @constructor
* @param object webConsoleActor
* The parent WebConsoleActor instance for this object.
* @param object netMonitorActor
* The parent NetworkMonitorActor instance for this object.
*/
const NetworkEventActor = protocol.ActorClassWithSpec(networkEventSpec, {
initialize(webConsoleActor) {
initialize(netMonitorActor) {
// Necessary to get the events to work
protocol.Actor.prototype.initialize.call(this, webConsoleActor.conn);
protocol.Actor.prototype.initialize.call(this, netMonitorActor.conn);
this.webConsoleActor = webConsoleActor;
this.conn = this.webConsoleActor.conn;
this.netMonitorActor = netMonitorActor;
this.conn = this.netMonitorActor.conn;
this._request = {
method: null,
@ -72,22 +72,17 @@ const NetworkEventActor = protocol.ActorClassWithSpec(networkEventSpec, {
* Releases this actor from the pool.
*/
destroy(conn) {
if (!this.webConsoleActor) {
if (!this.netMonitorActor) {
return;
}
if (this._request.url) {
this.webConsoleActor._networkEventActorsByURL.delete(this._request.url);
this.netMonitorActor._networkEventActorsByURL.delete(this._request.url);
}
if (this.channel) {
this.webConsoleActor._netEvents.delete(this.channel);
this.netMonitorActor._netEvents.delete(this.channel);
}
// Nullify webConsoleActor before calling releaseActor as it will recall this method
// To be removed once WebConsoleActor switches to protocol.js
const actor = this.webConsoleActor;
this.webConsoleActor = null;
actor.releaseActor(this);
this.netMonitorActor = null;
protocol.Actor.prototype.destroy.call(this, conn);
},

View File

@ -0,0 +1,83 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
const { networkMonitorSpec } = require("devtools/shared/specs/network-monitor");
loader.lazyRequireGetter(this, "NetworkMonitor", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkEventActor", "devtools/server/actors/network-event", true);
const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
_netEvents: new Map(),
_networkEventActorsByURL: new Map(),
// NetworkMonitorActor is instanciated from WebConsoleActor.startListeners
// Either in the same process, for debugging service worker requests or when debugging
// the parent process itself and tracking chrome requests.
// Or in another process, for tracking content requests that are actually done in the
// parent process.
// `filters` argument either contains an `outerWindowID` attribute when this is used
// cross processes. Or a `window` attribute when instanciated in the same process.
// `parentID` is an optional argument, to be removed, that specify the ID of the Web
// console actor. This is used to fake emitting an event from it to prevent changing
// RDP behavior.
initialize(conn, filters, parentID) {
Actor.prototype.initialize.call(this, conn);
this.parentID = parentID;
// Immediately start watching for new request according to `filters`.
// NetworkMonitor will call `onNetworkEvent` method.
this.netMonitor = new NetworkMonitor(filters, this);
this.netMonitor.init();
},
destroy() {
Actor.prototype.destroy.call(this);
if (this.netMonitor) {
this.netMonitor.destroy();
this.netMonitor = null;
}
},
getNetworkEventActor(channelId) {
let actor = this._netEvents.get(channelId);
if (actor) {
return actor;
}
actor = new NetworkEventActor(this);
this.manage(actor);
// map channel to actor so we can associate future events with it
this._netEvents.set(channelId, actor);
return actor;
},
// This method is called by NetworkMonitor instance when a new request is fired
onNetworkEvent(event) {
const { channelId } = event;
const actor = this.getNetworkEventActor(channelId);
this._netEvents.set(channelId, actor);
actor.init(event);
this._networkEventActorsByURL.set(actor._request.url, actor);
const packet = {
from: this.parentID,
type: "networkEvent",
eventActor: actor.form()
};
this.conn.send(packet);
return actor;
},
});
exports.NetworkMonitorActor = NetworkMonitorActor;

View File

@ -19,8 +19,7 @@ const { createValueGrip, stringIsLong } = require("devtools/server/actors/object
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const ErrorDocs = require("devtools/server/actors/errordocs");
loader.lazyRequireGetter(this, "NetworkMonitor", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkMonitorChild", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkMonitorActor", "devtools/server/actors/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkEventActor", "devtools/server/actors/network-event", true);
loader.lazyRequireGetter(this, "ConsoleProgressListener", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "StackTraceCollector", "devtools/shared/webconsole/network-monitor", true);
@ -288,16 +287,6 @@ WebConsoleActor.prototype =
*/
consoleAPIListener: null,
/**
* The NetworkMonitor instance.
*/
networkMonitor: null,
/**
* The NetworkMonitor instance living in the same (child) process.
*/
networkMonitorChild: null,
/**
* The ConsoleProgressListener instance.
*/
@ -354,18 +343,21 @@ WebConsoleActor.prototype =
this.consoleServiceListener.destroy();
this.consoleServiceListener = null;
}
if (this.networkMonitorActor) {
this.networkMonitorActor.destroy();
this.networkMonitorActor = null;
}
if (this.networkMonitorActorId) {
this.networkMonitorActorId = null;
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.destroy();
this.networkMonitorChildActor = null;
}
if (this.consoleAPIListener) {
this.consoleAPIListener.destroy();
this.consoleAPIListener = null;
}
if (this.networkMonitor) {
this.networkMonitor.destroy();
this.networkMonitor = null;
}
if (this.networkMonitorChild) {
this.networkMonitorChild.destroy();
this.networkMonitorChild = null;
}
if (this.stackTraceCollector) {
this.stackTraceCollector.destroy();
this.stackTraceCollector = null;
@ -575,7 +567,7 @@ WebConsoleActor.prototype =
* @return object
* The response object which holds the startedListeners array.
*/
startListeners: function(request) {
startListeners: async function(request) {
const startedListeners = [];
const window = !this.parentActor.isRootActor ? this.window : null;
let messageManager = null;
@ -623,7 +615,7 @@ WebConsoleActor.prototype =
if (isWorker) {
break;
}
if (!this.networkMonitor) {
if (!this.networkMonitorActorId && !this.networkMonitorActor) {
// Create a StackTraceCollector that's going to be shared both by
// the NetworkMonitorChild (getting messages about requests from
// parent) and by the NetworkMonitor that directly watches service
@ -634,16 +626,23 @@ WebConsoleActor.prototype =
if (messageManager && processBoundary) {
// Start a network monitor in the parent process to listen to
// most requests than happen in parent
this.networkMonitor =
new NetworkMonitorChild(this.parentActor.outerWindowID,
messageManager, this.conn, this);
this.networkMonitor.init();
this.networkMonitorActorId = await this.conn.spawnActorInParentProcess(
this.actorID, {
module: "devtools/server/actors/network-monitor",
constructor: "NetworkMonitorActor",
args: [
{ outerWindowID: this.parentActor.outerWindowID },
this.actorID
],
});
// Spawn also one in the child to listen to service workers
this.networkMonitorChild = new NetworkMonitor({ window }, this);
this.networkMonitorChild.init();
this.networkMonitorChildActor = new NetworkMonitorActor(this.conn,
{ window },
this.actorID);
} else {
this.networkMonitor = new NetworkMonitor({ window }, this);
this.networkMonitor.init();
this.networkMonitorActor = new NetworkMonitorActor(this.conn, { window },
this.actorID);
}
}
startedListeners.push(listener);
@ -743,13 +742,16 @@ WebConsoleActor.prototype =
stoppedListeners.push(listener);
break;
case "NetworkActivity":
if (this.networkMonitor) {
this.networkMonitor.destroy();
this.networkMonitor = null;
if (this.networkMonitorActor) {
this.networkMonitorActor.destroy();
this.networkMonitorActor = null;
}
if (this.networkMonitorChild) {
this.networkMonitorChild.destroy();
this.networkMonitorChild = null;
if (this.networkMonitorActorId) {
this.networkMonitorActorId = null;
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.destroy();
this.networkMonitorChildActor = null;
}
if (this.stackTraceCollector) {
this.stackTraceCollector.destroy();

View File

@ -32,6 +32,7 @@ DevToolsModules(
'layout.js',
'memory.js',
'network-event.js',
'network-monitor.js',
'node.js',
'object.js',
'perf.js',

View File

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { generateActorSpec } = require("devtools/shared/protocol");
const networkMonitorSpec = generateActorSpec({
typeName: "network-monitor",
methods: {},
});
exports.networkMonitorSpec = networkMonitorSpec;