--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -1001,40 +1001,40 @@ var DebuggerServer = {
if (!actor) {
mm.removeMessageListener("debug:actor", onActorCreated);
}
DebuggerServer._childMessageManagers.delete(mm);
};
let actor, childTransport;
let prefix = connection.allocID("child");
- let netMonitor = null;
+ // Compute the same prefix that's used by DebuggerServerConnection
+ let connPrefix = prefix + "/";
// provides hook to actor modules that need to exchange messages
// between e10s parent and child processes
let onSetupInParent = function (msg) {
// We may have multiple connectToChild instance running for the same tab
- // and need to filter the messages. Also the DebuggerServerConnection's
- // prefix has an additional '/' and the end, so use `includes`.
- if (!msg.json.prefix.includes(prefix)) {
+ // and need to filter the messages.
+ if (msg.json.prefix != connPrefix) {
return false;
}
let { module, setupParent } = msg.json;
let m;
try {
m = require(module);
if (!setupParent in m) {
dumpn(`ERROR: module '${module}' does not export 'setupParent'`);
return false;
}
- m[setupParent]({ mm, prefix });
+ m[setupParent]({ mm, prefix: connPrefix });
return true;
} catch (e) {
let errorMessage =
"Exception during actor module setup running in the parent process: ";
DevToolsUtils.reportException(errorMessage + e);
dumpn(`ERROR: ${errorMessage}\n\t module: '${module}'\n\t ` +
`setupParent: '${setupParent}'\n${DevToolsUtils.safeErrorString(e)}`);
@@ -1056,20 +1056,16 @@ var DebuggerServer = {
};
childTransport.ready();
connection.setForwarding(prefix, childTransport);
dumpn("establishing forwarding for app with prefix " + prefix);
actor = msg.json.actor;
-
- let { NetworkMonitorManager } = require("devtools/shared/webconsole/network-monitor");
- netMonitor = new NetworkMonitorManager(mm, actor.actor);
-
deferred.resolve(actor);
}).bind(this);
// Listen for browser frame swap
let onBrowserSwap = ({ detail: newFrame }) => {
// Remove listeners from old frame and mm
untrackMessageManager();
// Update frame and mm to point to the new browser frame
@@ -1083,17 +1079,18 @@ var DebuggerServer = {
if (childTransport) {
childTransport.swapBrowser(mm);
}
};
let destroy = DevToolsUtils.makeInfallible(function () {
// provides hook to actor modules that need to exchange messages
// between e10s parent and child processes
- DebuggerServer.emit("disconnected-from-child:" + prefix, { mm, prefix });
+ DebuggerServer.emit("disconnected-from-child:" + connPrefix,
+ { mm, prefix: connPrefix });
if (childTransport) {
// If we have a child transport, the actor has already
// been created. We need to stop using this message manager.
childTransport.close();
childTransport = null;
connection.cancelForwarding(prefix);
@@ -1114,21 +1111,16 @@ var DebuggerServer = {
if (actor) {
// The ContentActor within the child process doesn't necessary
// have time to uninitialize itself when the app is closed/killed.
// So ensure telling the client that the related actor is detached.
connection.send({ from: actor.actor, type: "tabDetached" });
actor = null;
}
- if (netMonitor) {
- netMonitor.destroy();
- netMonitor = null;
- }
-
if (onDestroy) {
onDestroy(mm);
}
// Cleanup all listeners
untrackMessageManager();
Services.obs.removeObserver(onMessageManagerClose, "message-manager-close");
events.off(connection, "closed", destroy);
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -11,16 +11,18 @@ const Services = require("Services");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyRequireGetter(this, "NetworkHelper",
"devtools/shared/webconsole/network-helper");
loader.lazyRequireGetter(this, "DevToolsUtils",
"devtools/shared/DevToolsUtils");
loader.lazyRequireGetter(this, "flags",
"devtools/shared/flags");
+loader.lazyRequireGetter(this, "DebuggerServer",
+ "devtools/server/main", true);
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyServiceGetter(this, "gActivityDistributor",
"@mozilla.org/network/http-activity-distributor;1",
"nsIHttpActivityDistributor");
// /////////////////////////////////////////////////////////////////////////////
// Network logging
// /////////////////////////////////////////////////////////////////////////////
@@ -1383,25 +1385,25 @@ NetworkMonitor.prototype = {
*
* @constructor
* @param number appId
* The web appId of the child process.
* @param number outerWindowID
* The outerWindowID of the TabActor's main window.
* @param nsIMessageManager messageManager
* The nsIMessageManager to use to communicate with the parent process.
- * @param string connID
- * The connection ID to use for send messages to the parent process.
+ * @param object DebuggerServerConnection
+ * The RDP connection to the client.
* @param object owner
* The WebConsoleActor that is listening for the network requests.
*/
-function NetworkMonitorChild(appId, outerWindowID, messageManager, connID, owner) {
+function NetworkMonitorChild(appId, outerWindowID, messageManager, conn, owner) {
this.appId = appId;
this.outerWindowID = outerWindowID;
- this.connID = connID;
+ this.conn = conn;
this.owner = owner;
this._messageManager = messageManager;
this._onNewEvent = this._onNewEvent.bind(this);
this._onUpdateEvent = this._onUpdateEvent.bind(this);
this._netEvents = new Map();
}
exports.NetworkMonitorChild = NetworkMonitorChild;
@@ -1414,31 +1416,36 @@ NetworkMonitorChild.prototype = {
get saveRequestAndResponseBodies() {
return this._saveRequestAndResponseBodies;
},
set saveRequestAndResponseBodies(val) {
this._saveRequestAndResponseBodies = val;
- this._messageManager.sendAsyncMessage("debug:netmonitor:" + this.connID, {
+ this._messageManager.sendAsyncMessage("debug:netmonitor", {
action: "setPreferences",
preferences: {
saveRequestAndResponseBodies: this._saveRequestAndResponseBodies,
},
});
},
init: function () {
+ this.conn.setupInParent({
+ module: "devtools/shared/webconsole/network-monitor",
+ setupParent: "setupParentProcess"
+ });
+
let mm = this._messageManager;
- mm.addMessageListener("debug:netmonitor:" + this.connID + ":newEvent",
+ mm.addMessageListener("debug:netmonitor:newEvent",
this._onNewEvent);
- mm.addMessageListener("debug:netmonitor:" + this.connID + ":updateEvent",
+ mm.addMessageListener("debug:netmonitor:updateEvent",
this._onUpdateEvent);
- mm.sendAsyncMessage("debug:netmonitor:" + this.connID, {
+ mm.sendAsyncMessage("debug:netmonitor", {
appId: this.appId,
outerWindowID: this.outerWindowID,
action: "start",
});
},
_onNewEvent: DevToolsUtils.makeInfallible(function _onNewEvent(msg) {
let {id, event} = msg.data;
@@ -1468,30 +1475,30 @@ NetworkMonitorChild.prototype = {
return;
}
actor[method].apply(actor, args);
}),
destroy: function () {
let mm = this._messageManager;
try {
- mm.removeMessageListener("debug:netmonitor:" + this.connID + ":newEvent",
+ mm.removeMessageListener("debug:netmonitor:newEvent",
this._onNewEvent);
- mm.removeMessageListener("debug:netmonitor:" + this.connID +
- ":updateEvent",
+ mm.removeMessageListener("debug:netmonitor:updateEvent",
this._onUpdateEvent);
} catch (e) {
// On b2g, when registered to a new root docshell,
// all message manager functions throw when trying to call them during
// message-manager-disconnect event.
// As there is no attribute/method on message manager to know
// if they are still usable or not, we can only catch the exception...
}
this._netEvents.clear();
this._messageManager = null;
+ this.conn = null;
this.owner = null;
},
};
/**
* The NetworkEventActorProxy is used to send network request information from
* the main process to the child app process. One proxy is used per request.
* Similarly, one NetworkEventActor in the child app process is used per
@@ -1500,31 +1507,28 @@ NetworkMonitorChild.prototype = {
* The child process has a NetworkMonitorChild instance that is listening for
* all network logging from the main process. The net monitor shim is used to
* proxy the data to the WebConsoleActor instance of the child process.
*
* @constructor
* @param nsIMessageManager messageManager
* The message manager for the child app process. This is used for
* communication with the NetworkMonitorChild instance of the process.
- * @param string connID
- * The connection ID to use to send messages to the child process.
*/
-function NetworkEventActorProxy(messageManager, connID) {
+function NetworkEventActorProxy(messageManager) {
this.id = gSequenceId();
- this.connID = connID;
this.messageManager = messageManager;
}
exports.NetworkEventActorProxy = NetworkEventActorProxy;
NetworkEventActorProxy.methodFactory = function (method) {
return DevToolsUtils.makeInfallible(function () {
let args = Array.slice(arguments);
let mm = this.messageManager;
- mm.sendAsyncMessage("debug:netmonitor:" + this.connID + ":updateEvent", {
+ mm.sendAsyncMessage("debug:netmonitor:updateEvent", {
id: this.id,
method: method,
args: args,
});
}, "NetworkEventActorProxy." + method);
};
NetworkEventActorProxy.prototype = {
@@ -1534,17 +1538,17 @@ NetworkEventActorProxy.prototype = {
*
* @param object event
* Object describing the network request.
* @return object
* This object.
*/
init: DevToolsUtils.makeInfallible(function (event) {
let mm = this.messageManager;
- mm.sendAsyncMessage("debug:netmonitor:" + this.connID + ":newEvent", {
+ mm.sendAsyncMessage("debug:netmonitor:newEvent", {
id: this.id,
event: event,
});
return this;
}),
};
(function () {
@@ -1554,42 +1558,54 @@ NetworkEventActorProxy.prototype = {
"addResponseCookies", "addResponseContent", "addEventTimings"];
let factory = NetworkEventActorProxy.methodFactory;
for (let method of methods) {
NetworkEventActorProxy.prototype[method] = factory(method);
}
})();
/**
- * The NetworkMonitor manager used by the Webapps actor in the main process.
- * This object uses the message manager to listen for requests from the child
- * process to start/stop the network monitor.
+ * This is triggered by the child calling `setupInParent` when the child's network monitor
+ * is starting up. This initializes the parent process side of the monitoring.
+ */
+function setupParentProcess({ mm, prefix }) {
+ let networkMonitor = new NetworkMonitorParent(mm, prefix);
+ DebuggerServer.once("disconnected-from-child:" + prefix, () => {
+ networkMonitor.destroy();
+ networkMonitor = null;
+ });
+}
+
+exports.setupParentProcess = setupParentProcess;
+
+/**
+ * The NetworkMonitorParent runs in the parent process and uses the message manager to
+ * listen for requests from the child process to start/stop the network monitor. Most
+ * request data is only available from the parent process, so that's why the network
+ * monitor needs to run there when debugging tabs that are in the child.
*
- * @constructor
* @param nsIMessageManager mm
* The message manager for the browser we're filtering on.
- * @param string id
- * Instance identifier to use for messages.
+ * @param string prefix
+ * The RDP connection prefix that uniquely identifies the connection.
*/
-function NetworkMonitorManager(mm, id) {
- this.id = id;
+function NetworkMonitorParent(mm, prefix) {
this.messageManager = mm;
this.onNetMonitorMessage = this.onNetMonitorMessage.bind(this);
this.onNetworkEvent = this.onNetworkEvent.bind(this);
- mm.addMessageListener("debug:netmonitor:" + id, this.onNetMonitorMessage);
+ mm.addMessageListener("debug:netmonitor", this.onNetMonitorMessage);
}
-exports.NetworkMonitorManager = NetworkMonitorManager;
-NetworkMonitorManager.prototype = {
+NetworkMonitorParent.prototype = {
netMonitor: null,
messageManager: null,
/**
- * Handler for "debug:monitor" messages received through the message manager
+ * Handler for "debug:netmonitor" messages received through the message manager
* from the content process.
*
* @param object msg
* Message from the content.
*/
onNetMonitorMessage: DevToolsUtils.makeInfallible(function (msg) {
let {action} = msg.json;
// Pipe network monitor data from parent to child via the message manager.
@@ -1632,25 +1648,25 @@ NetworkMonitorManager.prototype = {
* NetworkMonitor instance.
*
* @param object event
* Object describing the network request.
* @return object
* A NetworkEventActorProxy instance which is notified when further
* data about the request is available.
*/
- onNetworkEvent: DevToolsUtils.makeInfallible(function _onNetworkEvent(event) {
- return new NetworkEventActorProxy(this.messageManager, this.id).init(event);
+ onNetworkEvent: DevToolsUtils.makeInfallible(function (event) {
+ return new NetworkEventActorProxy(this.messageManager).init(event);
}),
destroy: function () {
if (this.messageManager) {
let mm = this.messageManager;
this.messageManager = null;
- mm.removeMessageListener("debug:netmonitor:" + this.id, this.onNetMonitorMessage);
+ mm.removeMessageListener("debug:netmonitor", this.onNetMonitorMessage);
}
this.frames = null;
if (this.netMonitor) {
this.netMonitor.destroy();
this.netMonitor = null;
}
},