Bug 1315044 - Prevent loading multiple loaders and debugger servers when creating multiple ContentActors. r=jryans
MozReview-Commit-ID: 4slVLBNdGyg
--- a/devtools/server/content-server.jsm
+++ b/devtools/server/content-server.jsm
@@ -3,54 +3,77 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-const { DevToolsLoader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
-
this.EXPORTED_SYMBOLS = ["init"];
-function init(msg) {
- // Init a custom, invisible DebuggerServer, in order to not pollute
- // the debugger with all devtools modules, nor break the debugger itself with using it
- // in the same process.
- let devtools = new DevToolsLoader();
- devtools.invisibleToDebugger = true;
- let { DebuggerServer, ActorPool } = devtools.require("devtools/server/main");
+let gLoader;
+
+function setupServer(mm) {
+ // Prevent spawning multiple server per process, even if the caller call us
+ // multiple times
+ if (gLoader) {
+ return gLoader;
+ }
+
+ // Lazy load Loader.jsm to prevent loading any devtools dependency too early.
+ let { DevToolsLoader } =
+ Cu.import("resource://devtools/shared/Loader.jsm", {});
+
+ // Init a custom, invisible DebuggerServer, in order to not pollute the
+ // debugger with all devtools modules, nor break the debugger itself with
+ // using it in the same process.
+ gLoader = new DevToolsLoader();
+ gLoader.invisibleToDebugger = true;
+ let { DebuggerServer } = gLoader.require("devtools/server/main");
if (!DebuggerServer.initialized) {
DebuggerServer.init();
}
// In case of apps being loaded in parent process, DebuggerServer is already
// initialized, but child specific actors are not registered.
// Otherwise, for child process, we need to load actors the first
// time we load child.js
DebuggerServer.addChildActors();
+ // Clean up things when the client disconnects
+ mm.addMessageListener("debug:content-process-destroy", function onDestroy() {
+ mm.removeMessageListener("debug:content-process-destroy", onDestroy);
+
+ DebuggerServer.destroy();
+ gLoader.destroy();
+ gLoader = null;
+ });
+
+ return gLoader;
+}
+
+function init(msg) {
let mm = msg.target;
mm.QueryInterface(Ci.nsISyncMessageSender);
let prefix = msg.data.prefix;
- // Connect both parent/child processes debugger servers RDP via message managers
+ // Setup a server if none started yet
+ let loader = setupServer(mm);
+
+ // Connect both parent/child processes debugger servers RDP via message
+ // managers
+ let { DebuggerServer } = loader.require("devtools/server/main");
let conn = DebuggerServer.connectToParent(prefix, mm);
conn.parentMessageManager = mm;
- let { ChildProcessActor } = devtools.require("devtools/server/actors/child-process");
+ let { ChildProcessActor } =
+ loader.require("devtools/server/actors/child-process");
+ let { ActorPool } = loader.require("devtools/server/main");
let actor = new ChildProcessActor(conn);
let actorPool = new ActorPool(conn);
actorPool.addActor(actor);
conn.addActorPool(actorPool);
- let response = {actor: actor.form()};
+ let response = { actor: actor.form() };
mm.sendAsyncMessage("debug:content-process-actor", response);
-
- mm.addMessageListener("debug:content-process-destroy", function onDestroy() {
- mm.removeMessageListener("debug:content-process-destroy", onDestroy);
-
- DebuggerServer.destroy();
- });
}
--- a/devtools/server/tests/mochitest/test_getProcess.html
+++ b/devtools/server/tests/mochitest/test_getProcess.html
@@ -15,16 +15,17 @@ Bug 1060093 - Test DebuggerServer.getPro
let Cu = Components.utils;
let Cc = Components.classes;
let Ci = Components.interfaces;
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
let {DebuggerClient} = require("devtools/shared/client/main");
let {DebuggerServer} = require("devtools/server/main");
+let Services = require("Services");
window.onload = function() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
"set": [
// Always log packets when running tests.
["devtools.debugger.log", true],
@@ -106,26 +107,52 @@ function runTests() {
// Assert that calling client.getProcess against the same process id is
// returning the same actor.
function getProcessAgain(firstActor, id) {
client.getProcess(id).then(response => {
let actor = response.form;
is(actor, firstActor,
"Second call to getProcess with the same id returns the same form");
+ closeClient();
+ });
+ }
+
+ function processScript() {
+ let listener = function () {
+ Services.obs.removeObserver(listener, "sdk:loader:destroy", false);
+ sendAsyncMessage("test:getProcess-destroy", null);
+ };
+ Services.obs.addObserver(listener, "sdk:loader:destroy", false);
+ }
+
+ function closeClient() {
+ let onLoaderDestroyed = new Promise(done => {
+ let processListener = function () {
+ Services.ppmm.removeMessageListener("test:getProcess-destroy", processListener)
+ done();
+ };
+ Services.ppmm.addMessageListener("test:getProcess-destroy", processListener)
+ });
+ let script = "data:,(" + processScript + ")()";
+ Services.ppmm.loadProcessScript(script, true);
+ client.close();
+
+ onLoaderDestroyed.then(function () {
+ Services.ppmm.removeDelayedProcessScript(script);
+ info("Loader destroyed in the content process");
+
cleanup();
});
}
function cleanup() {
- client.close().then(function () {
- DebuggerServer.destroy();
- iframe.remove();
- SimpleTest.finish()
- });
+ DebuggerServer.destroy();
+ iframe.remove();
+ SimpleTest.finish()
}
connect();
}
</script>
</pre>
</body>