Bug 1492265 - Use a content process target actor for xpcshell debugging r=jdescottes on a CLOSED TREE
☠☠ backed out by 88544bf70da7 ☠ ☠
authorAlexandre Poirot <poirot.alex@gmail.com>
Mon, 08 Oct 2018 14:26:05 +0000
changeset 488422 26d2f8e018b50fb4638ac9278d959103729fa507
parent 488421 632c0d2d8c2459422a8c2d8743b4f925da0596ef
child 488423 ccf9864ee59f8f62787c28a73c4042ed5f304cee
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersjdescottes
bugs1492265
milestone64.0a1
Bug 1492265 - Use a content process target actor for xpcshell debugging r=jdescottes on a CLOSED TREE MozReview-Commit-ID: J9XTgC0EBPG Depends on D7415 Differential Revision: https://phabricator.services.mozilla.com/D7416
devtools/client/framework/target.js
devtools/server/actors/root.js
devtools/server/tests/unit/test_xpcshell_debugging.js
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -224,18 +224,20 @@ function TabTarget({ form, client, chrom
   // target actor that doesn't have any valid browsing context.
   // (Once FF63 is no longer supported, we can remove the `else` branch and only look
   // for the traits)
   if (this._form.traits && ("isBrowsingContext" in this._form.traits)) {
     this._isBrowsingContext = this._form.traits.isBrowsingContext;
   } else {
     // browser content toolbox's form will be of the form:
     //   server0.conn0.content-process0/contentProcessTarget7
+    // while xpcshell debugging will be:
+    //   server1.conn0.contentProcessTarget7
     const isContentProcessTarget =
-      this._form.actor.match(/conn\d+\.content-process\d+\/contentProcessTarget\d+/);
+      this._form.actor.match(/conn\d+\.(content-process\d+\/)?contentProcessTarget\d+/);
     this._isBrowsingContext = !this.isLegacyAddon && !isContentProcessTarget;
   }
 
   // Cache of already created targed-scoped fronts
   // [typeName:string => Front instance]
   this.fronts = new Map();
   // Temporary fix for bug #1493131 - inspector has a different life cycle
   // than most other fronts because it is closely related to the toolbox.
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -9,16 +9,20 @@
 const { Cu } = require("chrome");
 const Services = require("Services");
 const { Pool } = require("devtools/shared/protocol");
 const { LazyPool, createExtraActors } = require("devtools/shared/protocol/lazy-pool");
 const { DebuggerServer } = require("devtools/server/main");
 
 loader.lazyRequireGetter(this, "ChromeWindowTargetActor",
   "devtools/server/actors/targets/chrome-window", true);
+loader.lazyRequireGetter(this, "ContentProcessTargetActor",
+  "devtools/server/actors/targets/content-process", true);
+loader.lazyRequireGetter(this, "ParentProcessTargetActor",
+  "devtools/server/actors/targets/parent-process", true);
 
 /* Root actor for the remote debugging protocol. */
 
 /**
  * Create a remote debugging protocol root actor.
  *
  * @param connection
  *     The DebuggerServerConnection whose root actor we are constructing.
@@ -516,26 +520,40 @@ RootActor.prototype = {
     }
     if (("id" in request) && typeof (request.id) != "number") {
       return { error: "wrongParameter",
                message: "getProcess requires a valid `id` attribute." };
     }
     // If the request doesn't contains id parameter or id is 0
     // (id == 0, based on onListProcesses implementation)
     if ((!("id" in request)) || request.id === 0) {
-      if (this._parentProcessTargetActor && (!this._parentProcessTargetActor.docShell ||
-          this._parentProcessTargetActor.docShell.isBeingDestroyed)) {
+      // Check if we are running on xpcshell. hiddenDOMWindow is going to throw on it.
+      // When running on xpcshell, there is no valid browsing context to attach to
+      // and so ParentProcessTargetActor doesn't make sense as it inherits from
+      // BrowsingContextTargetActor. So instead use ContentProcessTargetActor, which
+      // matches xpcshell needs.
+      let isXpcshell = true;
+      try {
+        isXpcshell = !Services.wm.getMostRecentWindow(null) &&
+                     !Services.appShell.hiddenDOMWindow;
+      } catch (e) {}
+
+      if (!isXpcshell && this._parentProcessTargetActor &&
+          (!this._parentProcessTargetActor.docShell ||
+            this._parentProcessTargetActor.docShell.isBeingDestroyed)) {
         this._parentProcessTargetActor.destroy();
         this._parentProcessTargetActor = null;
       }
       if (!this._parentProcessTargetActor) {
-        // Create a ParentProcessTargetActor for the parent process
-        const { ParentProcessTargetActor } =
-          require("devtools/server/actors/targets/parent-process");
-        this._parentProcessTargetActor = new ParentProcessTargetActor(this.conn);
+        // Create the target actor for the parent process
+        if (isXpcshell) {
+          this._parentProcessTargetActor = new ContentProcessTargetActor(this.conn);
+        } else {
+          this._parentProcessTargetActor = new ParentProcessTargetActor(this.conn);
+        }
         this._globalActorPool.manage(this._parentProcessTargetActor);
       }
 
       return { form: this._parentProcessTargetActor.form() };
     }
 
     const { id } = request;
     const mm = Services.ppmm.getChildAt(id);
--- a/devtools/server/tests/unit/test_xpcshell_debugging.js
+++ b/devtools/server/tests/unit/test_xpcshell_debugging.js
@@ -23,19 +23,18 @@ add_task(async function() {
   // Ensure that global actors are available. Just test the device actor.
   const deviceFront = await client.mainRoot.getFront("device");
   const desc = await deviceFront.getDescription();
   equal(desc.geckobuildid, Services.appinfo.platformBuildID, "device actor works");
 
   // Even though we have no tabs, getProcess gives us the chromeDebugger.
   const response = await client.getProcess();
 
-  const actor = response.form.actor;
-  const [, tabClient] = await client.attachTarget(actor);
-  const [, threadClient] = await tabClient.attachThread(null);
+  const { chromeDebugger } = response.form;
+  const [, threadClient] = await client.attachThread(chromeDebugger);
   const onResumed = new Promise(resolve => {
     threadClient.addOneTimeListener("paused", (event, packet) => {
       equal(packet.why.type, "breakpoint",
           "yay - hit the breakpoint at the first line in our script");
       // Resume again - next stop should be our "debugger" statement.
       threadClient.addOneTimeListener("paused", (event, packet) => {
         equal(packet.why.type, "debuggerStatement",
               "yay - hit the 'debugger' statement in our script");