Bug 1268134 - Add client and toolbox access to specific windows. r=ochameau draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Thu, 14 Apr 2016 17:09:49 -0500
changeset 487698 8570d3c1d337db47140a00040a386154e532a412
parent 487697 74018ee007f6775674a1665afa53f7c84b23f0be
child 487699 bd457cb09af483ba3c2ce7c3bec26e638fee6dbd
push id46299
push userbmo:jryans@gmail.com
push dateWed, 22 Feb 2017 00:00:11 +0000
reviewersochameau
bugs1268134
milestone54.0a1
Bug 1268134 - Add client and toolbox access to specific windows. r=ochameau MozReview-Commit-ID: 3IILOc6gZFi
devtools/client/framework/target-from-url.js
devtools/client/framework/test/browser_target_from_url.js
devtools/shared/client/main.js
--- a/devtools/client/framework/target-from-url.js
+++ b/devtools/client/framework/target-from-url.js
@@ -1,45 +1,48 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { Cu, Ci } = require("chrome");
-
 const { TargetFactory } = require("devtools/client/framework/target");
 const { DebuggerServer } = require("devtools/server/main");
 const { DebuggerClient } = require("devtools/shared/client/main");
 const { Task } = require("devtools/shared/task");
 
 /**
  * Construct a Target for a given URL object having various query parameters:
  *
  * host:
  *    {String} The hostname or IP address to connect to.
  * port:
  *    {Number} The TCP port to connect to, to use with `host` argument.
  * ws:
  *    {Boolean} If true, connect via websocket instread of regular TCP connection.
  *
- * type: tab, process
- *    {String} The type of target to connect to.  Currently tabs and processes are supported types.
+ * type: tab, process, window
+ *    {String} The type of target to connect to.
  *
- * If type="tab":
+ * If type == "tab":
  * id:
  *    {Number} the tab outerWindowID
  * chrome: Optional
- *    {Boolean} Force the creation of a chrome target. Gives more privileges to the tab
- *    actor. Allows chrome execution in the webconsole and see chrome files in
- *    the debugger. (handy when contributing to firefox)
+ *    {Boolean} Force the creation of a chrome target. Gives more privileges to
+ *    the tab actor. Allows chrome execution in the webconsole and see chrome
+ *    files in the debugger. (handy when contributing to firefox)
  *
- * If type="process":
+ * If type == "process":
  * id:
- *    {Number} the process id to debug. Default to 0, which is the parent process.
+ *    {Number} the process id to debug. Default to 0, which is the parent
+ *    process.
+ *
+ * If type == "window":
+ * id:
+ *    {Number} the window outerWindowID
  *
  * @param {URL} url
  *        The url to fetch query params from.
  *
  * @return A target object
  */
 exports.targetFromURL = Task.async(function* (url) {
   let params = url.searchParams;
@@ -88,16 +91,36 @@ exports.targetFromURL = Task.async(funct
         isTabActor = false;
       }
     } catch (ex) {
       if (ex.error == "noProcess") {
         throw new Error("targetFromURL, process with id:'" + id + "' doesn't exist");
       }
       throw ex;
     }
+  } else if (type == "window") {
+    // Fetch target for a remote window actor
+    DebuggerServer.allowChromeProcess = true;
+    try {
+      id = parseInt(id, 10);
+      if (isNaN(id)) {
+        throw new Error("targetFromURL, window requires id parameter");
+      }
+      let response = yield client.mainRoot.getWindow({
+        outerWindowID: id,
+      });
+      form = response.window;
+      chrome = true;
+    } catch (ex) {
+      if (ex.error == "notFound") {
+        throw new Error(`targetFromURL, window with id:'${id}' ` +
+                        "doesn't exist");
+      }
+      throw ex;
+    }
   } else {
     throw new Error("targetFromURL, unsupported type='" + type + "' parameter");
   }
 
   return TargetFactory.forRemoteTab({ client, form, chrome, isTabActor });
 });
 
 function* createClient(params) {
--- a/devtools/client/framework/test/browser_target_from_url.js
+++ b/devtools/client/framework/test/browser_target_from_url.js
@@ -31,18 +31,29 @@ add_task(function* () {
   info("Test invalid type");
   try {
     yield targetFromURL(new URL("http://foo?type=x"));
     ok(false, "Shouldn't pass");
   } catch (e) {
     is(e.message, "targetFromURL, unsupported type='x' parameter");
   }
 
+  info("Test browser window");
+  let windowId = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIDOMWindowUtils)
+                       .outerWindowID;
+  target = yield targetFromURL(new URL("http://foo?type=window&id=" + windowId));
+  is(target.url, window.location.href);
+  is(target.isLocalTab, false);
+  is(target.chrome, true);
+  is(target.isTabActor, true);
+  is(target.isRemote, true);
+
   info("Test tab");
-  let windowId = browser.outerWindowID;
+  windowId = browser.outerWindowID;
   target = yield targetFromURL(new URL("http://foo?type=tab&id=" + windowId));
   assertIsTabTarget(target, TEST_URI);
 
   info("Test tab with chrome privileges");
   target = yield targetFromURL(new URL("http://foo?type=tab&id=" + windowId + "&chrome"));
   assertIsTabTarget(target, TEST_URI, true);
 
   info("Test invalid tab id");
--- a/devtools/shared/client/main.js
+++ b/devtools/shared/client/main.js
@@ -1737,16 +1737,37 @@ RootClient.prototype = {
         throw new Error("Unsupported argument given to getTab request");
       }
     }
 
     return this.request(packet);
   },
 
   /**
+   * Fetch the WindowActor for a specific window, like a browser window in
+   * Firefox, but it can be used to reach any window in the process.
+   *
+   * @param number outerWindowID
+   *        The outerWindowID of the top level window you are looking for.
+   */
+  getWindow: function ({ outerWindowID }) {
+    if (!outerWindowID) {
+      throw new Error("Must specify outerWindowID");
+    }
+
+    let packet = {
+      to: this.actor,
+      type: "getWindow",
+      outerWindowID,
+    };
+
+    return this.request(packet);
+  },
+
+  /**
    * Description of protocol's actors and methods.
    *
    * @param function onResponse
    *        Called with the response packet.
    */
   protocolDescription: DebuggerClient.requester({ type: "protocolDescription" }),
 
   /*