Bug 1364075 - remove DevTools dependency in ContentProcessSingleton;r=ochameau
authorJulian Descottes <jdescottes@mozilla.com>
Mon, 29 May 2017 23:36:26 +0200
changeset 361773 6e9b45f7ed376eea83df779d60b3c4562b188a66
parent 361772 215cfdee973f3963aabde49296e2805697b4b108
child 361774 411f357ea4853ead25ade894173952516f6ed003
push id31942
push userryanvm@gmail.com
push dateThu, 01 Jun 2017 15:54:15 +0000
treeherdermozilla-central@cac2fd43de81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1364075
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1364075 - remove DevTools dependency in ContentProcessSingleton;r=ochameau MozReview-Commit-ID: 38XKKM37jC5
devtools/client/framework/devtools-browser.js
devtools/server/content-process-debugger-server.js
devtools/server/main.js
devtools/server/moz.build
toolkit/components/processsingleton/ContentProcessSingleton.js
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -852,16 +852,19 @@ var gDevToolsBrowser = exports.gDevTools
 
     gDevToolsBrowser._pingTelemetry();
     gDevToolsBrowser._telemetry = null;
 
     for (let win of gDevToolsBrowser._trackedBrowserWindows) {
       gDevToolsBrowser._forgetBrowserWindow(win);
     }
 
+    // Remove scripts loaded in content process to support the Browser Content Toolbox.
+    DebuggerServer.removeContentServerScript();
+
     gDevTools.destroy({ shuttingDown });
   },
 };
 
 // Handle all already registered tools,
 gDevTools.getToolDefinitionArray()
          .forEach(def => gDevToolsBrowser._addToolToWindows(def));
 // and the new ones.
new file mode 100644
--- /dev/null
+++ b/devtools/server/content-process-debugger-server.js
@@ -0,0 +1,26 @@
+/* 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/. */
+
+/* global addMessageListener, removeMessageListener */
+
+"use strict";
+
+const { utils: Cu } = Components;
+const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+
+function onInit(message) {
+  // Only reply if we are in a real content process
+  if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
+    let {init} = Cu.import("resource://devtools/server/content-server.jsm", {});
+    init(message);
+  }
+}
+
+function onClose() {
+  removeMessageListener("debug:init-content-server", onInit);
+  removeMessageListener("debug:close-content-server", onClose);
+}
+
+addMessageListener("debug:init-content-server", onInit);
+addMessageListener("debug:close-content-server", onClose);
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -64,16 +64,19 @@ if (isWorker) {
   const VERBOSE_PREF = "devtools.debugger.log.verbose";
 
   flags.wantLogging = Services.prefs.getBoolPref(LOG_PREF);
   flags.wantVerbose =
     Services.prefs.getPrefType(VERBOSE_PREF) !== Services.prefs.PREF_INVALID &&
     Services.prefs.getBoolPref(VERBOSE_PREF);
 }
 
