Bug 910184 - Use a separate server for Browser Debugger. r=vporof

This commit is contained in:
J. Ryan Stinnett 2013-08-28 16:19:34 +02:00
parent b36c3245a2
commit cce5c9715c
5 changed files with 65 additions and 47 deletions

View File

@ -11,10 +11,10 @@ const DBG_XUL = "chrome://browser/content/devtools/debugger.xul";
const CHROME_DEBUGGER_PROFILE_NAME = "-chrome-debugger";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
Cu.import("resource://gre/modules/devtools/Loader.jsm");
let require = devtools.require;
let Telemetry = require("devtools/shared/telemetry");
this.EXPORTED_SYMBOLS = ["BrowserDebuggerProcess"];
@ -50,11 +50,21 @@ BrowserDebuggerProcess.prototype = {
* Initializes the debugger server.
*/
_initServer: function() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
if (!this.loader) {
// Create a separate loader instance, so that we can be sure to receive a
// separate instance of the DebuggingServer from the rest of the devtools.
// This allows us to safely use the tools against even the actors and
// DebuggingServer itself.
this.loader = new DevToolsLoader();
this.loader.main("devtools/server/main");
this.debuggerServer = this.loader.DebuggerServer;
}
DebuggerServer.openListener(Prefs.chromeDebuggingPort);
if (!this.debuggerServer.initialized) {
this.debuggerServer.init();
this.debuggerServer.addBrowserActors();
}
this.debuggerServer.openListener(Prefs.chromeDebuggingPort);
},
/**
@ -136,6 +146,8 @@ BrowserDebuggerProcess.prototype = {
this._telemetry.toolClosed("jsbrowserdebugger");
this.debuggerServer.destroy();
dumpn("Chrome debugger is now closed...");
if (typeof this._closeCallback == "function") {
this._closeCallback.call({}, this);

View File

@ -21,7 +21,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "console", "resource://gre/modules/devto
let loader = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {}).Loader;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
this.EXPORTED_SYMBOLS = ["devtools"];
this.EXPORTED_SYMBOLS = ["DevToolsLoader", "devtools"];
/**
* Providers are different strategies for loading the devtools.
@ -36,11 +36,11 @@ let loaderGlobals = {
lazyImporter: XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils),
lazyServiceGetter: XPCOMUtils.defineLazyServiceGetter.bind(XPCOMUtils)
}
}
};
// Used when the tools should be loaded from the Firefox package itself (the default)
var BuiltinProvider = {
load: function(done) {
load: function() {
this.loader = new loader.Loader({
modules: {
"toolkit/loader": loader
@ -78,7 +78,7 @@ var SrcdirProvider = {
return Services.io.newFileURI(file).spec;
},
load: function(done) {
load: function() {
let srcdir = Services.prefs.getComplexValue("devtools.loader.srcdir",
Ci.nsISupportsString);
srcdir = OS.Path.normalize(srcdir.data.trim());
@ -182,9 +182,15 @@ var SrcdirProvider = {
/**
* The main devtools API.
* In addition to a few loader-related details, this object will also include all
* exports from the main module.
* exports from the main module. The standard instance of this loader is
* exported as |devtools| below, but if a fresh copy of the loader is needed,
* then a new one can also be created.
*/
this.devtools = {
this.DevToolsLoader = function DevToolsLoader() {
this._chooseProvider();
};
DevToolsLoader.prototype = {
_provider: null,
/**
@ -267,5 +273,5 @@ this.devtools = {
},
};
// Now load the tools.
devtools._chooseProvider();
// Export the standard instance of DevToolsLoader used by the tools.
this.devtools = new DevToolsLoader();

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Loads the remote debugging protocol code into a sandbox, in order to
* shield it from the debuggee. This way, when debugging chrome globals,
@ -15,30 +16,11 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
this.EXPORTED_SYMBOLS = ["DebuggerServer", "ActorPool"];
var loadSubScript =
"function loadSubScript(aURL)\n" +
"{\n" +
"const Ci = Components.interfaces;\n" +
"const Cc = Components.classes;\n" +
" try {\n" +
" let loader = Cc[\"@mozilla.org/moz/jssubscript-loader;1\"]\n" +
" .getService(Ci.mozIJSSubScriptLoader);\n" +
" loader.loadSubScript(aURL, this);\n" +
" } catch(e) {\n" +
" dump(\"Error loading: \" + aURL + \": \" + e + \" - \" + e.stack + \"\\n\");\n" +
" throw e;\n" +
" }\n" +
"}";
let server = devtools.require("devtools/server/main");
// Load the debugging server in a sandbox with its own compartment.
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
.createInstance(Ci.nsIPrincipal);
var gGlobal = Cu.Sandbox(systemPrincipal);
Cu.evalInSandbox(loadSubScript, gGlobal, "1.8");
gGlobal.loadSubScript("resource://gre/modules/devtools/server/main.js");
this.DebuggerServer = gGlobal.DebuggerServer;
this.ActorPool = gGlobal.ActorPool;
this.DebuggerServer = server.DebuggerServer;
this.ActorPool = server.ActorPool;

View File

@ -10,11 +10,7 @@
* debugging global.
*/
const Ci = Components.interfaces;
const Cc = Components.classes;
const CC = Components.Constructor;
const Cu = Components.utils;
const Cr = Components.results;
const { Ci, Cc, CC, Cu, Cr, components: Components } = require("chrome");
const DBG_STRINGS_URI = "chrome://global/locale/devtools/debugger.properties";
Cu.import("resource://gre/modules/Services.jsm");
@ -25,7 +21,24 @@ const promptConnections = Services.prefs.getBoolPref("devtools.debugger.prompt-c
Cu.import("resource://gre/modules/jsdebugger.jsm");
addDebuggerToGlobal(this);
function loadSubScript(aURL)
{
try {
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
loader.loadSubScript(aURL, this);
} catch(e) {
let errorStr = "Error loading: " + aURL + ": " + e + " - " + e.stack + "\n";
dump(errorStr);
Cu.reportError(errorStr);
throw e;
}
}
let loaderRequire = require;
this.require = null;
loadSubScript.call(this, "resource://gre/modules/commonjs/sdk/core/promise.js");
this.require = loaderRequire;
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
@ -259,9 +272,7 @@ var DebuggerServer = {
}
let moduleAPI = ModuleAPI();
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let mod = devtools.require(id);
let mod = require(id);
mod.register(moduleAPI);
gRegisteredModules[id] = { module: mod, api: moduleAPI };
},
@ -607,6 +618,7 @@ var DebuggerServer = {
}
};
exports.DebuggerServer = DebuggerServer;
/**
* Construct an ActorPool.
@ -622,6 +634,8 @@ function ActorPool(aConnection)
this._actors = {};
}
exports.ActorPool = ActorPool;
ActorPool.prototype = {
/**
* Add an actor to the actor pool. If the actor doesn't have an ID,

View File

@ -192,7 +192,11 @@ DebuggerTransport.prototype = {
dumpn("Got: " + packet);
let self = this;
Services.tm.currentThread.dispatch(makeInfallible(function() {
self.hooks.onPacket(parsed);
// Ensure the hooks are still around by the time this runs (they will go
// away when the transport is closed).
if (self.hooks) {
self.hooks.onPacket(parsed);
}
}, "DebuggerTransport instance's this.hooks.onPacket"), 0);
return true;