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 495717 26d2f8e018b50fb4638ac9278d959103729fa507
parent 495716 632c0d2d8c2459422a8c2d8743b4f925da0596ef
child 495718 ccf9864ee59f8f62787c28a73c4042ed5f304cee
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1492265
milestone64.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 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");