+const CONTENT_PROCESS_DBG_SERVER_SCRIPT =
+  "resource://devtools/server/content-process-debugger-server.js";
+
 function loadSubScript(url) {
   try {
     let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
                    .getService(Ci.mozIJSSubScriptLoader);
     loader.loadSubScript(url, this);
   } catch (e) {
     let errorStr = "Error loading: " + url + ":\n" +
                    (e.fileName ? "at " + e.fileName + " : " + e.lineNumber + "\n" : "") +
@@ -144,16 +147,18 @@ function ModuleAPI() {
 }
 
 /** *
  * Public API
  */
 var DebuggerServer = {
   _listeners: [],
   _initialized: false,
+  // Flag to check if the content process debugger server script was already loaded.
+  _contentProcessScriptLoaded: false,
   // Map of global actor names to actor constructors provided by extensions.
   globalActorFactories: {},
   // Map of tab actor names to actor constructors provided by extensions.
   tabActorFactories: {},
 
   LONG_STRING_LENGTH: 10000,
   LONG_STRING_INITIAL_LENGTH: 1000,
   LONG_STRING_READ_LENGTH: 65 * 1024,
@@ -750,17 +755,26 @@ var DebuggerServer = {
 
       dumpn("establishing forwarding for process with prefix " + prefix);
 
       actor = msg.json.actor;
 
       deferred.resolve(actor);
     });
 
-    mm.sendAsyncMessage("DevTools:InitDebuggerServer", {
+    // Load the content process debugger server script only once.
+    if (!this._contentProcessScriptLoaded) {
+      // Load the process script that will receive the debug:init-content-server message
+      Services.ppmm.loadProcessScript(CONTENT_PROCESS_DBG_SERVER_SCRIPT, true);
+      this._contentProcessScriptLoaded = true;
+    }
+
+    // Send a message to the content process debugger server script to forward it the
+    // prefix.
+    mm.sendAsyncMessage("debug:init-content-server", {
       prefix: prefix
     });
 
     function onClose() {
       Services.obs.removeObserver(onMessageManagerClose, "message-manager-close");
       events.off(connection, "closed", onClose);
       if (childTransport) {
         // If we have a child transport, the actor has already
@@ -1364,16 +1378,30 @@ var DebuggerServer = {
         for (let connID of Object.getOwnPropertyNames(this._connections)) {
           this._connections[connID].rootActor.removeActorByName(name);
         }
       }
     }
   },
 
   /**
+   * Called when DevTools are unloaded to remove the contend process server script for the
+   * list of scripts loaded for each new content process. Will also remove message
+   * listeners from already loaded scripts.
+   */
+  removeContentServerScript() {
+    Services.ppmm.removeDelayedProcessScript(CONTENT_PROCESS_DBG_SERVER_SCRIPT);
+    try {
+      Services.ppmm.broadcastAsyncMessage("debug:close-content-server");
+    } catch (e) {
+      // Nothing to do
+    }
+  },
+
+  /**
    * ⚠ TESTING ONLY! ⚠ Searches all active connections for an actor matching an ID.
    * This is helpful for some tests which depend on reaching into the server to check some
    * properties of an actor.
    */
   _searchAllConnectionsForActor(actorID) {
     for (let connID of Object.getOwnPropertyNames(this._connections)) {
       let actor = this._connections[connID].getActor(actorID);
       if (actor) {
--- a/devtools/server/moz.build
+++ b/devtools/server/moz.build
@@ -13,16 +13,17 @@ DIRS += [
 ]
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 DevToolsModules(
     'child.js',
+    'content-process-debugger-server.js',
     'content-server.jsm',
     'css-logic.js',
     'event-parsers.js',
     'main.js',
     'primitive.js',
     'service-worker-child.js',
     'websocket-server.js',
     'worker.js'
--- a/toolkit/components/processsingleton/ContentProcessSingleton.js
+++ b/toolkit/components/processsingleton/ContentProcessSingleton.js
@@ -44,17 +44,16 @@ ContentProcessSingleton.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   observe(subject, topic, data) {
     switch (topic) {
     case "app-startup": {
       Services.obs.addObserver(this, "console-api-log-event");
       Services.obs.addObserver(this, "xpcom-shutdown");
-      cpmm.addMessageListener("DevTools:InitDebuggerServer", this);
       TelemetryController.observe(null, topic, null);
       break;
     }
     case "console-api-log-event": {
       let consoleMsg = subject.wrappedJSObject;
 
       let msgData = {
         level: consoleMsg.level,
@@ -98,24 +97,14 @@ ContentProcessSingleton.prototype = {
 
       cpmm.sendAsyncMessage("Console:Log", msgData);
       break;
     }
 
     case "xpcom-shutdown":
       Services.obs.removeObserver(this, "console-api-log-event");
       Services.obs.removeObserver(this, "xpcom-shutdown");
-      cpmm.removeMessageListener("DevTools:InitDebuggerServer", this);
       break;
     }
   },
-
-  receiveMessage(message) {
-    // load devtools component on-demand
-    // Only reply if we are in a real content process
-    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
-      let {init} = Cu.import("resource://devtools/server/content-server.jsm", {});
-      init(message);
-    }
-  },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentProcessSingleton]);