merge m-c to fx-team; a=desktop-only FIREFOX_AURORA_14_BASE
authorTim Taubert <tim.taubert@gmx.de>
Tue, 24 Apr 2012 11:35:52 -0400
changeset 92664 357da346ceb705d196a46574804c7c4ec44ac186
parent 92658 d7f017e8e572d8ecff1cfcfee37bd621293654ba (current diff)
parent 92663 f849003d9864d36b72af72acde513faa66449e24 (diff)
child 92665 2c4cfdfaf0772e5de91f79846c6bfebc6994e266
child 92980 a974c45914eba0eed284cff94f20031a3cc1fd01
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersdesktop-only
milestone14.0a1
merge m-c to fx-team; a=desktop-only
browser/app/profile/firefox.js
browser/base/content/browser.js
--- a/toolkit/devtools/debugger/server/dbg-script-actors.js
+++ b/toolkit/devtools/debugger/server/dbg-script-actors.js
@@ -82,17 +82,17 @@ ThreadActor.prototype = {
       this.conn.addActorPool(this._breakpointPool);
     }
     return this._breakpointPool;
   },
 
   _scripts: {},
 
   /**
-   * Add a debuggee global to the JSInspector.
+   * Add a debuggee global to the Debugger object.
    */
   addDebuggee: function TA_addDebuggee(aGlobal) {
     // Use the inspector xpcom component to turn on debugging
     // for aGlobal's compartment.  Ideally this won't be necessary
     // medium- to long-term, and will be managed by the engine
     // instead.
 
     if (!this._dbg) {
copy from toolkit/devtools/debugger/server/dbg-server.jsm
copy to toolkit/devtools/debugger/server/dbg-server.js
--- a/toolkit/devtools/debugger/server/dbg-server.jsm
+++ b/toolkit/devtools/debugger/server/dbg-server.js
@@ -43,34 +43,19 @@
  * debugging global.
  */
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const CC = Components.Constructor;
 const Cu = Components.utils;
 
-var EXPORTED_SYMBOLS = ["DebuggerServer"];
-
 Cu.import("resource://gre/modules/Services.jsm");
 let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
 
-function loadSubScript(aURL)
-{
-  try {
-    let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-      .getService(Components.interfaces.mozIJSSubScriptLoader);
-    loader.loadSubScript(aURL, this);
-  } catch(e) {
-    dumpn("Error loading: " + aURL + ": " + e + " - " + e.stack + "\n");
-
-    throw e;
-  }
-}
-
 function dumpn(str) {
   if (wantLogging) {
     dump("DBG-SERVER: " + str + "\n");
   }
 }
 
 function dbg_assert(cond, e) {
   if (!cond) {
@@ -96,17 +81,23 @@ var DebuggerServer = {
   /**
    * Initialize the debugger server.
    */
   init: function DH_init() {
     if (this.initialized) {
       return;
     }
 
-    Cu.import("resource://gre/modules/jsdebugger.jsm");
+    // Hack: Merely loading jsdebugger.jsm will not work, because it will load
+    // in the chrome compartment, and then we'd get a cross-compartment wrapper
+    // of that. The Debugger object must be created in the sandbox compartment,
+    // that is, this file's compartment.
+    const init = Cc["@mozilla.org/jsdebugger;1"].createInstance(Ci.IJSDebugger);
+    init.addClass();  // adds global variable Debugger to this global.
+
     this.xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
     this.initTransport();
     this.addActors("chrome://global/content/devtools/dbg-script-actors.js");
   },
 
   /**
    * Initialize the debugger server's transport variables.  This can be
    * in place of init() for cases where the jsdebugger isn't needed.
--- a/toolkit/devtools/debugger/server/dbg-server.jsm
+++ b/toolkit/devtools/debugger/server/dbg-server.jsm
@@ -34,461 +34,43 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 "use strict";
 /**
- * Toolkit glue for the remote debugging protocol, loaded into the
- * debugging global.
+ * Loads the remote debugging protocol code into a sandbox, in order to
+ * shield it from the debuggee. This way, when debugging chrome globals,
+ * debugger and debuggee will be in separate compartments.
  */
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
-const CC = Components.Constructor;
 const Cu = Components.utils;
 
 var EXPORTED_SYMBOLS = ["DebuggerServer"];
 
-Cu.import("resource://gre/modules/Services.jsm");
-let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
-
 function loadSubScript(aURL)
 {
   try {
-    let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-      .getService(Components.interfaces.mozIJSSubScriptLoader);
+    let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
+      .getService(Ci.mozIJSSubScriptLoader);
     loader.loadSubScript(aURL, this);
   } catch(e) {
-    dumpn("Error loading: " + aURL + ": " + e + " - " + e.stack + "\n");
+    dump("Error loading: " + aURL + ": " + e + " - " + e.stack + "\n");
 
     throw e;
   }
 }
 
-function dumpn(str) {
-  if (wantLogging) {
-    dump("DBG-SERVER: " + str + "\n");
-  }
-}
-
-function dbg_assert(cond, e) {
-  if (!cond) {
-    return e;
-  }
-}
-
-loadSubScript.call(this, "chrome://global/content/devtools/dbg-transport.js");
-
-// XPCOM constructors
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-
-/***
- * Public API
- */
-var DebuggerServer = {
-  _listener: null,
-  _transportInitialized: false,
-  xpcInspector: null,
-
-  /**
-   * Initialize the debugger server.
-   */
-  init: function DH_init() {
-    if (this.initialized) {
-      return;
-    }
-
-    Cu.import("resource://gre/modules/jsdebugger.jsm");
-    this.xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
-    this.initTransport();
-    this.addActors("chrome://global/content/devtools/dbg-script-actors.js");
-  },
-
-  /**
-   * Initialize the debugger server's transport variables.  This can be
-   * in place of init() for cases where the jsdebugger isn't needed.
-   */
-  initTransport: function DH_initTransport() {
-    if (this._transportInitialized) {
-      return;
-    }
-
-    this._connections = {};
-    this._nextConnID = 0;
-    this._transportInitialized = true;
-  },
-
-  get initialized() { return !!this.xpcInspector; },
-
-  /**
-   * Load a subscript into the debugging global.
-   *
-   * @param aURL string A url that will be loaded as a subscript into the
-   *        debugging global.  The user must load at least one script
-   *        that implements a createRootActor() function to create the
-   *        server's root actor.
-   */
-  addActors: function DH_addActors(aURL) {
-    loadSubScript.call(this, aURL);
-  },
-
-  /**
-   * Install Firefox-specific actors.
-   */
-  addBrowserActors: function DH_addBrowserActors() {
-    this.addActors("chrome://global/content/devtools/dbg-browser-actors.js");
-  },
-
-  /**
-   * Listens on the given port for remote debugger connections.
-   *
-   * @param aPort int
-   *        The port to listen on.
-   * @param aLocalOnly bool
-   *        If true, server will listen on the loopback device.
-   */
-  openListener: function DH_openListener(aPort, aLocalOnly) {
-    this._checkInit();
-
-    if (this._listener) {
-      throw "Debugging listener already open.";
-    }
-
-    try {
-      let socket = new ServerSocket(aPort, aLocalOnly, 4);
-      socket.asyncListen(this);
-      this._listener = socket;
-    } catch (e) {
-      dumpn("Could not start debugging listener on port " + aPort + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-
-    return true;
-  },
+Cu.import("resource:///modules/devtools/dbg-client.jsm");
 
-  /**
-   * Close a previously-opened TCP listener.
-   */
-  closeListener: function DH_closeListener() {
-    this._checkInit();
-
-    if (!this._listener) {
-      return false;
-    }
-
-    this._listener.close();
-    this._listener = null;
-
-    return true;
-  },
-
-  /**
-   * Creates a new connection to the local debugger speaking over an
-   * nsIPipe.
-   *
-   * @returns a client-side DebuggerTransport for communicating with
-   *          the newly-created connection.
-   */
-  connectPipe: function DH_connectPipe() {
-    this._checkInit();
-
-    let toServer = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
-    toServer.init(true, true, 0, 0, null);
-    let toClient = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
-    toClient.init(true, true, 0, 0, null);
-
-    let serverTransport = new DebuggerTransport(toServer.inputStream,
-                                                toClient.outputStream);
-    this._onConnection(serverTransport);
-
-    return new DebuggerTransport(toClient.inputStream, toServer.outputStream);
-  },
-
-
-  // nsIServerSocketListener implementation
-
-  onSocketAccepted: function DH_onSocketAccepted(aSocket, aTransport) {
-    dumpn("New debugging connection on " + aTransport.host + ":" + aTransport.port);
-
-    try {
-      let input = aTransport.openInputStream(0, 0, 0);
-      let output = aTransport.openOutputStream(0, 0, 0);
-      let transport = new DebuggerTransport(input, output);
-      DebuggerServer._onConnection(transport);
-    } catch (e) {
-      dumpn("Couldn't initialize connection: " + e + " - " + e.stack);
-    }
-  },
-
-  onStopListening: function DH_onStopListening() { },
-
-  /**
-   * Raises an exception if the server has not been properly initialized.
-   */
-  _checkInit: function DH_checkInit() {
-    if (!this._transportInitialized) {
-      throw "DebuggerServer has not been initialized.";
-    }
-
-    if (!this.createRootActor) {
-      throw "Use DebuggerServer.addActors() to add a root actor implementation.";
-    }
-  },
-
-  /**
-   * Create a new debugger connection for the given transport.  Called
-   * after connectPipe() or after an incoming socket connection.
-   */
-  _onConnection: function DH_onConnection(aTransport) {
-    let connID = "conn" + this._nextConnID++ + '.';
-    let conn = new DebuggerServerConnection(connID, aTransport);
-    this._connections[connID] = conn;
-
-    // Create a root actor for the connection and send the hello packet.
-    conn.rootActor = this.createRootActor(conn);
-    conn.addActor(conn.rootActor);
-    aTransport.send(conn.rootActor.sayHello());
-    aTransport.ready();
-  },
-
-  /**
-   * Remove the connection from the debugging server.
-   */
-  _connectionClosed: function DH_connectionClosed(aConnection) {
-    delete this._connections[aConnection.prefix];
-  }
-};
-
-/**
- * Construct an ActorPool.
- *
- * ActorPools are actorID -> actor mapping and storage.  These are
- * used to accumulate and quickly dispose of groups of actors that
- * share a lifetime.
- */
-function ActorPool(aConnection)
-{
-  this.conn = aConnection;
-  this._cleanups = {};
-  this._actors = {};
-}
+// Load the debugging server in a sandbox with its own compartment.
+var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
+                      .createInstance(Ci.nsIPrincipal);
 
-ActorPool.prototype = {
-  /**
-   * Add an actor to the actor pool.  If the actor doesn't have an ID,
-   * allocate one from the connection.
-   *
-   * @param aActor object
-   *        The actor implementation.  If the object has a
-   *        'disconnected' property, it will be called when the actor
-   *        pool is cleaned up.
-   */
-  addActor: function AP_addActor(aActor) {
-    aActor.conn = this.conn;
-    if (!aActor.actorID) {
-      aActor.actorID = this.conn.allocID(aActor.actorPrefix || undefined);
-    }
-
-    if (aActor.registeredPool) {
-      aActor.registeredPool.removeActor(aActor);
-    }
-    aActor.registeredPool = this;
-
-    this._actors[aActor.actorID] = aActor;
-    if (aActor.disconnect) {
-      this._cleanups[aActor.actorID] = aActor;
-    }
-  },
-
-  get: function AP_get(aActorID) {
-    return this._actors[aActorID];
-  },
-
-  has: function AP_has(aActorID) {
-    return aActorID in this._actors;
-  },
-
-  /**
-   * Remove an actor from the actor pool.
-   */
-  removeActor: function AP_remove(aActorID) {
-    delete this._actors[aActorID];
-    delete this._cleanups[aActorID];
-  },
-
-  /**
-   * Run all cleanups previously registered with addCleanup.
-   */
-  cleanup: function AP_cleanup() {
-    for each (let actor in this._cleanups) {
-      actor.disconnect();
-    }
-    this._cleanups = {};
-  }
-}
-
-/**
- * Creates a DebuggerServerConnection.
- *
- * Represents a connection to this debugging global from a client.
- * Manages a set of actors and actor pools, allocates actor ids, and
- * handles incoming requests.
- *
- * @param aPrefix string
- *        All actor IDs created by this connection should be prefixed
- *        with aPrefix.
- * @param aTransport transport
- *        Packet transport for the debugging protocol.
- */
-function DebuggerServerConnection(aPrefix, aTransport)
-{
-  this._prefix = aPrefix;
-  this._transport = aTransport;
-  this._transport.hooks = this;
-  this._nextID = 1;
-
-  this._actorPool = new ActorPool(this);
-  this._extraPools = [];
-}
-
-DebuggerServerConnection.prototype = {
-  _prefix: null,
-  get prefix() { return this._prefix },
-
-  _transport: null,
-  get transport() { return this._transport },
-
-  send: function DSC_send(aPacket) {
-    this.transport.send(aPacket);
-  },
-
-  allocID: function DSC_allocID(aPrefix) {
-    return this.prefix + (aPrefix || '') + this._nextID++;
-  },
-
-  /**
-   * Add a map of actor IDs to the connection.
-   */
-  addActorPool: function DSC_addActorPool(aActorPool) {
-    this._extraPools.push(aActorPool);
-  },
-
-  /**
-   * Remove a previously-added pool of actors to the connection.
-   */
-  removeActorPool: function DSC_removeActorPool(aActorPool) {
-    let index = this._extraPools.splice(this._extraPools.lastIndexOf(aActorPool), 1);
-  },
+var gGlobal = Cu.Sandbox(systemPrincipal);
+gGlobal.importFunction(loadSubScript);
+gGlobal.loadSubScript("chrome://global/content/devtools/dbg-server.js");
 
-  /**
-   * Add an actor to the default actor pool for this connection.
-   */
-  addActor: function DSC_addActor(aActor) {
-    this._actorPool.addActor(aActor);
-  },
-
-  /**
-   * Remove an actor to the default actor pool for this connection.
-   */
-  removeActor: function DSC_removeActor(aActor) {
-    this._actorPool.removeActor(aActor);
-  },
-
-  /**
-   * Add a cleanup to the default actor pool for this connection.
-   */
-  addCleanup: function DSC_addCleanup(aCleanup) {
-    this._actorPool.addCleanup(aCleanup);
-  },
-
-  /**
-   * Look up an actor implementation for an actorID.  Will search
-   * all the actor pools registered with the connection.
-   *
-   * @param aActorID string
-   *        Actor ID to look up.
-   */
-  getActor: function DSC_getActor(aActorID) {
-    if (this._actorPool.has(aActorID)) {
-      return this._actorPool.get(aActorID);
-    }
-
-    for each (let pool in this._extraPools) {
-      if (pool.has(aActorID)) {
-        return pool.get(aActorID);
-      }
-    }
-
-    if (aActorID === "root") {
-      return this.rootActor;
-    }
-
-    return null;
-  },
-
-  // Transport hooks.
-
-  /**
-   * Called by DebuggerTransport to dispatch incoming packets as appropriate.
-   *
-   * @param aPacket object
-   *        The incoming packet.
-   */
-  onPacket: function DSC_onPacket(aPacket) {
-    let actor = this.getActor(aPacket.to);
-    if (!actor) {
-      this.transport.send({ from: aPacket.to ? aPacket.to : "root",
-                            error: "noSuchActor" });
-      return;
-    }
-
-    var ret = null;
-
-    // Dispatch the request to the actor.
-    if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
-      try {
-        ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
-      } catch(e) {
-        Cu.reportError(e);
-        ret = { error: "unknownError",
-                message: "An unknown error has occurred while processing request." };
-      }
-    } else {
-      ret = { error: "unrecognizedPacketType",
-              message: 'Actor "' + actor.actorID + '" does not recognize the packet type "' + aPacket.type + '"' };
-    }
-
-    if (!ret) {
-      // XXX: The actor wasn't ready to reply yet, don't process new
-      // requests until it does.
-      return;
-    }
-
-    if (!ret.from) {
-      ret.from = aPacket.to;
-    }
-
-    this.transport.send(ret);
-  },
-
-  /**
-   * Called by DebuggerTransport when the underlying stream is closed.
-   *
-   * @param aStatus nsresult
-   *        The status code that corresponds to the reason for closing
-   *        the stream.
-   */
-  onClosed: function DSC_onClosed(aStatus) {
-    dumpn("Cleaning up connection.");
-
-    this._actorPool.cleanup();
-    this._actorPool = null;
-    this._extraPools.map(function(p) { p.cleanup(); });
-    this._extraPools = null;
-
-    DebuggerServer._connectionClosed(this);
-  }
-};
+var DebuggerServer = gGlobal.DebuggerServer;
--- a/toolkit/devtools/jar.mn
+++ b/toolkit/devtools/jar.mn
@@ -1,4 +1,5 @@
 toolkit.jar:
   content/global/devtools/dbg-transport.js        (debugger/dbg-transport.js)
+  content/global/devtools/dbg-server.js        		(debugger/server/dbg-server.js)
   content/global/devtools/dbg-script-actors.js    (debugger/server/dbg-script-actors.js)
   content/global/devtools/dbg-browser-actors.js   (debugger/server/dbg-browser-actors.js)