Bug 1485676 - Connect to local server from TargetFactory.forTab and make TabTarget always remote-like. r=yulia
☠☠ backed out by 99b4f09fa32c ☠ ☠
authorAlexandre Poirot <poirot.alex@gmail.com>
Tue, 21 Aug 2018 08:05:21 -0700
changeset 493538 f9ef30ae3f7f21cc8e92f04575a8d9be0bc9c283
parent 493537 a83636fab16af5537d168c004f812633722e83f4
child 493539 e63025150c7a16f6881b1332cc1c52e991521c3d
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)
reviewersyulia
bugs1485676
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 1485676 - Connect to local server from TargetFactory.forTab and make TabTarget always remote-like. r=yulia Tags: #secure-revision Bug #: 1485676 Differential Revision: https://phabricator.services.mozilla.com/D4078 MozReview-Commit-ID: JAwiySsBZBu
browser/components/extensions/test/browser/browser_ext_devtools_panels_elements.js
browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js
devtools/client/accessibility/test/browser/head.js
devtools/client/application/test/head.js
devtools/client/canvasdebugger/test/head.js
devtools/client/debugger/new/test/mochitest/head.js
devtools/client/debugger/test/mochitest/browser_dbg_break-unselected.js
devtools/client/debugger/test/mochitest/head.js
devtools/client/dom/test/head.js
devtools/client/framework/devtools-browser.js
devtools/client/framework/devtools.js
devtools/client/framework/target.js
devtools/client/framework/test/browser_devtools_api.js
devtools/client/framework/test/browser_devtools_api_destroy.js
devtools/client/framework/test/browser_ignore_toolbox_network_requests.js
devtools/client/framework/test/browser_keybindings_02.js
devtools/client/framework/test/browser_keybindings_03.js
devtools/client/framework/test/browser_menu_api.js
devtools/client/framework/test/browser_new_activation_workflow.js
devtools/client/framework/test/browser_target_events.js
devtools/client/framework/test/browser_toolbox_custom_host.js
devtools/client/framework/test/browser_toolbox_dynamic_registration.js
devtools/client/framework/test/browser_toolbox_getpanelwhenready.js
devtools/client/framework/test/browser_toolbox_highlight.js
devtools/client/framework/test/browser_toolbox_hosts.js
devtools/client/framework/test/browser_toolbox_hosts_size.js
devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
devtools/client/framework/test/browser_toolbox_options.js
devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
devtools/client/framework/test/browser_toolbox_options_disable_cache-02.js
devtools/client/framework/test/browser_toolbox_options_disable_js.js
devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
devtools/client/framework/test/browser_toolbox_options_frames_button.js
devtools/client/framework/test/browser_toolbox_options_multiple_tabs.js
devtools/client/framework/test/browser_toolbox_raise.js
devtools/client/framework/test/browser_toolbox_ready.js
devtools/client/framework/test/browser_toolbox_selected_tool_unavailable.js
devtools/client/framework/test/browser_toolbox_sidebar.js
devtools/client/framework/test/browser_toolbox_sidebar_events.js
devtools/client/framework/test/browser_toolbox_sidebar_existing_tabs.js
devtools/client/framework/test/browser_toolbox_sidebar_overflow_menu.js
devtools/client/framework/test/browser_toolbox_split_console.js
devtools/client/framework/test/browser_toolbox_tabsswitch_shortcuts.js
devtools/client/framework/test/browser_toolbox_telemetry_activate_splitconsole.js
devtools/client/framework/test/browser_toolbox_telemetry_close.js
devtools/client/framework/test/browser_toolbox_telemetry_enter.js
devtools/client/framework/test/browser_toolbox_telemetry_exit.js
devtools/client/framework/test/browser_toolbox_theme_registration.js
devtools/client/framework/test/browser_toolbox_toggle.js
devtools/client/framework/test/browser_toolbox_tool_ready.js
devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
devtools/client/framework/test/browser_toolbox_window_reload_target.js
devtools/client/framework/test/browser_toolbox_window_shortcuts.js
devtools/client/framework/test/browser_toolbox_window_title_changes.js
devtools/client/framework/test/browser_toolbox_window_title_frame_select.js
devtools/client/framework/test/browser_toolbox_zoom.js
devtools/client/framework/test/browser_toolbox_zoom_popup.js
devtools/client/framework/test/helper_disable_cache.js
devtools/client/inspector/animation/test/head.js
devtools/client/inspector/rules/test/browser_rules_authored_color.js
devtools/client/inspector/rules/test/browser_rules_colorUnit.js
devtools/client/inspector/rules/test/browser_rules_flexbox-highlighter-on-reload.js
devtools/client/inspector/rules/test/browser_rules_grid-highlighter-on-reload.js
devtools/client/inspector/test/browser_inspector_destroy-before-ready.js
devtools/client/inspector/test/browser_inspector_initialization.js
devtools/client/inspector/test/browser_inspector_inspect_node_contextmenu.js
devtools/client/inspector/test/browser_inspector_switch-to-inspector-on-pick.js
devtools/client/inspector/test/head.js
devtools/client/memory/test/browser/head.js
devtools/client/menus.js
devtools/client/netmonitor/test/head.js
devtools/client/performance/test/helpers/panel-utils.js
devtools/client/responsive.html/test/browser/browser_telemetry_activate_rdm.js
devtools/client/responsive.html/test/browser/browser_toolbox_swap_browsers.js
devtools/client/responsive.html/test/browser/browser_toolbox_swap_inspector.js
devtools/client/scratchpad/scratchpad.js
devtools/client/scratchpad/test/browser_scratchpad_close_toolbox.js
devtools/client/scratchpad/test/browser_scratchpad_menubar.js
devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
devtools/client/shadereditor/test/head.js
devtools/client/shared/link.js
devtools/client/shared/test/browser_telemetry_button_eyedropper.js
devtools/client/shared/test/browser_telemetry_button_paintflashing.js
devtools/client/shared/test/browser_telemetry_button_responsive.js
devtools/client/shared/test/browser_telemetry_button_scratchpad.js
devtools/client/shared/test/browser_telemetry_sidebar.js
devtools/client/shared/test/browser_theme_switching.js
devtools/client/shared/test/head.js
devtools/client/shared/test/shared-head.js
devtools/client/sourceeditor/test/browser_css_autocompletion.js
devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
devtools/client/storage/test/browser_storage_indexeddb_overflow.js
devtools/client/storage/test/browser_storage_overflow.js
devtools/client/storage/test/head.js
devtools/client/styleeditor/test/browser_styleeditor_fetch-from-netmonitor.js
devtools/client/styleeditor/test/browser_styleeditor_loading.js
devtools/client/styleeditor/test/browser_styleeditor_sync.js
devtools/client/styleeditor/test/browser_styleeditor_xul.js
devtools/client/styleeditor/test/head.js
devtools/client/webaudioeditor/test/head.js
devtools/client/webconsole/test/mochitest/browser_console_webconsole_ctrlw_close_tab.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
devtools/client/webconsole/test/mochitest/browser_webconsole_close_unfocused_window.js
devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js
devtools/client/webconsole/test/mochitest/browser_webconsole_location_scratchpad_link.js
devtools/client/webconsole/test/mochitest/browser_webconsole_location_styleeditor_link.js
devtools/client/webconsole/test/mochitest/browser_webconsole_network_attach.js
devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_openinnet.js
devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_status_code.js
devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js
devtools/client/webconsole/test/mochitest/browser_webconsole_shows_reqs_from_netmonitor.js
devtools/client/webconsole/test/mochitest/browser_webconsole_split.js
devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_scratchpad_link.js
devtools/client/webconsole/test/mochitest/head.js
devtools/docs/frontend/telemetry.md
devtools/server/tests/mochitest/test_framerate_04.html
dom/security/test/cors/head.js
dom/security/test/general/browser_test_FTP_console_warning.js
--- a/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements.js
@@ -74,17 +74,17 @@ add_task(async function test_devtools_pa
        </body>
       </html>`,
       "devtools_page.js": devtools_page,
     },
   });
 
   await extension.startup();
 
-  let target = devtools.TargetFactory.forTab(tab);
+  let target = await devtools.TargetFactory.forTab(tab);
 
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
   info("developer toolbox opened");
 
   await extension.awaitMessage("devtools_page_loaded");
 
   await toolbox.selectTool("inspector");
 
--- a/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js
@@ -109,17 +109,17 @@ add_task(async function test_devtools_pa
        </body>
       </html>`,
       "devtools_page.js": devtools_page,
     },
   });
 
   await extension.startup();
 
-  let target = devtools.TargetFactory.forTab(tab);
+  let target = await devtools.TargetFactory.forTab(tab);
 
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
   info("developer toolbox opened");
 
   await extension.awaitMessage("devtools_page_loaded");
 
   const waitInspector = toolbox.once("inspector-selected");
   toolbox.selectTool("inspector");
--- a/devtools/client/accessibility/test/browser/head.js
+++ b/devtools/client/accessibility/test/browser/head.js
@@ -151,17 +151,17 @@ async function disableAccessibilityInspe
  * Open the Accessibility panel for the given tab.
  *
  * @param {Element} tab
  *        Optional tab element for which you want open the Accessibility panel.
  *        The default tab is taken from the global variable |tab|.
  * @return a promise that is resolved once the panel is open.
  */
 async function initAccessibilityPanel(tab = gBrowser.selectedTab) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "accessibility");
   return toolbox.getCurrentPanel();
 }
 
 /**
  * Check the state of the accessibility tree.
  * @param  {document} doc       panel documnent.
  * @param  {Array}    expected  an array that represents an expected row list.
--- a/devtools/client/application/test/head.js
+++ b/devtools/client/application/test/head.js
@@ -42,17 +42,17 @@ function getWorkerContainers(doc) {
 
 function navigate(target, url, waitForTargetEvent = "navigate") {
   executeSoon(() => target.activeTab.navigateTo(url));
   return once(target, waitForTargetEvent);
 }
 
 async function openNewTabAndApplicationPanel(url) {
   const tab = await addTab(url);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   const toolbox = await gDevTools.showToolbox(target, "application");
   const panel = toolbox.getCurrentPanel();
   return { panel, tab, target, toolbox };
 }
 
 async function unregisterAllWorkers(client) {
--- a/devtools/client/canvasdebugger/test/head.js
+++ b/devtools/client/canvasdebugger/test/head.js
@@ -122,51 +122,51 @@ function initServer() {
 }
 
 function initCallWatcherBackend(aUrl) {
   info("Initializing a call watcher front.");
   initServer();
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+
     await registerActorInContentProcess("chrome://mochitests/content/browser/devtools/client/canvasdebugger/test/call-watcher-actor.js", {
       prefix: "callWatcher",
       constructor: "CallWatcherActor",
       type: { target: true }
     });
 
+    const target = await TargetFactory.forTab(tab);
     await target.makeRemote();
-
     const front = new CallWatcherFront(target.client, target.form);
     return { target, front };
   })();
 }
 
 function initCanvasDebuggerBackend(aUrl) {
   info("Initializing a canvas debugger front.");
   initServer();
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     const front = new CanvasFront(target.client, target.form);
     return { target, front };
   })();
 }
 
 function initCanvasDebuggerFrontend(aUrl) {
   info("Initializing a canvas debugger pane.");
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     Services.prefs.setBoolPref("devtools.canvasdebugger.enabled", true);
     const toolbox = await gDevTools.showToolbox(target, "canvasdebugger");
     const panel = toolbox.getCurrentPanel();
     return { target, panel };
   })();
--- a/devtools/client/debugger/new/test/mochitest/head.js
+++ b/devtools/client/debugger/new/test/mochitest/head.js
@@ -64,17 +64,17 @@ async function takeScreenshot(dbg) {
   context.drawWindow(dbg.win, 0, 0, canvas.width, canvas.height, "white");
   await waitForTime(1000);
   dump(`[SCREENSHOT] ${canvas.toDataURL()}\n`);
 }
 
 // Attach a debugger to a tab, returning a promise that resolves with the
 // debugger's toolbox.
 async function attachDebugger(tab) {
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
   let toolbox = await gDevTools.showToolbox(target, "jsdebugger");
   return toolbox;
 }
 
 // Return a promise that resolves when a breakpoint has been set.
 async function setBreakpoint(threadClient, expectedFile, lineno) {
   let {sources} = await threadClient.getSources();
   ok(sources.length == 1, "Got one source");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-unselected.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-unselected.js
@@ -8,17 +8,17 @@
  * the debugger UI has been initialized.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html";
 
 function test() {
   Task.spawn(function* () {
     const tab = yield getTab(TAB_URL);
-    const target = TargetFactory.forTab(tab);
+    const target = yield TargetFactory.forTab(tab);
     const toolbox = yield gDevTools.showToolbox(target, "webconsole");
 
     is(toolbox.currentToolId, "webconsole", "Console is the current panel");
 
     toolbox.target.on("thread-paused", Task.async(function* () {
       // Wait for the toolbox to handle the event and switch tools
       yield waitForTick();
 
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -38,17 +38,17 @@ Services.prefs.setBoolPref("devtools.deb
 registerCleanupFunction(async function() {
   Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
 
   info("finish() was called, cleaning up...");
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
 
   while (gBrowser && gBrowser.tabs && gBrowser.tabs.length > 1) {
     info("Destroying toolbox.");
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    let target = await TargetFactory.forTab(gBrowser.selectedTab);
     await gDevTools.closeToolbox(target);
 
     info("Removing tab.");
     gBrowser.removeCurrentTab();
   }
 
   // Properly shut down the server to avoid memory leaks.
   DebuggerServer.destroy();
@@ -548,17 +548,17 @@ let initDebugger = Task.async(function*(
     // only once the panel is ready. That to be able to safely catch the
     // SOURCE_SHOWN event.
     tab = yield addTab("about:blank", window);
     url = urlOrTab;
   }
   info("Debugee tab added successfully: " + urlOrTab);
 
   let debuggee = tab.linkedBrowser.contentWindowAsCPOW.wrappedJSObject;
-  let target = TargetFactory.forTab(tab);
+  let target = yield TargetFactory.forTab(tab);
 
   let toolbox = yield gDevTools.showToolbox(target, "jsdebugger");
   info("Debugger panel shown successfully.");
 
   let debuggerPanel = toolbox.getCurrentPanel();
   let panelWin = debuggerPanel.panelWin;
   let { Sources } = panelWin.DebuggerView;
 
--- a/devtools/client/dom/test/head.js
+++ b/devtools/client/dom/test/head.js
@@ -57,24 +57,21 @@ function addTestTab(url) {
 /**
  * Open the DOM panel for the given tab.
  *
  * @param {Element} tab
  *        Optional tab element for which you want open the DOM panel.
  *        The default tab is taken from the global variable |tab|.
  * @return a promise that is resolved once the web console is open.
  */
-function initDOMPanel(tab) {
-  return new Promise(resolve => {
-    const target = TargetFactory.forTab(tab || gBrowser.selectedTab);
-    gDevTools.showToolbox(target, "dom").then(toolbox => {
-      const panel = toolbox.getCurrentPanel();
-      resolve(panel);
-    });
-  });
+async function initDOMPanel(tab) {
+  const target = await TargetFactory.forTab(tab || gBrowser.selectedTab);
+  const toolbox = await gDevTools.showToolbox(target, "dom");
+  const panel = toolbox.getCurrentPanel();
+  return panel;
 }
 
 /**
  * Synthesize asynchronous click event (with clean stack trace).
  */
 function synthesizeMouseClickSoon(panel, element) {
   return new Promise(resolve => {
     executeSoon(() => {
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -476,18 +476,18 @@ var gDevToolsBrowser = exports.gDevTools
   /**
    * Hook the JS debugger tool to the "Debug Script" button of the slow script
    * dialog.
    */
   setSlowScriptDebugHandler() {
     const debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
                          .getService(Ci.nsISlowScriptDebug);
 
-    function slowScriptDebugHandler(tab, callback) {
-      const target = TargetFactory.forTab(tab);
+    async function slowScriptDebugHandler(tab, callback) {
+      const target = await TargetFactory.forTab(tab);
 
       gDevTools.showToolbox(target, "jsdebugger").then(toolbox => {
         const threadClient = toolbox.threadClient;
 
         // Break in place, which means resuming the debuggee thread and pausing
         // right before the next step happens.
         switch (threadClient.state) {
           case "paused":
@@ -539,17 +539,17 @@ var gDevToolsBrowser = exports.gDevTools
 
     debugService.remoteActivationHandler = function(browser, callback) {
       const chromeWindow = browser.ownerDocument.defaultView;
       const tab = chromeWindow.gBrowser.getTabForBrowser(browser);
       chromeWindow.gBrowser.selected = tab;
 
       slowScriptDebugHandler(tab, function() {
         callback.finishDebuggerStartup();
-      });
+      }).catch(console.error);
     };
   },
 
   /**
    * Unset the slow script debug handler.
    */
   unsetSlowScriptDebugHandler() {
     const debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
--- a/devtools/client/framework/devtools.js
+++ b/devtools/client/framework/devtools.js
@@ -686,17 +686,17 @@ DevTools.prototype = {
    *        ending with the deepest nested frame.
    * @param {Number} startTime
    *        Optional, indicates the time at which the user event related to this node
    *        inspection started. This is a `Cu.now()` timing.
    * @return {Promise} a promise that resolves when the node is selected in the inspector
    *         markup view.
    */
   async inspectNode(tab, nodeSelectors, startTime) {
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     const toolbox = await gDevTools.showToolbox(target, "inspector", null, null,
                                                 startTime, "inspect_dom");
     const inspector = toolbox.getCurrentPanel();
 
     // If the toolbox has been switched into a nested frame, we should first remove
     // selectors according to the frame depth.
     nodeSelectors.splice(0, toolbox.selectedFrameDepth);
@@ -726,17 +726,17 @@ DevTools.prototype = {
    *        and not directly in the root document.
    * @param {Number} startTime
    *        Optional, indicates the time at which the user event related to this
    *        node inspection started. This is a `Cu.now()` timing.
    * @return {Promise} a promise that resolves when the accessible object is
    *         selected in the accessibility inspector.
    */
   async inspectA11Y(tab, nodeSelectors, startTime) {
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     const toolbox = await gDevTools.showToolbox(
       target, "accessibility", null, null, startTime);
     const nodeFront = await this.findNodeFront(toolbox.walker, nodeSelectors);
     // Select the accessible object in the panel and wait for the event that
     // tells us it has been done.
     const a11yPanel = toolbox.getCurrentPanel();
     const onSelected = a11yPanel.once("new-accessible-front-selected");
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -15,30 +15,86 @@ loader.lazyRequireGetter(this, "getFront
 
 const targets = new WeakMap();
 const promiseTargets = new WeakMap();
 
 /**
  * Functions for creating Targets
  */
 const TargetFactory = exports.TargetFactory = {
+
   /**
-   * Construct a Target
+   * Construct a Target. The target will be cached for each Tab so that we create only
+   * one per tab.
+   *
+   * @param {XULTab} tab
+   *        The tab to use in creating a new target.
+   *
+   * @return A target object
+   */
+  forTab: async function(tab) {
+    let target = targets.get(tab);
+    if (target) {
+      return target;
+    }
+    const promise = this.createTargetForTab(tab);
+    // Immediately set the target's promise in cache to prevent race
+    targets.set(tab, promise);
+    target = await promise;
+    // Then replace the promise with the target object
+    targets.set(tab, target);
+    return target;
+  },
+
+  /**
+   * Constructor a target for the given tab.
+   *
    * @param {XULTab} tab
    *        The tab to use in creating a new target.
    *
    * @return A target object
    */
-  forTab: function(tab) {
-    let target = targets.get(tab);
-    if (target == null) {
-      target = new TabTarget(tab);
-      targets.set(tab, target);
+  async createTargetForTab(tab) {
+    function createLocalServer() {
+      // Since a remote protocol connection will be made, let's start the
+      // DebuggerServer here, once and for all tools.
+      DebuggerServer.init();
+
+      // When connecting to a local tab, we only need the root actor.
+      // Then we are going to call DebuggerServer.connectToFrame and talk
+      // directly with actors living in the child process.
+      // We also need browser actors for actor registry which enabled addons
+      // to register custom actors.
+      // TODO: the comment and implementation are out of sync here. See Bug 1420134.
+      DebuggerServer.registerAllActors();
+      // Enable being able to get child process actors
+      DebuggerServer.allowChromeProcess = true;
     }
-    return target;
+
+    function createLocalClient() {
+      return new DebuggerClient(DebuggerServer.connectPipe());
+    }
+
+    createLocalServer();
+    const client = createLocalClient();
+
+    // Connect the local client to the local server
+    await client.connect();
+
+    // Fetch the FrameTargetActor form
+    const response = await client.getTab({ tab });
+
+    return new TabTarget({
+      client,
+      form: response.tab,
+      // A local TabTarget will never perform chrome debugging.
+      chrome: false,
+      isBrowsingContext: true,
+      tab,
+    });
   },
 
   /**
    * Return a promise of a Target for a remote tab.
    * @param {Object} options
    *        The options object has the following properties:
    *        {
    *          form: the remote protocol form of a tab,
@@ -106,42 +162,62 @@ const TargetFactory = exports.TargetFact
  * - visible: The target is visible (for TargetTab, tab is selected)
  *
  * Comparing Targets: 2 instances of a Target object can point at the same
  * thing, so t1 !== t2 and t1 != t2 even when they represent the same object.
  * To compare to targets use 't1.equals(t2)'.
  */
 
 /**
- * A TabTarget represents a page living in a browser tab. Generally these will
- * be web pages served over http(s), but they don't have to be.
+ * A TabTarget represents a debuggable context. It can be a browser tab, a tab on
+ * a remote device, like a tab on Firefox for Android. But it can also be an add-on,
+ * as well as firefox parent process, or just one of its content process.
+ * A TabTarget is related to a given TargetActor, for which we pass the form as
+ * argument.
+ *
+ * For now, only workers are having a distinct Target class called WorkerTarget.
+ *
+ * @param {Object} form
+ *                 The TargetActor's form to be connected to.
+ * @param {DebuggerClient} client
+ *                 The DebuggerClient instance to be used to debug this target.
+ * @param {Boolean} chrome
+ *                  True, if we allow to see privileged resources like JSM, xpcom,
+ *                  frame scripts...
+ * @param {Boolean} isBrowsingContext (optional)
+ *                  To be set to True if the Target actor inherits from BrowsingContextActor.
+ *                  This argument is considered to be True is not passed.
+ * @param {xul:tab} tab (optional)
+ *                  If the target is a local Firefox tab, a reference to the firefox
+ *                  frontend tab object.
  */
-function TabTarget(tab) {
+function TabTarget({ form, client, chrome, isBrowsingContext = true, tab = null }) {
   EventEmitter.decorate(this);
   this.destroy = this.destroy.bind(this);
   this.activeTab = this.activeConsole = null;
-  // Only real tabs need initialization here. Placeholder objects for remote
-  // targets will be initialized after a makeRemote method call.
-  if (tab && !["client", "form", "chrome"].every(tab.hasOwnProperty, tab)) {
+
+  this._form = form;
+  this._url = form.url;
+  this._title = form.title;
+
+  this._client = client;
+  this._chrome = chrome;
+
+  // When debugging local tabs, we also have a reference to the Firefox tab
+  // This is used to:
+  // * distinguish local tabs from remote (see target.isLocalTab)
+  // * being able to hookup into Firefox UI (see Hosts)
+  if (tab) {
     this._tab = tab;
     this._setupListeners();
-  } else {
-    this._form = tab.form;
-    this._url = this._form.url;
-    this._title = this._form.title;
+  }
 
-    this._client = tab.client;
-    this._chrome = tab.chrome;
-  }
   // Default isBrowsingContext to true if not explicitly specified
-  if (typeof tab.isBrowsingContext == "boolean") {
-    this._isBrowsingContext = tab.isBrowsingContext;
-  } else {
-    this._isBrowsingContext = true;
-  }
+  this._isBrowsingContext = isBrowsingContext;
+
   // Cache of already created targed-scoped fronts
   // [typeName:string => Front instance]
   this.fronts = new Map();
 }
 
 exports.TabTarget = TabTarget;
 
 TabTarget.prototype = {
@@ -384,36 +460,18 @@ TabTarget.prototype = {
    * for tools that support the Remote Debugging Protocol even for local
    * connections.
    */
   makeRemote: async function() {
     if (this._remote) {
       return this._remote;
     }
 
-    if (this.isLocalTab) {
-      // Since a remote protocol connection will be made, let's start the
-      // DebuggerServer here, once and for all tools.
-      DebuggerServer.init();
-
-      // When connecting to a local tab, we only need the root actor.
-      // Then we are going to call DebuggerServer.connectToFrame and talk
-      // directly with actors living in the child process.
-      // We also need browser actors for actor registry which enabled addons
-      // to register custom actors.
-      // TODO: the comment and implementation are out of sync here. See Bug 1420134.
-      DebuggerServer.registerAllActors();
-      // Enable being able to get child process actors
-      DebuggerServer.allowChromeProcess = true;
-
-      this._client = new DebuggerClient(DebuggerServer.connectPipe());
-      // A local TabTarget will never perform chrome debugging.
-      this._chrome = false;
-    } else if (this._form.isWebExtension &&
-          this.client.mainRoot.traits.webExtensionAddonConnect) {
+    if (this._form.isWebExtension &&
+        this.client.mainRoot.traits.webExtensionAddonConnect) {
       // The addonTargetActor form is related to a WebExtensionActor instance,
       // which isn't a target actor on its own, it is an actor living in the parent
       // process with access to the addon metadata, it can control the addon (e.g.
       // reloading it) and listen to the AddonManager events related to the lifecycle of
       // the addon (e.g. when the addon is disabled or uninstalled).
       // To retrieve the target actor instance, we call its "connect" method, (which
       // fetches the target actor form from a WebExtensionTargetActor instance).
       const {form} = await this._client.request({
@@ -452,27 +510,17 @@ TabTarget.prototype = {
       const attachConsole = () => {
         this._client.attachConsole(this._form.consoleActor, [])
           .then(onConsoleAttached, response => {
             reject(
               `Unable to attach to the console [${response.error}]: ${response.message}`);
           });
       };
 
-      if (this.isLocalTab) {
-        this._client.connect()
-          .then(() => this._client.getTab({tab: this.tab}))
-          .then(response => {
-            this._form = response.tab;
-            this._url = this._form.url;
-            this._title = this._form.title;
-
-            attachTab();
-          }, e => reject(e));
-      } else if (this.isBrowsingContext) {
+      if (this.isBrowsingContext) {
         // In the remote debugging case, the protocol connection will have been
         // already initialized in the connection screen code.
         attachTab();
       } else {
         // AddonActor and chrome debugging on RootActor doesn't inherit from
         // BrowsingContextTargetActor and doesn't need to be attached.
         attachConsole();
       }
@@ -489,17 +537,19 @@ TabTarget.prototype = {
     this.tab.ownerDocument.defaultView.addEventListener("unload", this);
     this.tab.addEventListener("TabRemotenessChange", this);
   },
 
   /**
    * Teardown event listeners.
    */
   _teardownListeners: function() {
-    this._tab.ownerDocument.defaultView.removeEventListener("unload", this);
+    if (this._tab.ownerDocument.defaultView) {
+      this._tab.ownerDocument.defaultView.removeEventListener("unload", this);
+    }
     this._tab.removeEventListener("TabClose", this);
     this._tab.removeEventListener("TabRemotenessChange", this);
   },
 
   /**
    * Setup listeners for remote debugging, updating existing ones as necessary.
    */
   _setupRemoteListeners: function() {
@@ -593,24 +643,24 @@ TabTarget.prototype = {
     // remotenesschange events. But we should ignore them as at the end
     // the content doesn't change its remoteness.
     if (this._tab.isResponsiveDesignMode) {
       return;
     }
 
     // Save a reference to the tab as it will be nullified on destroy
     const tab = this._tab;
-    const onToolboxDestroyed = target => {
+    const onToolboxDestroyed = async (target) => {
       if (target != this) {
         return;
       }
       gDevTools.off("toolbox-destroyed", target);
 
       // Recreate a fresh target instance as the current one is now destroyed
-      const newTarget = TargetFactory.forTab(tab);
+      const newTarget = await TargetFactory.forTab(tab);
       gDevTools.showToolbox(newTarget);
     };
     gDevTools.on("toolbox-destroyed", onToolboxDestroyed);
   },
 
   /**
    * Target is not alive anymore.
    */
--- a/devtools/client/framework/test/browser_devtools_api.js
+++ b/devtools/client/framework/test/browser_devtools_api.js
@@ -10,17 +10,17 @@
 const toolId1 = "testtool1";
 const toolId2 = "testtool2";
 
 function test() {
   addTab("about:blank").then(runTests1);
 }
 
 // Test scenario 1: the tool definition build method returns a promise.
-function runTests1(tab) {
+async function runTests1(tab) {
   const toolDefinition = {
     id: toolId1,
     isTargetSupported: () => true,
     visibilityswitch: "devtools.test-tool.enabled",
     url: "about:blank",
     label: "someLabel",
     build: function(iframeWindow, toolbox) {
       const panel = createTestPanel(iframeWindow, toolbox);
@@ -31,17 +31,17 @@ function runTests1(tab) {
   ok(gDevTools, "gDevTools exists");
   ok(!gDevTools.getToolDefinitionMap().has(toolId1),
     "The tool is not registered");
 
   gDevTools.registerTool(toolDefinition);
   ok(gDevTools.getToolDefinitionMap().has(toolId1),
     "The tool is registered");
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
 
   const events = {};
 
   // Check events on the gDevTools and toolbox objects.
   gDevTools.once(toolId1 + "-init", (toolbox, iframe) => {
     ok(iframe, "iframe argument available");
 
     toolbox.once(toolId1 + "-init", innerIframe => {
@@ -71,17 +71,17 @@ function runTests1(tab) {
     // Wait for unregisterTool to select the next tool before calling runTests2,
     // otherwise we will receive the wrong select event when waiting for
     // unregisterTool to select the next tool in continueTests below.
     toolbox.once("select", runTests2);
   });
 }
 
 // Test scenario 2: the tool definition build method returns panel instance.
-function runTests2() {
+async function runTests2() {
   const toolDefinition = {
     id: toolId2,
     isTargetSupported: () => true,
     visibilityswitch: "devtools.test-tool.enabled",
     url: "about:blank",
     label: "someLabel",
     build: function(iframeWindow, toolbox) {
       return createTestPanel(iframeWindow, toolbox);
@@ -90,17 +90,17 @@ function runTests2() {
 
   ok(!gDevTools.getToolDefinitionMap().has(toolId2),
     "The tool is not registered");
 
   gDevTools.registerTool(toolDefinition);
   ok(gDevTools.getToolDefinitionMap().has(toolId2),
     "The tool is registered");
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
 
   const events = {};
 
   // Check events on the gDevTools and toolbox objects.
   gDevTools.once(toolId2 + "-init", (toolbox, iframe) => {
     ok(iframe, "iframe argument available");
 
     toolbox.once(toolId2 + "-init", innerIframe => {
@@ -178,18 +178,18 @@ var continueTests = async function(toolb
   info("Unregistering tool");
   gDevTools.unregisterTool(toolId2);
 
   info("Destroying toolbox");
   destroyToolbox(toolbox);
 };
 
 function destroyToolbox(toolbox) {
-  toolbox.destroy().then(function() {
-    const target = TargetFactory.forTab(gBrowser.selectedTab);
+  toolbox.destroy().then(async function() {
+    const target = await TargetFactory.forTab(gBrowser.selectedTab);
     ok(gDevTools._toolboxes.get(target) == null, "gDevTools doesn't know about target");
     ok(toolbox.target == null, "toolbox doesn't know about target.");
     finishUp();
   });
 }
 
 function finishUp() {
   gBrowser.removeCurrentTab();
--- a/devtools/client/framework/test/browser_devtools_api_destroy.js
+++ b/devtools/client/framework/test/browser_devtools_api_destroy.js
@@ -4,17 +4,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests devtools API
 
 function test() {
   addTab("about:blank").then(runTests);
 }
 
-function runTests(aTab) {
+async function runTests(aTab) {
   const toolDefinition = {
     id: "testTool",
     visibilityswitch: "devtools.testTool.enabled",
     isTargetSupported: () => true,
     url: "about:blank",
     label: "someLabel",
     build: function(iframeWindow, toolbox) {
       return new Promise(resolve => {
@@ -29,17 +29,17 @@ function runTests(aTab) {
       });
     },
   };
 
   gDevTools.registerTool(toolDefinition);
 
   const collectedEvents = [];
 
-  const target = TargetFactory.forTab(aTab);
+  const target = await TargetFactory.forTab(aTab);
   gDevTools.showToolbox(target, toolDefinition.id).then(function(toolbox) {
     const panel = toolbox.getPanel(toolDefinition.id);
     ok(panel, "Tool open");
 
     gDevTools.once("toolbox-destroy", (toolbox, iframe) => {
       collectedEvents.push("toolbox-destroy");
     });
 
--- a/devtools/client/framework/test/browser_ignore_toolbox_network_requests.js
+++ b/devtools/client/framework/test/browser_ignore_toolbox_network_requests.js
@@ -10,17 +10,17 @@
 
 add_task(async function() {
   // TODO: This test tries to verify the normal behavior of the netmonitor and
   // therefore needs to avoid the explicit check for tests. Bug 1167188 will
   // allow us to remove this workaround.
   await pushPref("devtools.testing", false);
 
   let tab = await addTab(URL_ROOT + "doc_viewsource.html");
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
   let toolbox = await gDevTools.showToolbox(target, "styleeditor");
   let panel = toolbox.getPanel("styleeditor");
 
   is(panel.UI.editors.length, 1, "correct number of editors opened");
 
   const monitor = await toolbox.selectTool("netmonitor");
   const { store } = monitor.panelWin;
 
--- a/devtools/client/framework/test/browser_keybindings_02.js
+++ b/devtools/client/framework/test/browser_keybindings_02.js
@@ -16,17 +16,17 @@ const L10N = new LocalizationHelper("dev
 
 function getZoomValue() {
   return parseFloat(Services.prefs.getCharPref("devtools.toolbox.zoomValue"));
 }
 
 add_task(async function() {
   info("Create a test tab and open the toolbox");
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
 
   const {RIGHT, BOTTOM} = Toolbox.HostType;
   for (const type of [RIGHT, BOTTOM, RIGHT]) {
     info("Switch to host type " + type);
     await toolbox.switchHost(type);
 
     info("Try to use the toolbox shortcuts");
--- a/devtools/client/framework/test/browser_keybindings_03.js
+++ b/devtools/client/framework/test/browser_keybindings_03.js
@@ -13,17 +13,17 @@ const URL = "data:text/html;charset=utf8
 var {Toolbox} = require("devtools/client/framework/toolbox");
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 
 add_task(async function() {
   info("Create a test tab and open the toolbox");
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
 
   const shortcut = L10N.getStr("toolbox.toggleHost.key");
 
   const {RIGHT, BOTTOM, WINDOW} = Toolbox.HostType;
   checkHostType(toolbox, BOTTOM, RIGHT);
 
   info("Switching from bottom to right");
--- a/devtools/client/framework/test/browser_menu_api.js
+++ b/devtools/client/framework/test/browser_menu_api.js
@@ -9,17 +9,17 @@
 
 const URL = "data:text/html;charset=utf8,test page for menu api";
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
 add_task(async function() {
   info("Create a test tab and open the toolbox");
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
 
   await testMenuItems();
   await testMenuPopup(toolbox);
   await testSubmenu(toolbox);
 });
 
 function testMenuItems() {
--- a/devtools/client/framework/test/browser_new_activation_workflow.js
+++ b/devtools/client/framework/test/browser_new_activation_workflow.js
@@ -3,18 +3,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests devtools API
 
 var toolbox, target;
 
 function test() {
-  addTab("about:blank").then(function(aTab) {
-    target = TargetFactory.forTab(gBrowser.selectedTab);
+  addTab("about:blank").then(async function(aTab) {
+    target = await TargetFactory.forTab(gBrowser.selectedTab);
     loadWebConsole(aTab).then(function() {
       console.log("loaded");
     });
   });
 }
 
 function loadWebConsole(aTab) {
   ok(gDevTools, "gDevTools exists");
@@ -40,19 +40,19 @@ function selectAndCheckById(id) {
   return toolbox.selectTool(id).then(function() {
     const tab = toolbox.doc.getElementById("toolbox-tab-" + id);
     is(tab.classList.contains("selected"), true, "The " + id + " tab is selected");
     is(tab.getAttribute("aria-pressed"), "true", "The " + id + " tab is pressed");
   });
 }
 
 function testToggle() {
-  toolbox.once("destroyed", () => {
+  toolbox.once("destroyed", async () => {
     // Cannot reuse a target after it's destroyed.
-    target = TargetFactory.forTab(gBrowser.selectedTab);
+    target = await TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.showToolbox(target, "styleeditor").then(function(aToolbox) {
       toolbox = aToolbox;
       is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
       finishUp();
     });
   });
 
   toolbox.destroy();
--- a/devtools/client/framework/test/browser_target_events.js
+++ b/devtools/client/framework/test/browser_target_events.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 add_task(async function() {
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await target.makeRemote();
   is(target.tab, gBrowser.selectedTab, "Target linked to the right tab.");
 
   const willNavigate = once(target, "will-navigate");
   const navigate = once(target, "navigate");
   ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.location = "data:text/html,<meta charset='utf8'/>test navigation";
   });
--- a/devtools/client/framework/test/browser_toolbox_custom_host.js
+++ b/devtools/client/framework/test/browser_toolbox_custom_host.js
@@ -25,17 +25,17 @@ add_task(async function() {
     }
     window.addEventListener("message", onMessage);
   });
 
   let iframe = document.createElement("iframe");
   document.documentElement.appendChild(iframe);
 
   const tab = await addTab(TEST_URL);
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
   const options = { customIframe: iframe };
   let toolbox = await gDevTools.showToolbox(target, null, Toolbox.HostType.CUSTOM, options);
 
   is(toolbox.win.top, window, "Toolbox is included in browser.xul");
   is(toolbox.doc, iframe.contentDocument, "Toolbox is in the custom iframe");
 
   iframe.remove();
   await toolbox.destroy();
--- a/devtools/client/framework/test/browser_toolbox_dynamic_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_dynamic_registration.js
@@ -3,18 +3,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_URL = "data:text/html,test for dynamically registering and unregistering tools";
 
 var toolbox;
 
 function test() {
-  addTab(TEST_URL).then(tab => {
-    const target = TargetFactory.forTab(tab);
+  addTab(TEST_URL).then(async tab => {
+    const target = await TargetFactory.forTab(tab);
     gDevTools.showToolbox(target).then(testRegister);
   });
 }
 
 function testRegister(aToolbox) {
   toolbox = aToolbox;
   gDevTools.once("tool-registered", toolRegistered);
 
--- a/devtools/client/framework/test/browser_toolbox_getpanelwhenready.js
+++ b/devtools/client/framework/test/browser_toolbox_getpanelwhenready.js
@@ -7,17 +7,17 @@
 // resolutions regardless of whether it has opened first.
 
 var toolbox = null;
 
 const URL = "data:text/html;charset=utf8,test for getPanelWhenReady";
 
 add_task(async function() {
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   toolbox = await gDevTools.showToolbox(target);
 
   const debuggerPanelPromise = toolbox.getPanelWhenReady("jsdebugger");
   await toolbox.selectTool("jsdebugger");
   const debuggerPanel = await debuggerPanelPromise;
 
   is(debuggerPanel, toolbox.getPanel("jsdebugger"),
       "The debugger panel from getPanelWhenReady before loading is the actual panel");
--- a/devtools/client/framework/test/browser_toolbox_highlight.js
+++ b/devtools/client/framework/test/browser_toolbox_highlight.js
@@ -12,17 +12,17 @@ var toolbox = null;
 function test() {
   (async function() {
     const URL = "data:text/plain;charset=UTF-8,Nothing to see here, move along";
 
     const TOOL_ID_1 = "jsdebugger";
     const TOOL_ID_2 = "webconsole";
     await addTab(URL);
 
-    const target = TargetFactory.forTab(gBrowser.selectedTab);
+    const target = await TargetFactory.forTab(gBrowser.selectedTab);
     toolbox = await gDevTools.showToolbox(target, TOOL_ID_1, Toolbox.HostType.BOTTOM);
 
     // select tool 2
     await toolbox.selectTool(TOOL_ID_2);
     // and highlight the first one
     await highlightTab(TOOL_ID_1);
     // to see if it has the proper class.
     await checkHighlighted(TOOL_ID_1);
--- a/devtools/client/framework/test/browser_toolbox_hosts.js
+++ b/devtools/client/framework/test/browser_toolbox_hosts.js
@@ -9,17 +9,17 @@ var {Toolbox} = require("devtools/client
 var {LEFT, RIGHT, BOTTOM, WINDOW} = Toolbox.HostType;
 var toolbox, target;
 
 const URL = "data:text/html;charset=utf8,test for opening toolbox in different hosts";
 
 add_task(async function runTest() {
   info("Create a test tab and open the toolbox");
   const tab = await addTab(URL);
-  target = TargetFactory.forTab(tab);
+  target = await TargetFactory.forTab(tab);
   toolbox = await gDevTools.showToolbox(target, "webconsole");
 
   await testBottomHost();
   await testLeftHost();
   await testRightHost();
   await testWindowHost();
   await testToolSelect();
   await testDestroy();
@@ -90,17 +90,17 @@ async function testWindowHost() {
 
 async function testToolSelect() {
   // make sure we can load a tool after switching hosts
   await toolbox.selectTool("inspector");
 }
 
 async function testDestroy() {
   await toolbox.destroy();
-  target = TargetFactory.forTab(gBrowser.selectedTab);
+  target = await TargetFactory.forTab(gBrowser.selectedTab);
   toolbox = await gDevTools.showToolbox(target);
 }
 
 function testRememberHost() {
   // last host was the window - make sure it's the same when re-opening
   is(toolbox.hostType, WINDOW, "host remembered");
 
   const win = Services.wm.getMostRecentWindow("devtools:toolbox");
--- a/devtools/client/framework/test/browser_toolbox_hosts_size.js
+++ b/devtools/client/framework/test/browser_toolbox_hosts_size.js
@@ -14,17 +14,18 @@ add_task(async function() {
   // Set size prefs to make the hosts way too big, so that the size has
   // to be clamped to fit into the browser window.
   Services.prefs.setIntPref("devtools.toolbox.footer.height", 10000);
   Services.prefs.setIntPref("devtools.toolbox.sidebar.width", 10000);
 
   const tab = await addTab(URL);
   const nbox = gBrowser.getNotificationBox();
   const {clientHeight: nboxHeight, clientWidth: nboxWidth} = nbox;
-  const toolbox = await gDevTools.showToolbox(TargetFactory.forTab(tab));
+  const target = await TargetFactory.forTab(tab);
+  const toolbox = await gDevTools.showToolbox(target);
 
   is(nbox.clientHeight, nboxHeight, "Opening the toolbox hasn't changed the height of the nbox");
   is(nbox.clientWidth, nboxWidth, "Opening the toolbox hasn't changed the width of the nbox");
 
   let iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-bottom-iframe");
   is(iframe.clientHeight, nboxHeight - 25, "The iframe fits within the available space");
 
   await toolbox.switchHost(Toolbox.HostType.RIGHT);
@@ -39,17 +40,18 @@ add_task(async function() {
   // Set size prefs to something reasonable, so we can check to make sure
   // they are being set properly.
   Services.prefs.setIntPref("devtools.toolbox.footer.height", 100);
   Services.prefs.setIntPref("devtools.toolbox.sidebar.width", 100);
 
   const tab = await addTab(URL);
   const nbox = gBrowser.getNotificationBox();
   const {clientHeight: nboxHeight, clientWidth: nboxWidth} = nbox;
-  const toolbox = await gDevTools.showToolbox(TargetFactory.forTab(tab));
+  const target = await TargetFactory.forTab(tab);
+  const toolbox = await gDevTools.showToolbox(target);
 
   is(nbox.clientHeight, nboxHeight, "Opening the toolbox hasn't changed the height of the nbox");
   is(nbox.clientWidth, nboxWidth, "Opening the toolbox hasn't changed the width of the nbox");
 
   let iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-bottom-iframe");
   is(iframe.clientHeight, 100, "The iframe is resized properly");
 
   await toolbox.switchHost(Toolbox.HostType.RIGHT);
--- a/devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
+++ b/devtools/client/framework/test/browser_toolbox_hosts_telemetry.js
@@ -10,17 +10,17 @@ const {LEFT, RIGHT, BOTTOM, WINDOW} = To
 
 const URL = "data:text/html;charset=utf8,browser_toolbox_hosts_telemetry.js";
 
 add_task(async function() {
   startTelemetry();
 
   info("Create a test tab and open the toolbox");
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
 
   await changeToolboxHost(toolbox);
   await checkResults();
 });
 
 async function changeToolboxHost(toolbox) {
   info("Switch toolbox host");
--- a/devtools/client/framework/test/browser_toolbox_options.js
+++ b/devtools/client/framework/test/browser_toolbox_options.js
@@ -13,17 +13,17 @@ const {LocalizationHelper} = require("de
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 const {PrefObserver} = require("devtools/client/shared/prefs");
 
 add_task(async function() {
   const URL = "data:text/html;charset=utf8,test for dynamically registering " +
               "and unregistering tools";
   registerNewTool();
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   toolbox = await gDevTools.showToolbox(target);
 
   doc = toolbox.doc;
   await registerNewPerToolboxTool();
   await testSelectTool();
   await testOptionsShortcut();
   await testOptions();
   await testToggleTools();
--- a/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
@@ -10,33 +10,33 @@ let TEST_URL = "data:text/html;charset=u
 
 // The frames button is only shown if the page has at least one iframe so we
 // need to add one to the test page.
 TEST_URL += "<iframe src=\"data:text/plain,iframe\"></iframe>";
 
 var doc = null, toolbox = null, panelWin = null, modifiedPrefs = [];
 
 function test() {
-  addTab(TEST_URL).then(tab => {
-    const target = TargetFactory.forTab(tab);
+  addTab(TEST_URL).then(async (tab) => {
+    const target = await TargetFactory.forTab(tab);
     gDevTools.showToolbox(target)
       .then(testSelectTool)
       .then(testToggleToolboxButtons)
       .then(testPrefsAreRespectedWhenReopeningToolbox)
       .then(cleanup, errorHandler);
   });
 }
 
-function testPrefsAreRespectedWhenReopeningToolbox() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+async function testPrefsAreRespectedWhenReopeningToolbox() {
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
 
   return new Promise(resolve => {
     info("Closing toolbox to test after reopening");
-    gDevTools.closeToolbox(target).then(() => {
-      const tabTarget = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.closeToolbox(target).then(async () => {
+      const tabTarget = await TargetFactory.forTab(gBrowser.selectedTab);
       gDevTools.showToolbox(tabTarget)
         .then(testSelectTool)
         .then(() => {
           info("Toolbox has been reopened.  Checking UI state.");
           testPreferenceAndUIStateIsConsistent();
           resolve();
         });
     });
--- a/devtools/client/framework/test/browser_toolbox_options_disable_cache-02.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_cache-02.js
@@ -31,17 +31,17 @@ add_task(async function() {
   await setDisableCacheCheckboxChecked(tabs[0], true);
 
   // Open toolbox in tab 2 and ensure the cache is then disabled.
   tabs[2].toolbox = await gDevTools.showToolbox(tabs[2].target, "options");
   await checkCacheEnabled(tabs[2], false);
 
   // Close toolbox in tab 2 and ensure the cache is enabled again
   await tabs[2].toolbox.destroy();
-  tabs[2].target = TargetFactory.forTab(tabs[2].tab);
+  tabs[2].target = await TargetFactory.forTab(tabs[2].tab);
   await checkCacheEnabled(tabs[2], true);
 
   // Open toolbox in tab 2 and ensure the cache is then disabled.
   tabs[2].toolbox = await gDevTools.showToolbox(tabs[2].target, "options");
   await checkCacheEnabled(tabs[2], false);
 
   // Check the checkbox in tab 2 and ensure cache is enabled for all tabs.
   await setDisableCacheCheckboxChecked(tabs[2], false);
--- a/devtools/client/framework/test/browser_toolbox_options_disable_js.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_js.js
@@ -3,18 +3,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that disabling JavaScript for a tab works as it should.
 
 const TEST_URI = URL_ROOT + "browser_toolbox_options_disable_js.html";
 
 function test() {
-  addTab(TEST_URI).then(tab => {
-    const target = TargetFactory.forTab(tab);
+  addTab(TEST_URI).then(async (tab) => {
+    const target = await TargetFactory.forTab(tab);
     gDevTools.showToolbox(target).then(testSelectTool);
   });
 }
 
 function testSelectTool(toolbox) {
   toolbox.once("options-selected", () => testToggleJS(toolbox));
   toolbox.selectTool("options");
 }
--- a/devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
+++ b/devtools/client/framework/test/browser_toolbox_options_enable_serviceworkers_testing.js
@@ -24,18 +24,18 @@ function test() {
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", false]
   ]}, init);
 }
 
 function init() {
-  addTab(TEST_URI).then(tab => {
-    const target = TargetFactory.forTab(tab);
+  addTab(TEST_URI).then(async tab => {
+    const target = await TargetFactory.forTab(tab);
     const linkedBrowser = tab.linkedBrowser;
 
     loadFrameScriptUtils(linkedBrowser);
     linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
 
     gDevTools.showToolbox(target).then(testSelectTool);
   });
 }
--- a/devtools/client/framework/test/browser_toolbox_options_frames_button.js
+++ b/devtools/client/framework/test/browser_toolbox_options_frames_button.js
@@ -11,17 +11,17 @@ const TEST_URL = "data:text/html;charset
 const TEST_URL_FRAMES = TEST_URL + "<iframe src=\"data:text/plain,iframe\"></iframe>";
 const FRAME_BUTTON_PREF = "devtools.command-button-frames.enabled";
 
 add_task(async function() {
   // Hide the button by default.
   await pushPref(FRAME_BUTTON_PREF, false);
 
   const tab = await addTab(TEST_URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   info("Open the toolbox on the Options panel");
   const toolbox = await gDevTools.showToolbox(target, "options");
   const doc = toolbox.doc;
 
   const optionsPanel = toolbox.getCurrentPanel();
 
   let framesButton = doc.getElementById("command-button-frames");
--- a/devtools/client/framework/test/browser_toolbox_options_multiple_tabs.js
+++ b/devtools/client/framework/test/browser_toolbox_options_multiple_tabs.js
@@ -13,17 +13,17 @@ add_task(async function() {
   tab2 = await openToolboxOptionsInNewTab();
 
   await testToggleTools();
   await cleanup();
 });
 
 async function openToolboxOptionsInNewTab() {
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target);
   const doc = toolbox.doc;
   const panel = await toolbox.selectTool("options");
   const { id } = panel.panelDoc.querySelector(
     "#default-tools-box input[type=checkbox]:not([data-unsupported]):not([checked])");
 
   return {
     tab,
--- a/devtools/client/framework/test/browser_toolbox_raise.js
+++ b/devtools/client/framework/test/browser_toolbox_raise.js
@@ -5,19 +5,19 @@
 
 const TEST_URL = "data:text/html,test for opening toolbox in different hosts";
 
 var {Toolbox} = require("devtools/client/framework/toolbox");
 
 var toolbox, tab1, tab2;
 
 function test() {
-  addTab(TEST_URL).then(tab => {
+  addTab(TEST_URL).then(async (tab) => {
     tab2 = BrowserTestUtils.addTab(gBrowser);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
     gDevTools.showToolbox(target)
              .then(testBottomHost, console.error)
              .catch(console.error);
   });
 }
 
 function testBottomHost(aToolbox) {
   toolbox = aToolbox;
--- a/devtools/client/framework/test/browser_toolbox_ready.js
+++ b/devtools/client/framework/test/browser_toolbox_ready.js
@@ -2,17 +2,17 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_URL = "data:text/html,test for toolbox being ready";
 
 add_task(async function() {
   const tab = await addTab(TEST_URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
   ok(toolbox.isReady, "toolbox isReady is set");
   ok(toolbox.threadClient, "toolbox has a thread client");
 
   const toolbox2 = await gDevTools.showToolbox(toolbox.target, toolbox.toolId);
   is(toolbox2, toolbox, "same toolbox");
 
--- a/devtools/client/framework/test/browser_toolbox_selected_tool_unavailable.js
+++ b/devtools/client/framework/test/browser_toolbox_selected_tool_unavailable.js
@@ -23,26 +23,26 @@ const testToolDefinition = {
         panelDoc: iframeWindow.document
     };
   }
 };
 
 add_task(async function() {
   gDevTools.registerTool(testToolDefinition);
   let tab = await addTab("about:blank");
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
 
   let toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
   is(toolbox.currentToolId, "testTool", "test-tool was selected");
   await gDevTools.closeToolbox(target);
 
   // Make the previously selected tool unavailable.
   testToolDefinition.isTargetSupported = () => false;
 
-  target = TargetFactory.forTab(tab);
+  target = await TargetFactory.forTab(tab);
   toolbox = await gDevTools.showToolbox(target);
   is(toolbox.currentToolId, "webconsole", "web console was selected");
 
   await gDevTools.closeToolbox(target);
   gDevTools.unregisterTool(testToolDefinition.id);
   tab = toolbox = target = null;
   gBrowser.removeCurrentTab();
 });
--- a/devtools/client/framework/test/browser_toolbox_sidebar.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar.js
@@ -32,18 +32,18 @@ function test() {
           });
         });
       });
     },
   };
 
   gDevTools.registerTool(toolDefinition);
 
-  addTab("about:blank").then(function(aTab) {
-    const target = TargetFactory.forTab(aTab);
+  addTab("about:blank").then(async function(aTab) {
+    const target = await TargetFactory.forTab(aTab);
     gDevTools.showToolbox(target, toolDefinition.id).then(function(toolbox) {
       const panel = toolbox.getPanel(toolDefinition.id);
       panel.toolbox = toolbox;
       ok(true, "Tool open");
 
       const tabbox = panel.panelDoc.getElementById("sidebar");
       panel.sidebar = new ToolSidebar(tabbox, panel, "testbug865688", true);
 
--- a/devtools/client/framework/test/browser_toolbox_sidebar_events.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar_events.js
@@ -28,18 +28,18 @@ function test() {
           });
         });
       });
     },
   };
 
   gDevTools.registerTool(toolDefinition);
 
-  addTab("about:blank").then(function(aTab) {
-    const target = TargetFactory.forTab(aTab);
+  addTab("about:blank").then(async function(aTab) {
+    const target = await TargetFactory.forTab(aTab);
     gDevTools.showToolbox(target, toolDefinition.id).then(function(toolbox) {
       const panel = toolbox.getPanel(toolDefinition.id);
       ok(true, "Tool open");
 
       panel.once("sidebar-created", function() {
         collectedEvents.push("sidebar-created");
       });
 
--- a/devtools/client/framework/test/browser_toolbox_sidebar_existing_tabs.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar_existing_tabs.js
@@ -23,17 +23,17 @@ const testToolDefinition = {
       panelDoc: iframeWindow.document,
     });
   }
 };
 
 add_task(async function() {
   const tab = await addTab("about:blank");
 
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   gDevTools.registerTool(testToolDefinition);
   const toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
 
   const toolPanel = toolbox.getPanel(testToolDefinition.id);
   const tabbox = toolPanel.panelDoc.getElementById("sidebar");
 
   info("Creating the sidebar widget");
--- a/devtools/client/framework/test/browser_toolbox_sidebar_overflow_menu.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar_overflow_menu.js
@@ -23,17 +23,17 @@ const testToolDefinition = {
       destroy: () => {},
       panelDoc: iframeWindow.document,
     };
   }
 };
 
 add_task(async function() {
   const tab = await addTab("about:blank");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   gDevTools.registerTool(testToolDefinition);
   const toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
 
   const toolPanel = toolbox.getPanel(testToolDefinition.id);
   const tabbox = toolPanel.panelDoc.getElementById("sidebar");
 
   info("Creating the sidebar widget");
--- a/devtools/client/framework/test/browser_toolbox_split_console.js
+++ b/devtools/client/framework/test/browser_toolbox_split_console.js
@@ -11,17 +11,17 @@
 
 let gToolbox = null;
 let panelWin = null;
 
 const URL = "data:text/html;charset=utf8,test split console key delegation";
 
 add_task(async function() {
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   gToolbox = await gDevTools.showToolbox(target, "jsdebugger");
   panelWin = gToolbox.getPanel("jsdebugger").panelWin;
 
   await gToolbox.openSplitConsole();
   await testIsSplitConsoleFocused();
   await testUseKeyWithSplitConsole();
   await testUseKeyWithSplitConsoleWrongTool();
 
--- a/devtools/client/framework/test/browser_toolbox_tabsswitch_shortcuts.js
+++ b/devtools/client/framework/test/browser_toolbox_tabsswitch_shortcuts.js
@@ -9,17 +9,17 @@ requestLongerTimeout(2);
 
 var {Toolbox} = require("devtools/client/framework/toolbox");
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 
 add_task(async function() {
   const tab = await addTab("about:blank");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   const toolIDs = gDevTools.getToolDefinitionArray()
                          .filter(
                            def =>
                              def.isTargetSupported(target) &&
                              def.id !== "options"
                          )
--- a/devtools/client/framework/test/browser_toolbox_telemetry_activate_splitconsole.js
+++ b/devtools/client/framework/test/browser_toolbox_telemetry_activate_splitconsole.js
@@ -54,17 +54,17 @@ add_task(async function() {
   // Let's reset the counts.
   Services.telemetry.clearEvents();
 
   // Ensure no events have been logged
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   ok(!snapshot.parent, "No events have been logged for the main process");
 
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
 
   await toolbox.openSplitConsole();
   await toolbox.closeSplitConsole();
   await toolbox.openSplitConsole();
   await toolbox.closeSplitConsole();
 
   await checkResults();
--- a/devtools/client/framework/test/browser_toolbox_telemetry_close.js
+++ b/devtools/client/framework/test/browser_toolbox_telemetry_close.js
@@ -44,17 +44,17 @@ add_task(async function() {
   await openAndCloseToolbox("webconsole", RIGHT);
   await openAndCloseToolbox("webconsole", BOTTOM);
 
   checkResults();
 });
 
 async function openAndCloseToolbox(toolId, host) {
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, toolId);
 
   await toolbox.switchHost(host);
   await toolbox.destroy();
 }
 
 function checkResults() {
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
--- a/devtools/client/framework/test/browser_toolbox_telemetry_enter.js
+++ b/devtools/client/framework/test/browser_toolbox_telemetry_enter.js
@@ -91,17 +91,17 @@ add_task(async function() {
   // Let's reset the counts.
   Services.telemetry.clearEvents();
 
   // Ensure no events have been logged
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   ok(!snapshot.parent, "No events have been logged for the main process");
 
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   // Set up some cached messages for the web console.
   await ContentTask.spawn(tab.linkedBrowser, {}, () => {
     content.console.log("test 1");
     content.console.log("test 2");
     content.console.log("test 3");
     content.console.log("test 4");
     content.console.log("test 5");
--- a/devtools/client/framework/test/browser_toolbox_telemetry_exit.js
+++ b/devtools/client/framework/test/browser_toolbox_telemetry_exit.js
@@ -78,17 +78,17 @@ add_task(async function() {
   // Let's reset the counts.
   Services.telemetry.clearEvents();
 
   // Ensure no events have been logged
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   ok(!snapshot.parent, "No events have been logged for the main process");
 
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   // Open the toolbox
   await gDevTools.showToolbox(target, "inspector");
 
   // Switch between a few tools
   await gDevTools.showToolbox(target, "jsdebugger");
   await gDevTools.showToolbox(target, "styleeditor");
   await gDevTools.showToolbox(target, "netmonitor");
--- a/devtools/client/framework/test/browser_toolbox_theme_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_theme_registration.js
@@ -9,17 +9,17 @@
 const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/framework/test/";
 const TEST_THEME_NAME = "test-theme";
 const LIGHT_THEME_NAME = "light";
 
 var toolbox;
 
 add_task(async function themeRegistration() {
   const tab = await addTab("data:text/html,test");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   toolbox = await gDevTools.showToolbox(target, "options");
 
   const themeId = await new Promise(resolve => {
     gDevTools.once("theme-registered", registeredThemeId => {
       resolve(registeredThemeId);
     });
 
     gDevTools.registerTheme({
--- a/devtools/client/framework/test/browser_toolbox_toggle.js
+++ b/devtools/client/framework/test/browser_toolbox_toggle.js
@@ -29,26 +29,27 @@ add_task(async function() {
 
   // Test with F12 ; no modifiers
   info("Test toggle using F12");
   await testToggle("VK_F12", {});
 });
 
 async function testToggle(key, modifiers) {
   const tab = await addTab(URL + " ; key : '" + key + "'");
-  await gDevTools.showToolbox(TargetFactory.forTab(tab));
+  const target = await TargetFactory.forTab(tab);
+  await gDevTools.showToolbox(target);
 
   await testToggleDockedToolbox(tab, key, modifiers);
   await testToggleDetachedToolbox(tab, key, modifiers);
 
   await cleanup();
 }
 
 async function testToggleDockedToolbox(tab, key, modifiers) {
-  const toolbox = getToolboxForTab(tab);
+  const toolbox = await getToolboxForTab(tab);
 
   isnot(toolbox.hostType, Toolbox.HostType.WINDOW,
     "Toolbox is docked in the main window");
 
   info("verify docked toolbox is destroyed when using toggle key");
   const onToolboxDestroyed = gDevTools.once("toolbox-destroyed");
   EventUtils.synthesizeKey(key, modifiers);
   await onToolboxDestroyed;
@@ -57,17 +58,17 @@ async function testToggleDockedToolbox(t
   info("verify new toolbox is created when using toggle key");
   const onToolboxReady = gDevTools.once("toolbox-ready");
   EventUtils.synthesizeKey(key, modifiers);
   await onToolboxReady;
   ok(true, "Toolbox is created by using when toggle key");
 }
 
 async function testToggleDetachedToolbox(tab, key, modifiers) {
-  const toolbox = getToolboxForTab(tab);
+  const toolbox = await getToolboxForTab(tab);
 
   info("change the toolbox hostType to WINDOW");
 
   await toolbox.switchHost(Toolbox.HostType.WINDOW);
   is(toolbox.hostType, Toolbox.HostType.WINDOW,
     "Toolbox opened on separate window");
 
   info("Wait for focus on the toolbox window");
@@ -92,16 +93,17 @@ async function testToggleDetachedToolbox
     "own window");
 
   const onToolboxDestroyed = gDevTools.once("toolbox-destroyed");
   EventUtils.synthesizeKey(key, modifiers, toolboxWindow);
   await onToolboxDestroyed;
   ok(true, "Toolbox destroyed");
 }
 
-function getToolboxForTab(tab) {
-  return gDevTools.getToolbox(TargetFactory.forTab(tab));
+async function getToolboxForTab(tab) {
+  const target = await TargetFactory.forTab(tab);
+  return gDevTools.getToolbox(target);
 }
 
 function cleanup() {
   Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
   gBrowser.removeCurrentTab();
 }
--- a/devtools/client/framework/test/browser_toolbox_tool_ready.js
+++ b/devtools/client/framework/test/browser_toolbox_tool_ready.js
@@ -29,16 +29,16 @@ function performChecks(target) {
     await toolbox.destroy();
   })();
 }
 
 function test() {
   (async function() {
     toggleAllTools(true);
     const tab = await addTab("about:blank");
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
     await target.makeRemote();
     await performChecks(target);
     gBrowser.removeCurrentTab();
     toggleAllTools(false);
     finish();
   })();
 }
--- a/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
@@ -13,18 +13,18 @@ const TEST_URL = `data:text/html,<!DOCTY
     </body>
   </html>`;
 
 const TOOL_ID = "test-toolbox-tool";
 var toolbox;
 var target;
 
 function test() {
-  addTab(TEST_URL).then(tab => {
-    target = TargetFactory.forTab(tab);
+  addTab(TEST_URL).then(async (tab) => {
+    target = await TargetFactory.forTab(tab);
 
     gDevTools.showToolbox(target)
       .then(toolboxRegister)
       .then(testToolRegistered);
   });
 }
 
 var resolveToolInstanceBuild;
--- a/devtools/client/framework/test/browser_toolbox_window_reload_target.js
+++ b/devtools/client/framework/test/browser_toolbox_window_reload_target.js
@@ -12,18 +12,18 @@ const TEST_URL = "data:text/html;charset
 var {Toolbox} = require("devtools/client/framework/toolbox");
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 
 var target, toolbox, description, reloadsSent, toolIDs;
 
 function test() {
-  addTab(TEST_URL).then(() => {
-    target = TargetFactory.forTab(gBrowser.selectedTab);
+  addTab(TEST_URL).then(async () => {
+    target = await TargetFactory.forTab(gBrowser.selectedTab);
 
     target.makeRemote().then(() => {
       toolIDs = gDevTools.getToolDefinitionArray()
                   .filter(def => def.isTargetSupported(target))
                   .map(def => def.id);
       gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.BOTTOM)
                .then(startReloadTest);
     });
--- a/devtools/client/framework/test/browser_toolbox_window_shortcuts.js
+++ b/devtools/client/framework/test/browser_toolbox_window_shortcuts.js
@@ -6,18 +6,18 @@
 "use strict";
 
 var Startup = Cc["@mozilla.org/devtools/startup-clh;1"].getService(Ci.nsISupports)
   .wrappedJSObject;
 var {Toolbox} = require("devtools/client/framework/toolbox");
 
 var toolbox, toolIDs, toolShortcuts = [], idIndex, modifiedPrefs = [];
 
-function test() {
-  addTab("about:blank").then(function() {
+async function test() {
+  addTab("about:blank").then(async function() {
     toolIDs = [];
     for (const [id, definition] of gDevTools._tools) {
       const shortcut = Startup.KeyShortcuts.filter(s => s.toolId == id)[0];
       if (!shortcut) {
         continue;
       }
       toolIDs.push(id);
       toolShortcuts.push(shortcut);
@@ -27,17 +27,17 @@ function test() {
       if (pref) {
         const prefValue = Services.prefs.getBoolPref(pref, false);
         if (!prefValue) {
           modifiedPrefs.push(pref);
           Services.prefs.setBoolPref(pref, true);
         }
       }
     }
-    const target = TargetFactory.forTab(gBrowser.selectedTab);
+    const target = await TargetFactory.forTab(gBrowser.selectedTab);
     idIndex = 0;
     gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.WINDOW)
              .then(testShortcuts);
   });
 }
 
 function testShortcuts(aToolbox, aIndex) {
   if (aIndex === undefined) {
--- a/devtools/client/framework/test/browser_toolbox_window_title_changes.js
+++ b/devtools/client/framework/test/browser_toolbox_window_title_changes.js
@@ -16,18 +16,18 @@ function test() {
   const TOOL_ID_2 = "jsdebugger";
 
   const NAME_1 = "";
   const NAME_2 = "";
   const NAME_3 = "Toolbox test for title update";
 
   let toolbox;
 
-  addTab(URL_1).then(function() {
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
+  addTab(URL_1).then(async function() {
+    let target = await TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.showToolbox(target, null, Toolbox.HostType.BOTTOM)
       .then(function(aToolbox) {
         toolbox = aToolbox;
       })
       .then(() => toolbox.selectTool(TOOL_ID_1))
 
     // undock toolbox and check title
       .then(() => {
@@ -64,19 +64,19 @@ function test() {
 
     // destroy toolbox, create new one hosted in a window (with a
     // different tool id), and check title
       .then(function() {
         // Give the tools a chance to handle the navigation event before
         // destroying the toolbox.
         executeSoon(function() {
           toolbox.destroy()
-            .then(function() {
+            .then(async function() {
               // After destroying the toolbox, a fresh target is required.
-              target = TargetFactory.forTab(gBrowser.selectedTab);
+              target = await TargetFactory.forTab(gBrowser.selectedTab);
               return gDevTools.showToolbox(target, null, Toolbox.HostType.WINDOW);
             })
             .then(function(aToolbox) {
               toolbox = aToolbox;
             })
             .then(() => {
               const onTitleChanged = waitForTitleChange(toolbox);
               toolbox.selectTool(TOOL_ID_1);
--- a/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js
+++ b/devtools/client/framework/test/browser_toolbox_window_title_frame_select.js
@@ -16,17 +16,17 @@ const URL = URL_ROOT + "browser_toolbox_
 const IFRAME_URL = URL_ROOT + "browser_toolbox_window_title_changes_page.html";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 
 add_task(async function() {
   Services.prefs.setBoolPref("devtools.command-button-frames.enabled", true);
 
   await addTab(URL);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   let toolbox = await gDevTools.showToolbox(target, null,
     Toolbox.HostType.BOTTOM);
 
   await toolbox.switchHost(Toolbox.HostType.WINDOW);
   // Wait for title change event *after* switch host, in order to listen
   // for the event on the WINDOW host window, which only exists after switchHost
   await waitForTitleChange(toolbox);
 
--- a/devtools/client/framework/test/browser_toolbox_zoom.js
+++ b/devtools/client/framework/test/browser_toolbox_zoom.js
@@ -10,17 +10,17 @@ const L10N = new LocalizationHelper("dev
 add_task(async function() {
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("devtools.toolbox.zoomValue");
   });
 
   // This test assume that zoom value will be default value. i.e. x1.0.
   Services.prefs.setCharPref("devtools.toolbox.zoomValue", "1.0");
   await addTab("about:blank");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target,
                                             "styleeditor",
                                             Toolbox.HostType.BOTTOM);
 
   info("testing zoom keys");
 
   testZoomLevel("In", 2, 1.2, toolbox);
   testZoomLevel("Out", 3, 0.9, toolbox);
--- a/devtools/client/framework/test/browser_toolbox_zoom_popup.js
+++ b/devtools/client/framework/test/browser_toolbox_zoom_popup.js
@@ -15,17 +15,17 @@ add_task(async function() {
   registerCleanupFunction(async function() {
     Services.prefs.clearUserPref("devtools.toolbox.zoomValue");
   });
   const zoom = 1.4;
   Services.prefs.setCharPref("devtools.toolbox.zoomValue", zoom.toString(10));
 
   info("Load iframe page for checking the frame menu with x1.4 zoom.");
   await addTab(TEST_URL);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target,
                                             "inspector",
                                             Toolbox.HostType.WINDOW);
   const inspector = toolbox.getCurrentPanel();
   const hostWindow = toolbox.win.parent;
   const originWidth = hostWindow.outerWidth;
   const originHeight = hostWindow.outerHeight;
   const windowUtils = toolbox.win.windowUtils;
--- a/devtools/client/framework/test/helper_disable_cache.js
+++ b/devtools/client/framework/test/helper_disable_cache.js
@@ -32,17 +32,17 @@ var tabs = [
   {
     title: "Tab 3",
     desc: "No toolbox",
     startToolbox: false
   }];
 
 async function initTab(tabX, startToolbox) {
   tabX.tab = await addTab(TEST_URI);
-  tabX.target = TargetFactory.forTab(tabX.tab);
+  tabX.target = await TargetFactory.forTab(tabX.tab);
 
   if (startToolbox) {
     tabX.toolbox = await gDevTools.showToolbox(tabX.target, "options");
   }
 }
 
 async function checkCacheStateForAllTabs(states) {
   for (let i = 0; i < tabs.length; i++) {
--- a/devtools/client/inspector/animation/test/head.js
+++ b/devtools/client/inspector/animation/test/head.js
@@ -38,17 +38,17 @@ const openAnimationInspector = async fun
 };
 
 /**
  * Close the toolbox.
  *
  * @return {Promise} that resolves when the toolbox has closed.
  */
 const closeAnimationInspector = async function() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   return gDevTools.closeToolbox(target);
 };
 
 /**
  * Some animation features are not enabled by default in release/beta channels
  * yet including:
  *   * parts of the Web Animations API (Bug 1264101), and
  *   * the frames() timing function (Bug 1379582).
--- a/devtools/client/inspector/rules/test/browser_rules_authored_color.js
+++ b/devtools/client/inspector/rules/test/browser_rules_authored_color.js
@@ -56,12 +56,12 @@ add_task(async function() {
     focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
     await onHidden;
     await onRuleViewChanged;
 
     is(getRuleViewPropertyValue(view, "element", "color"), color.result,
        "changing the color preserved the unit for " + color.name);
   }
 
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   await gDevTools.closeToolbox(target);
   gBrowser.removeCurrentTab();
 });
--- a/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
@@ -27,17 +27,17 @@ add_task(async function() {
 
     const tab = await addTab("data:text/html;charset=utf-8," +
                            encodeURIComponent(TEST_URI));
     const {inspector, view} = await openRuleView();
 
     await selectNode("#testid", inspector);
     await basicTest(view, name, result);
 
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
     await gDevTools.closeToolbox(target);
     gBrowser.removeCurrentTab();
   }
 });
 
 async function basicTest(view, name, result) {
   const cPicker = view.tooltips.getTooltip("colorPicker");
   const swatch = getRuleViewProperty(view, "#testid", "color").valueSpan
--- a/devtools/client/inspector/rules/test/browser_rules_flexbox-highlighter-on-reload.js
+++ b/devtools/client/inspector/rules/test/browser_rules_flexbox-highlighter-on-reload.js
@@ -17,17 +17,17 @@ const TEST_URI = `
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
 
   info("Check that the flexbox highlighter can be displayed.");
   await checkFlexboxHighlighter();
 
   info("Close the toolbox before reloading the tab.");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
 
   await refreshTab();
 
   info("Check that the flexbox highlighter can be displayed after reloading the page.");
   await checkFlexboxHighlighter();
 });
 
--- a/devtools/client/inspector/rules/test/browser_rules_grid-highlighter-on-reload.js
+++ b/devtools/client/inspector/rules/test/browser_rules_grid-highlighter-on-reload.js
@@ -22,17 +22,17 @@ const TEST_URI = `
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
 
   info("Check that the grid highlighter can be displayed");
   await checkGridHighlighter();
 
   info("Close the toolbox before reloading the tab");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
 
   await refreshTab();
 
   info("Check that the grid highlighter can be displayed after reloading the page");
   await checkGridHighlighter();
 });
 
--- a/devtools/client/inspector/test/browser_inspector_destroy-before-ready.js
+++ b/devtools/client/inspector/test/browser_inspector_destroy-before-ready.js
@@ -11,16 +11,16 @@ add_task(async function() {
   // At least one assertion is needed to avoid failing the test, but really,
   // what we're interested in is just having the test pass when switching to the
   // inspector.
   ok(true);
 
   await addTab("data:text/html;charset=utf-8,test inspector destroy");
 
   info("Open the toolbox on the debugger panel");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "jsdebugger");
 
   info("Switch to the inspector panel and immediately end the test");
   const onInspectorSelected = toolbox.once("inspector-selected");
   toolbox.selectTool("inspector");
   await onInspectorSelected;
 });
--- a/devtools/client/inspector/test/browser_inspector_initialization.js
+++ b/devtools/client/inspector/test/browser_inspector_initialization.js
@@ -30,17 +30,17 @@ add_task(async function() {
   const testActor = await getTestActorWithoutToolbox(tab);
 
   await testToolboxInitialization(testActor, tab);
   await testContextMenuInitialization(testActor);
   await testContextMenuInspectorAlreadyOpen(testActor);
 });
 
 async function testToolboxInitialization(testActor, tab) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   info("Opening inspector with gDevTools.");
   const toolbox = await gDevTools.showToolbox(target, "inspector");
   const inspector = toolbox.getCurrentPanel();
 
   ok(true, "Inspector started, and notification received.");
   ok(inspector, "Inspector instance is accessible.");
   ok(inspector.isReady, "Inspector instance is ready.");
@@ -70,40 +70,44 @@ async function testContextMenuInitializa
   info("Checking inspector state.");
   await testMarkupView("#salutation");
   await testBreadcrumbs("#salutation");
 }
 
 async function testContextMenuInspectorAlreadyOpen(testActor) {
   info("Changing node by clicking on 'Inspect Element' context menu item");
 
-  const inspector = getActiveInspector();
+  const inspector = await getActiveInspector();
   ok(inspector, "Inspector is active");
 
   await clickOnInspectMenuItem(testActor, "#closing");
 
   ok(true, "Inspector was updated when 'Inspect Element' was clicked.");
   await testMarkupView("#closing", inspector);
   await testBreadcrumbs("#closing", inspector);
 }
 
 async function testMarkupView(selector, inspector) {
-  inspector = inspector || getActiveInspector();
+  if (!inspector) {
+    inspector = await getActiveInspector();
+  }
   const nodeFront = await getNodeFront(selector, inspector);
   try {
     is(inspector.selection.nodeFront, nodeFront,
        "Right node is selected in the markup view");
   } catch (ex) {
     ok(false, "Got exception while resolving selected node of markup view.");
     console.error(ex);
   }
 }
 
 async function testBreadcrumbs(selector, inspector) {
-  inspector = inspector || getActiveInspector();
+  if (!inspector) {
+    inspector = await getActiveInspector();
+  }
   const nodeFront = await getNodeFront(selector, inspector);
 
   const b = inspector.breadcrumbs;
   const expectedText = b.prettyPrintNodeAsText(nodeFront);
   const button = b.container.querySelector("button[checked=true]");
   ok(button, "A crumbs is checked=true");
   is(button.getAttribute("title"), expectedText,
      "Crumb refers to the right node");
--- a/devtools/client/inspector/test/browser_inspector_inspect_node_contextmenu.js
+++ b/devtools/client/inspector/test/browser_inspector_inspect_node_contextmenu.js
@@ -39,25 +39,25 @@ add_task(async function() {
 });
 
 async function testContextMenuWithinIframe(testActor, nodeFrontGetter) {
   info("Opening inspector via 'Inspect Element' context menu item within an iframe");
   const selector = ["iframe", "#in-frame"];
   await clickOnInspectMenuItem(testActor, selector);
 
   info("Checking inspector state.");
-  const inspector = getActiveInspector();
+  const inspector = await getActiveInspector();
   const nodeFront = await nodeFrontGetter(inspector);
 
   is(inspector.selection.nodeFront, nodeFront,
      "Right node is selected in the markup view");
 }
 
 async function changeToolboxToInnerFrame() {
-  const { toolbox } = getActiveInspector();
+  const { toolbox } = await getActiveInspector();
 
   const btn = toolbox.doc.getElementById("command-button-frames");
   const panel = toolbox.doc.getElementById("command-button-frames-panel");
   btn.click();
   ok(panel, "popup panel has created.");
   await waitUntil(() => panel.classList.contains("tooltip-visible"));
 
   info("Select the iframe in the frame list.");
--- a/devtools/client/inspector/test/browser_inspector_switch-to-inspector-on-pick.js
+++ b/devtools/client/inspector/test/browser_inspector_switch-to-inspector-on-pick.js
@@ -67,19 +67,19 @@ add_task(async function() {
   await startPickerAndAssertSwitchToInspector(toolbox);
 
   info("Stoppping element picker.");
   await toolbox.highlighterUtils.stopPicker();
 
   checkResults();
 });
 
-function openToolbox(tab) {
+async function openToolbox(tab) {
   info("Opening webconsole.");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   return gDevTools.showToolbox(target, "webconsole");
 }
 
 async function startPickerAndAssertSwitchToInspector(toolbox) {
   info("Clicking element picker button.");
   const pickButton = toolbox.doc.querySelector("#command-button-pick");
   pickButton.click();
 
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -178,18 +178,18 @@ function clearCurrentNodeSelection(inspe
  *         with an object: { tab, toolbox, inspector }.
  */
 var openInspectorForURL = async function(url, hostType) {
   const tab = await addTab(url);
   const { inspector, toolbox, testActor } = await openInspector(hostType);
   return { tab, inspector, toolbox, testActor };
 };
 
-function getActiveInspector() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+async function getActiveInspector() {
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   return gDevTools.getToolbox(target).getPanel("inspector");
 }
 
 /**
  * Right click on a node in the test page and click on the inspect menu item.
  * @param {TestActor}
  * @param {String} selector The selector for the node to click on in the page.
  * @return {Promise} Resolves to the inspector when it has opened and is updated
--- a/devtools/client/memory/test/browser/head.js
+++ b/devtools/client/memory/test/browser/head.js
@@ -20,29 +20,29 @@ var { L10N } = require("devtools/client/
 
 Services.prefs.setBoolPref("devtools.memory.enabled", true);
 
 /**
  * Open the memory panel for the given tab.
  */
 this.openMemoryPanel = async function(tab) {
   info("Opening memory panel.");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "memory");
   info("Memory panel shown successfully.");
   const panel = toolbox.getCurrentPanel();
   return { tab, panel };
 };
 
 /**
  * Close the memory panel for the given tab.
  */
 this.closeMemoryPanel = async function(tab) {
   info("Closing memory panel.");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = gDevTools.getToolbox(target);
   await toolbox.destroy();
   info("Closed memory panel successfully.");
 };
 
 /**
  * Return a test function that adds a tab with the given url, opens the memory
  * panel, runs the given generator, closes the memory panel, removes the tab,
--- a/devtools/client/menus.js
+++ b/devtools/client/menus.js
@@ -96,17 +96,17 @@ exports.menuitems = [
     },
     keyId: "responsiveDesignMode",
     checkbox: true
   },
   { id: "menu_eyedropper",
     l10nKey: "eyedropper",
     async oncommand(event) {
       const window = event.target.ownerDocument.defaultView;
-      const target = TargetFactory.forTab(window.gBrowser.selectedTab);
+      const target = await TargetFactory.forTab(window.gBrowser.selectedTab);
       await target.makeRemote();
       const inspectorFront = await target.getFront("inspector");
       inspectorFront.pickColorFromPage({copyOnSelect: true, fromMenu: true});
     },
     checkbox: true
   },
   { id: "menu_scratchpad",
     l10nKey: "scratchpad",
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -284,17 +284,17 @@ async function waitForAllNetworkUpdateEv
 
 function initNetMonitor(url, enableCache) {
   info("Initializing a network monitor pane.");
 
   return (async function() {
     const tab = await addTab(url);
     info("Net tab added successfully: " + url);
 
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
     info("Target remoted.");
 
     const toolbox = await gDevTools.showToolbox(target, "netmonitor");
     info("Network monitor pane shown successfully.");
 
     const monitor = toolbox.getCurrentPanel();
--- a/devtools/client/performance/test/helpers/panel-utils.js
+++ b/devtools/client/performance/test/helpers/panel-utils.js
@@ -18,17 +18,17 @@ exports.initPanelInNewTab = async functi
 };
 
 /**
  * Initializes a toolbox panel in the specified tab.
  */
 exports.initPanelInTab = async function({ tool, tab }) {
   dump(`Initializing a ${tool} panel.\n`);
 
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   // Open a toolbox and wait for the connection to the performance actors
   // to be opened. This is necessary because of the WebConsole's
   // `profile` and `profileEnd` methods.
   const toolbox = await gDevTools.showToolbox(target, tool);
   await toolbox.initPerformance();
 
--- a/devtools/client/responsive.html/test/browser/browser_telemetry_activate_rdm.js
+++ b/devtools/client/responsive.html/test/browser/browser_telemetry_activate_rdm.js
@@ -52,17 +52,17 @@ add_task(async function() {
   // Let's reset the counts.
   Services.telemetry.clearEvents();
 
   // Ensure no events have been logged
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   ok(!snapshot.parent, "No events have been logged for the main process");
 
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   await openCloseRDM(tab);
   await gDevTools.showToolbox(target, "inspector");
   await openCloseRDM(tab);
   await checkResults();
 });
 
 async function openCloseRDM(tab) {
--- a/devtools/client/responsive.html/test/browser/browser_toolbox_swap_browsers.js
+++ b/devtools/client/responsive.html/test/browser/browser_toolbox_swap_browsers.js
@@ -20,17 +20,17 @@ function getServerConnections(browser) {
 }
 
 const checkServerConnectionCount = async function(browser, expected, msg) {
   const conns = await getServerConnections(browser);
   is(conns.length || 0, expected, "Server connection count: " + msg);
 };
 
 const checkToolbox = async function(tab, location) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
 };
 
 add_task(async function() {
   const tab = await addTab(TEST_URL);
 
   const tabsInDifferentProcesses = E10S_MULTI_ENABLED &&
     (gBrowser.tabs[0].linkedBrowser.frameLoader.childID !=
--- a/devtools/client/responsive.html/test/browser/browser_toolbox_swap_inspector.js
+++ b/devtools/client/responsive.html/test/browser/browser_toolbox_swap_inspector.js
@@ -3,17 +3,17 @@
 
 "use strict";
 
 // Verify that inspector does not reboot when opening and closing RDM.
 
 const TEST_URL = "http://example.com/";
 
 const checkToolbox = async function(tab, location) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
 };
 
 add_task(async function() {
   const tab = await addTab(TEST_URL);
 
   info("Open toolbox outside RDM");
   {
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -581,26 +581,26 @@ var Scratchpad = {
   /**
    * Reload the current page and execute the entire editor content when
    * the page finishes loading. Note that this operation should be available
    * only in the content context.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  reloadAndRun: function SP_reloadAndRun() {
+  reloadAndRun: async function SP_reloadAndRun() {
     const deferred = defer();
 
     if (this.executionContext !== SCRATCHPAD_CONTEXT_CONTENT) {
       console.error(this.strings
                     .GetStringFromName("scratchpadContext.invalid"));
       return;
     }
 
-    const target = TargetFactory.forTab(this.gBrowser.selectedTab);
+    const target = await TargetFactory.forTab(this.gBrowser.selectedTab);
     target.once("navigate", () => {
       this.run().then(results => deferred.resolve(results));
     });
     target.makeRemote().then(() => target.activeTab.reload());
 
     return deferred.promise;
   },
 
@@ -1538,18 +1538,18 @@ var Scratchpad = {
    */
   openErrorConsole: function SP_openErrorConsole() {
     HUDService.toggleBrowserConsole();
   },
 
   /**
    * Open the Web Console.
    */
-  openWebConsole: function SP_openWebConsole() {
-    const target = TargetFactory.forTab(this.gBrowser.selectedTab);
+  openWebConsole: async function SP_openWebConsole() {
+    const target = await TargetFactory.forTab(this.gBrowser.selectedTab);
     gDevTools.showToolbox(target, "webconsole");
     this.browserWindow.focus();
   },
 
   /**
    * Set the current execution context to be the active tab content window.
    */
   setContentContext: function SP_setContentContext() {
@@ -2087,18 +2087,18 @@ ScratchpadTab.prototype = {
   /**
    * Attach to this tab.
    *
    * @param object aSubject
    *        The tab or window to obtain the connection for.
    * @return Promise
    *         The promise for the TabTarget for this tab.
    */
-  _attach: function ST__attach(aSubject) {
-    const target = TargetFactory.forTab(this._tab);
+  _attach: async function ST__attach(aSubject) {
+    const target = await TargetFactory.forTab(this._tab);
     target.once("close", () => {
       if (scratchpadTargets) {
         scratchpadTargets.delete(aSubject);
       }
     });
     return target.makeRemote().then(() => target);
   },
 };
--- a/devtools/client/scratchpad/test/browser_scratchpad_close_toolbox.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_close_toolbox.js
@@ -18,17 +18,17 @@ function test() {
 async function runTests([win, sp]) {
   // Use the scratchpad before opening the toolbox.
   const source = "window.foobar = 7;";
   sp.setText(source);
   const [,, result] = await sp.display();
   is(result, 7, "Display produced the expected output.");
 
   // Now open the toolbox and close it again.
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
   ok(toolbox, "Toolbox was opened.");
   const closed = await gDevTools.closeToolbox(target);
   is(closed, true, "Toolbox was closed.");
 
   // Now see if using the scratcphad works as expected.
   sp.setText(source);
   const [,, result2] = await sp.display();
--- a/devtools/client/scratchpad/test/browser_scratchpad_menubar.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_menubar.js
@@ -23,14 +23,14 @@ add_task(async function() {
 add_task(async function() {
   // Now open the scratchpad panel after setting visibility preference.
   info("Test existence of menu bar of scratchpad panel.");
   await new Promise(resolve => {
     SpecialPowers.pushPrefEnv({"set": [["devtools.scratchpad.enabled", true]]}, resolve);
   });
 
   info("Open devtools on the Scratchpad.");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "scratchpad");
 
   const menuToolbar = toolbox.doc.getElementById("sp-menu-toolbar");
   ok(!menuToolbar, "The scratchpad panel should not have a menu bar.");
 });
--- a/devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
@@ -20,18 +20,18 @@ function test() {
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(function() {
     openScratchpad(function() {
       const sw = gScratchpadWindow;
       const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
       const {TargetFactory} = require("devtools/client/framework/target");
 
-      openScratchpad(function() {
-        const target = TargetFactory.forTab(gBrowser.selectedTab);
+      openScratchpad(async function() {
+        const target = await TargetFactory.forTab(gBrowser.selectedTab);
         gDevTools.showToolbox(target, "webconsole").then((toolbox) => {
           const hud = toolbox.getCurrentPanel().hud;
           hud.ui.clearOutput(true);
           testFocus(sw, hud);
         });
       });
     });
   });
--- a/devtools/client/shadereditor/test/head.js
+++ b/devtools/client/shadereditor/test/head.js
@@ -147,31 +147,31 @@ function reload(aTarget, aWaitForTargetE
 function initBackend(aUrl) {
   info("Initializing a shader editor front.");
 
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     const front = new WebGLFront(target.client, target.form);
     return { target, front };
   })();
 }
 
 function initShaderEditor(aUrl) {
   info("Initializing a shader editor pane.");
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     Services.prefs.setBoolPref("devtools.shadereditor.enabled", true);
     const toolbox = await gDevTools.showToolbox(target, "shadereditor");
     const panel = toolbox.getCurrentPanel();
     return { target, panel };
   })();
--- a/devtools/client/shared/link.js
+++ b/devtools/client/shared/link.js
@@ -57,17 +57,17 @@ exports.openDocLink = async function(url
 exports.openContentLink = async function(url, options = {}) {
   const top = _getTopWindow();
   if (!top) {
     return;
   }
   if (!options.triggeringPrincipal && top.gBrowser) {
     const tab = top.gBrowser.selectedTab;
     if (TargetFactory.isKnownTab(tab)) {
-      const target = TargetFactory.forTab(tab);
+      const target = await TargetFactory.forTab(tab);
       options.triggeringPrincipal = target.contentPrincipal;
     }
   }
   top.openWebLinkIn(url, "tab", options);
 };
 
 /**
  * Open a trusted |url| in a new tab using the SystemPrincipal.
--- a/devtools/client/shared/test/browser_telemetry_button_eyedropper.js
+++ b/devtools/client/shared/test/browser_telemetry_button_eyedropper.js
@@ -5,17 +5,17 @@
 
 const TEST_URI = "data:text/html;charset=utf-8," +
   "<p>browser_telemetry_button_eyedropper.js</p><div>test</div>";
 
 add_task(async function() {
   await addTab(TEST_URI);
   startTelemetry();
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
 
   info("testing the eyedropper button");
   await testButton(toolbox);
 
   await gDevTools.closeToolbox(target);
   gBrowser.removeCurrentTab();
 });
--- a/devtools/client/shared/test/browser_telemetry_button_paintflashing.js
+++ b/devtools/client/shared/test/browser_telemetry_button_paintflashing.js
@@ -12,17 +12,17 @@ const TEST_URI = "data:text/html;charset
 const TOOL_DELAY = 200;
 
 add_task(async function() {
   await addTab(TEST_URI);
   startTelemetry();
 
   await pushPref("devtools.command-button-paintflashing.enabled", true);
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
   info("inspector opened");
 
   info("testing the paintflashing button");
   await testButton(toolbox);
 
   await gDevTools.closeToolbox(target);
   gBrowser.removeCurrentTab();
--- a/devtools/client/shared/test/browser_telemetry_button_responsive.js
+++ b/devtools/client/shared/test/browser_telemetry_button_responsive.js
@@ -31,17 +31,17 @@ registerCleanupFunction(() => {
 });
 
 loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
 
 add_task(async function() {
   await addTab(TEST_URI);
   startTelemetry();
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
   info("inspector opened");
 
   info("testing the responsivedesign button");
   await testButton(toolbox);
 
   await gDevTools.closeToolbox(target);
   gBrowser.removeCurrentTab();
--- a/devtools/client/shared/test/browser_telemetry_button_scratchpad.js
+++ b/devtools/client/shared/test/browser_telemetry_button_scratchpad.js
@@ -12,17 +12,17 @@ const TEST_URI = "data:text/html;charset
 const TOOL_DELAY = 200;
 
 add_task(async function() {
   await addTab(TEST_URI);
   startTelemetry();
 
   await pushPref("devtools.command-button-scratchpad.enabled", true);
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
   info("inspector opened");
 
   const onAllWindowsOpened = trackScratchpadWindows();
 
   info("testing the scratchpad button");
   await testButton(toolbox);
   await onAllWindowsOpened;
--- a/devtools/client/shared/test/browser_telemetry_sidebar.js
+++ b/devtools/client/shared/test/browser_telemetry_sidebar.js
@@ -108,17 +108,17 @@ add_task(async function() {
 
   // Ensure no events have been logged
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
   ok(!snapshot.parent, "No events have been logged for the main process");
 
   await addTab(TEST_URI);
   startTelemetry();
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
   info("inspector opened");
 
   await testSidebar(toolbox);
   checkResults();
   checkEventTelemetry();
 
   await gDevTools.closeToolbox(target);
--- a/devtools/client/shared/test/browser_theme_switching.js
+++ b/devtools/client/shared/test/browser_theme_switching.js
@@ -1,16 +1,16 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 add_task(async function() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target);
   const doc = toolbox.doc;
   const root = doc.documentElement;
 
   const platform = root.getAttribute("platform");
   const expectedPlatform = getPlatform();
   is(platform, expectedPlatform, ":root[platform] is correct");
 
--- a/devtools/client/shared/test/head.js
+++ b/devtools/client/shared/test/head.js
@@ -124,17 +124,17 @@ async function(type = "bottom", src = CH
  * some amount of time in between.
  * @param {Number} nbOfTimes
  * @param {Number} usageTime in milliseconds
  * @param {String} toolId
  */
 async function openAndCloseToolbox(nbOfTimes, usageTime, toolId) {
   for (let i = 0; i < nbOfTimes; i++) {
     info("Opening toolbox " + (i + 1));
-    const target = TargetFactory.forTab(gBrowser.selectedTab);
+    const target = await TargetFactory.forTab(gBrowser.selectedTab);
     await gDevTools.showToolbox(target, toolId);
 
     // We use a timeout to check the toolbox's active time
     await new Promise(resolve => setTimeout(resolve, usageTime));
 
     info("Closing toolbox " + (i + 1));
     await gDevTools.closeToolbox(target);
   }
--- a/devtools/client/shared/test/shared-head.js
+++ b/devtools/client/shared/test/shared-head.js
@@ -403,17 +403,17 @@ function wait(ms) {
  * @param {String} toolId Optional. The ID of the tool to be selected.
  * @param {String} hostType Optional. The type of toolbox host to be used.
  * @return {Promise} Resolves with the toolbox, when it has been opened.
  */
 var openToolboxForTab = async function(tab, toolId, hostType) {
   info("Opening the toolbox");
 
   let toolbox;
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   // Check if the toolbox is already loaded.
   toolbox = gDevTools.getToolbox(target);
   if (toolbox) {
     if (!toolId || (toolId && toolbox.getPanel(toolId))) {
       info("Toolbox is already opened");
       return toolbox;
@@ -446,17 +446,17 @@ var openNewTabAndToolbox = async functio
 
 /**
  * Close a tab and if necessary, the toolbox that belongs to it
  * @param {Tab} tab The tab to close.
  * @return {Promise} Resolves when the toolbox and tab have been destroyed and
  * closed.
  */
 var closeTabAndToolbox = async function(tab = gBrowser.selectedTab) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   if (target) {
     await gDevTools.closeToolbox(target);
   }
 
   await removeTab(tab);
 };
 
 /**
@@ -613,17 +613,17 @@ function pushPref(preferenceName, value)
  * @return {?} anything that is found at the provided path in the object.
  */
 function lookupPath(obj, path) {
   const segments = path.split(".");
   return segments.reduce((prev, current) => prev[current], obj);
 }
 
 var closeToolbox = async function() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
 };
 
 /**
  * Clean the logical clipboard content. This method only clears the OS clipboard on
  * Windows (see Bug 666254).
  */
 function emptyClipboard() {
--- a/devtools/client/sourceeditor/test/browser_css_autocompletion.js
+++ b/devtools/client/sourceeditor/test/browser_css_autocompletion.js
@@ -79,17 +79,17 @@ add_task(async function test() {
   const tab = await addTab(TEST_URI);
   browser = tab.linkedBrowser;
   await runTests();
   browser = null;
   gBrowser.removeCurrentTab();
 });
 
 async function runTests() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await target.makeRemote();
   inspector = InspectorFront(target.client, target.form);
   const walker = await inspector.getWalker();
   completer = new CSSCompleter({walker: walker,
                                 cssProperties: getClientCssProperties()});
   await checkStateAndMoveOn();
   await completer.walker.release();
   inspector.destroy();
--- a/devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
+++ b/devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
@@ -9,17 +9,17 @@ const TEST_URI = "data:text/html;charset
                  "<div id='baz'></div><body></html>";
 
 add_task(async function() {
   await addTab(TEST_URI);
   await runTests();
 });
 
 async function runTests() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await target.makeRemote();
   const inspector = InspectorFront(target.client, target.form);
   const walker = await inspector.getWalker();
   const {ed, win, edWin} = await setup(null, {
     autocomplete: true,
     mode: Editor.modes.css,
     autocompleteOpts: {walker: walker, cssProperties: getClientCssProperties()}
   });
--- a/devtools/client/storage/test/browser_storage_indexeddb_overflow.js
+++ b/devtools/client/storage/test/browser_storage_indexeddb_overflow.js
@@ -10,17 +10,17 @@ const ITEMS_PER_PAGE = 50;
 
 add_task(async function() {
   await openTabAndSetupStorage(MAIN_DOMAIN + "storage-overflow-indexeddb.html");
 
   info("Run the tests with short DevTools");
   await runTests();
 
   info("Close Toolbox");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
 
   await finishTests();
 });
 
 async function runTests() {
   gUI.tree.expandAll();
 
--- a/devtools/client/storage/test/browser_storage_overflow.js
+++ b/devtools/client/storage/test/browser_storage_overflow.js
@@ -10,17 +10,17 @@ const ITEMS_PER_PAGE = 50;
 
 add_task(async function() {
   await openTabAndSetupStorage(MAIN_DOMAIN + "storage-overflow.html");
 
   info("Run the tests with short DevTools");
   await runTests();
 
   info("Close Toolbox");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
 
   info("Set a toolbox height of 1000px");
   await pushPref("devtools.toolbox.footer.height", 1000);
 
   info("Open storage panel again");
   await openStoragePanel();
 
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -130,17 +130,17 @@ async function openTabAndSetupStorage(ur
  *
  * @param cb {Function} Optional callback, if you don't want to use the returned
  *                      promise
  *
  * @return {Promise} a promise that resolves when the storage inspector is ready
  */
 var openStoragePanel = async function(cb) {
   info("Opening the storage inspector");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
 
   let storage, toolbox;
 
   // Checking if the toolbox and the storage are already loaded
   // The storage-updated event should only be waited for if the storage
   // isn't loaded yet
   toolbox = gDevTools.getToolbox(target);
   if (toolbox) {
--- a/devtools/client/styleeditor/test/browser_styleeditor_fetch-from-netmonitor.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_fetch-from-netmonitor.js
@@ -6,17 +6,17 @@
 // A test to ensure Style Editor only issues 1 request for each stylesheet (instead of 2)
 // by using the network monitor's request history (bug 1306892).
 
 const TEST_URL = TEST_BASE_HTTP + "doc_fetch_from_netmonitor.html";
 
 add_task(async function() {
   info("Opening netmonitor");
   const tab = await addTab("about:blank");
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "netmonitor");
   const monitor = toolbox.getPanel("netmonitor");
   const { store, windowRequire } = monitor.panelWin;
   const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
   const {
     getSortedRequests,
   } = windowRequire("devtools/client/netmonitor/src/selectors/index");
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_loading.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_loading.js
@@ -8,17 +8,17 @@
 const TESTCASE_URI = TEST_BASE_HTTP + "longload.html";
 
 add_task(async function() {
   // launch Style Editor right when the tab is created (before load)
   // this checks that the Style Editor still launches correctly when it is
   // opened *while* the page is still loading. The Style Editor should not
   // signal that it is loaded until the accompanying content page is loaded.
   const tabAdded = addTab(TESTCASE_URI);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const styleEditorLoaded = gDevTools.showToolbox(target, "styleeditor");
 
   await Promise.all([tabAdded, styleEditorLoaded]);
 
   const toolbox = gDevTools.getToolbox(target);
   const panel = toolbox.getPanel("styleeditor");
   const { panelWindow } = panel;
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_sync.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sync.js
@@ -15,17 +15,17 @@ const expectedText = `
   }
 
   #testid {
     /*! font-size: 4em; */
   }
   `;
 
 async function closeAndReopenToolbox() {
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.closeToolbox(target);
   const { ui: newui } = await openStyleEditor();
   return newui;
 }
 
 add_task(async function() {
   await addTab(TESTCASE_URI);
   const { inspector, view } = await openRuleView();
--- a/devtools/client/styleeditor/test/browser_styleeditor_xul.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_xul.js
@@ -7,16 +7,16 @@
 "use strict";
 
 waitForExplicitFinish();
 
 const TEST_URL = TEST_BASE + "doc_xulpage.xul";
 
 add_task(async function() {
   const tab = await addTab(TEST_URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
 
   const toolbox = await gDevTools.showToolbox(target, "styleeditor");
   const panel = toolbox.getCurrentPanel();
 
   ok(panel,
      "The style-editor panel did initialize correctly for the XUL window");
 });
--- a/devtools/client/styleeditor/test/head.js
+++ b/devtools/client/styleeditor/test/head.js
@@ -67,17 +67,17 @@ var reloadPageAndWaitForStyleSheets = as
 
 /**
  * Open the style editor for the current tab.
  */
 var openStyleEditor = async function(tab) {
   if (!tab) {
     tab = gBrowser.selectedTab;
   }
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, "styleeditor");
   const panel = toolbox.getPanel("styleeditor");
   const ui = panel.UI;
 
   // The stylesheet list appears with an animation. Let this animation finish.
   const animations = ui._root.getAnimations({subtree: true});
   await Promise.all(animations.map(a => a.finished));
 
--- a/devtools/client/webaudioeditor/test/head.js
+++ b/devtools/client/webaudioeditor/test/head.js
@@ -59,17 +59,17 @@ function navigate(aTarget, aUrl, aWaitFo
 function initBackend(aUrl) {
   info("Initializing a web audio editor front.");
 
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     const front = new WebAudioFront(target.client, target.form);
     return { target, front };
   })();
 }
 
@@ -78,17 +78,17 @@ function initBackend(aUrl) {
  * panel.
  * This requires calling teardown before the test ends.
  */
 function initWebAudioEditor(aUrl) {
   info("Initializing a web audio editor pane.");
 
   return (async function() {
     const tab = await addTab(aUrl);
-    const target = TargetFactory.forTab(tab);
+    const target = await TargetFactory.forTab(tab);
 
     await target.makeRemote();
 
     Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", true);
     const toolbox = await gDevTools.showToolbox(target, "webaudioeditor");
     const panel = toolbox.getCurrentPanel();
     return { target, panel, toolbox };
   })();
--- a/devtools/client/webconsole/test/mochitest/browser_console_webconsole_ctrlw_close_tab.js
+++ b/devtools/client/webconsole/test/mochitest/browser_console_webconsole_ctrlw_close_tab.js
@@ -16,17 +16,17 @@ add_task(async function() {
   await pushPref("toolkit.cosmeticAnimations.enabled", false);
 
   let hud = await openNewTabAndConsole(TEST_URI);
 
   const tabClosed = defer();
   const toolboxDestroyed = defer();
   const tabSelected = defer();
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
   gBrowser.tabContainer.addEventListener("TabClose", function() {
     info("tab closed");
     tabClosed.resolve(null);
   }, {once: true});
 
   gBrowser.tabContainer.addEventListener("TabSelect", function() {
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
@@ -27,17 +27,17 @@ add_task(async function() {
 });
 
 async function performTests() {
   const { jsterm } = await openNewTabAndConsole(TEST_URI);
   const {
     autocompletePopup: popup,
   } = jsterm;
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
   const jstermComplete = value => setInputValueForAutocompletion(jsterm, value);
 
   // Test that document.title gives string methods. Native getters must execute.
   await jstermComplete("document.title.");
 
   const newItemsLabels = getPopupLabels(popup);
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_close_unfocused_window.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_close_unfocused_window.js
@@ -33,12 +33,12 @@ add_task(async function() {
   win2.close();
 
   info("Close the test tab in the first window");
   window.gBrowser.removeTab(tab1);
 
   ok(true, "No error was triggered during the test");
 });
 
-function closeToolboxForTab(tab) {
-  const target = TargetFactory.forTab(tab);
+async function closeToolboxForTab(tab) {
+  const target = await TargetFactory.forTab(tab);
   return gDevTools.closeToolbox(target);
 }
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_location_debugger_link.js
@@ -24,17 +24,17 @@ add_task(async function() {
 
   // On e10s, the exception thrown in test-location-debugger-link-errors.js
   // is triggered in child process and is ignored by test harness
   if (!Services.appinfo.browserTabsRemoteAutostart) {
     expectUncaughtException();
   }
 
   const hud = await openNewTabAndConsole(TEST_URI);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
   await testOpenInDebugger(hud, toolbox, "document.bar");
 
   info("Selecting the console again");
   await toolbox.selectTool("webconsole");
   await testOpenInDebugger(hud, toolbox, "Blah Blah");
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_location_scratchpad_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_location_scratchpad_link.js
@@ -8,17 +8,17 @@
 const TEST_URI = "data:text/html;charset=utf8,<p>test Scratchpad panel linking</p>";
 
 add_task(async function() {
   await pushPref("devtools.scratchpad.enabled", true);
   await openNewTabAndToolbox(TEST_URI);
 
   info("Opening toolbox with Scratchpad panel");
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "scratchpad", "window");
 
   const scratchpadPanel = toolbox.getPanel("scratchpad");
   const { scratchpad } = scratchpadPanel;
   is(toolbox.getCurrentPanel(), scratchpadPanel,
     "Scratchpad is currently selected panel");
 
   info("Switching to webconsole panel");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_location_styleeditor_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_location_styleeditor_link.js
@@ -7,17 +7,17 @@
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/" +
                  "test-location-styleeditor-link.html";
 
 add_task(async function() {
   await pushPref("devtools.webconsole.filter.css", true);
   const hud = await openNewTabAndConsole(TEST_URI);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
   await testViewSource(hud, toolbox, "\u2018font-weight\u2019");
 
   info("Selecting the console again");
   await toolbox.selectTool("webconsole");
   await testViewSource(hud, toolbox, "\u2018color\u2019");
 });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_network_attach.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_network_attach.js
@@ -9,17 +9,17 @@ const TEST_PATH = "http://example.com/br
 const TEST_URI = TEST_PATH + TEST_FILE;
 
 add_task(async function task() {
   await pushPref("devtools.webconsole.filter.net", false);
   await pushPref("devtools.webconsole.filter.netxhr", true);
   await openNewTabAndToolbox(TEST_URI, "netmonitor");
 
   const currentTab = gBrowser.selectedTab;
-  const target = TargetFactory.forTab(currentTab);
+  const target = await TargetFactory.forTab(currentTab);
   const toolbox = gDevTools.getToolbox(target);
 
   const monitor = toolbox.getCurrentPanel();
   const netReady = monitor.panelWin.api.once("NetMonitor:PayloadReady");
 
   // Fire an XHR POST request.
   await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
     content.wrappedJSObject.testXhrGet();
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
@@ -51,17 +51,17 @@ const tabs = [{
 }];
 
 /**
  * Main test for checking HTTP logs in the Console panel.
  */
 add_task(async function task() {
   const hud = await openNewTabAndConsole(TEST_URI);
   const currentTab = gBrowser.selectedTab;
-  const target = TargetFactory.forTab(currentTab);
+  const target = await TargetFactory.forTab(currentTab);
 
   // Execute XHR and expand it after all network
   // update events are received. Consequently,
   // check out content of all (HTTP details) tabs.
   await openRequestAfterUpdates(target, hud);
 
   // Test proper UI update when request is opened.
   // For every tab (with HTTP details):
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_openinnet.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_openinnet.js
@@ -20,17 +20,17 @@ registerCleanupFunction(() => {
   Services.prefs.clearUserPref(NET_PREF);
   Services.prefs.clearUserPref(XHR_PREF);
 });
 
 add_task(async function task() {
   const hud = await openNewTabAndConsole(TEST_URI);
 
   const currentTab = gBrowser.selectedTab;
-  const target = TargetFactory.forTab(currentTab);
+  const target = await TargetFactory.forTab(currentTab);
   const toolbox = gDevTools.getToolbox(target);
 
   const documentUrl = TEST_PATH + TEST_FILE;
   await loadDocument(documentUrl);
   info("Document loaded.");
 
   await openMessageInNetmonitor(toolbox, hud, documentUrl);
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_status_code.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_status_code.js
@@ -15,17 +15,17 @@ const LEARN_MORE_URI = "https://develope
 
 pushPref(NET_PREF, true);
 pushPref(XHR_PREF, true);
 
 add_task(async function task() {
   const hud = await openNewTabAndConsole(TEST_URI);
 
   const currentTab = gBrowser.selectedTab;
-  const target = TargetFactory.forTab(currentTab);
+  const target = await TargetFactory.forTab(currentTab);
   const toolbox = gDevTools.getToolbox(target);
   const {ui} = toolbox.getCurrentPanel().hud;
   const onNetworkMessageUpdate = ui.jsterm.hud.once("network-message-updated");
 
   // Fire an XHR POST request.
   await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
     content.wrappedJSObject.testXhrPost();
   });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js
@@ -19,17 +19,17 @@ const TEST_URI = "https://example.com/br
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
 
   info("Switch to the debugger");
   await openDebugger();
 
   info("Switch to the inspector");
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await gDevTools.showToolbox(target, "inspector");
 
   info("Call firstCall() and wait for the debugger statement to be reached.");
   const toolbox = gDevTools.getToolbox(target);
   const dbg = createDebuggerContext(toolbox);
   await pauseDebugger(dbg);
 
   info("Switch back to the console");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_shows_reqs_from_netmonitor.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_shows_reqs_from_netmonitor.js
@@ -34,17 +34,17 @@ add_task(async function task() {
 
   await loadDocument(TEST_PATH);
   info("Document loaded.");
 
   await onMessageAdded;
   info("Network message found.");
 
   // Test that the request appears in the network panel.
-  const target = TargetFactory.forTab(currentTab);
+  const target = await TargetFactory.forTab(currentTab);
   const toolbox = await gDevTools.showToolbox(target, "netmonitor");
   info("Network panel is open.");
 
   await testNetmonitor(toolbox);
 });
 
 async function testNetmonitor(toolbox) {
   const monitor = toolbox.getCurrentPanel();
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_split.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_split.js
@@ -242,17 +242,17 @@ async function performTests() {
        "Web console is collapsed after toggling");
     ok(!currentUIState.openedConsolePanel,
        "The console panel is not the current tool");
     is(currentUIState.menuLabel, "split",
        "The menu item indicates the console is not split");
   }
 
   async function openPanel(toolId) {
-    const target = TargetFactory.forTab(gBrowser.selectedTab);
+    const target = await TargetFactory.forTab(gBrowser.selectedTab);
     toolbox = await gDevTools.showToolbox(target, toolId);
   }
 
   async function openAndCheckPanel(toolId) {
     await openPanel(toolId);
     await checkToolboxUI(toolbox.getCurrentPanel());
   }
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
@@ -20,17 +20,17 @@ const TEST_URI = "http://example.com/bro
 
 add_task(async function() {
   Services.prefs.setBoolPref("devtools.webconsole.filter.log", true);
   registerCleanupFunction(async function() {
     Services.prefs.clearUserPref("devtools.webconsole.filter.log");
   });
 
   const hud = await openNewTabAndConsole(TEST_URI);
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
   await testOpenInDebugger(hud, toolbox, "console.trace()");
 });
 
 async function testOpenInDebugger(hud, toolbox, text) {
   info(`Testing message with text "${text}"`);
   const messageNode = await waitFor(() => findMessage(hud, text));
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_scratchpad_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_scratchpad_link.js
@@ -8,17 +8,17 @@
 const TEST_URI = "data:text/html;charset=utf8,<p>test stacktrace scratchpad linking</p>";
 
 add_task(async function() {
   await pushPref("devtools.scratchpad.enabled", true);
   await openNewTabAndToolbox(TEST_URI);
 
   info("Opening toolbox with Scratchpad panel");
 
-  const target = TargetFactory.forTab(gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "scratchpad", "window");
 
   const scratchpadPanel = toolbox.getPanel("scratchpad");
   const { scratchpad } = scratchpadPanel;
   is(toolbox.getCurrentPanel(), scratchpadPanel,
     "Scratchpad is currently selected panel");
 
   info("Switching to webconsole panel");
--- a/devtools/client/webconsole/test/mochitest/head.js
+++ b/devtools/client/webconsole/test/mochitest/head.js
@@ -519,17 +519,17 @@ function isJstermFocused(jsterm) {
  *         - toolbox: the Toolbox instance.
  *         - panel: the jsdebugger panel instance.
  */
 async function openDebugger(options = {}) {
   if (!options.tab) {
     options.tab = gBrowser.selectedTab;
   }
 
-  const target = TargetFactory.forTab(options.tab);
+  const target = await TargetFactory.forTab(options.tab);
   let toolbox = gDevTools.getToolbox(target);
   const dbgPanelAlreadyOpen = toolbox && toolbox.getPanel("jsdebugger");
   if (dbgPanelAlreadyOpen) {
     await toolbox.selectTool("jsdebugger");
 
     return {
       target,
       toolbox,
@@ -555,48 +555,48 @@ async function openDebugger(options = {}
   return {target, toolbox, panel};
 }
 
 async function openInspector(options = {}) {
   if (!options.tab) {
     options.tab = gBrowser.selectedTab;
   }
 
-  const target = TargetFactory.forTab(options.tab);
+  const target = await TargetFactory.forTab(options.tab);
   const toolbox = await gDevTools.showToolbox(target, "inspector");
 
   return toolbox.getCurrentPanel();
 }
 
 /**
  * Open the Web Console for the given tab, or the current one if none given.
  *
  * @param Element tab
  *        Optional tab element for which you want open the Web Console.
  *        Defaults to current selected tab.
  * @return Promise
  *         A promise that is resolved with the console hud once the web console is open.
  */
 async function openConsole(tab) {
-  const target = TargetFactory.forTab(tab || gBrowser.selectedTab);
+  const target = await TargetFactory.forTab(tab || gBrowser.selectedTab);
   const toolbox = await gDevTools.showToolbox(target, "webconsole");
   return toolbox.getCurrentPanel().hud;
 }
 
 /**
  * Close the Web Console for the given tab.
  *
  * @param Element [tab]
  *        Optional tab element for which you want close the Web Console.
  *        Defaults to current selected tab.
  * @return object
  *         A promise that is resolved once the web console is closed.
  */
 async function closeConsole(tab = gBrowser.selectedTab) {
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = gDevTools.getToolbox(target);
   if (toolbox) {
     await toolbox.destroy();
   }
 }
 
 /**
  * Fake clicking a link and return the URL we would have navigated to.
--- a/devtools/docs/frontend/telemetry.md
+++ b/devtools/docs/frontend/telemetry.md
@@ -378,17 +378,17 @@ add_task(async function() {
   await openAndCloseToolbox("webconsole", SIDE);
   await openAndCloseToolbox("webconsole", BOTTOM);
 
   checkResults();
 });
 
 async function openAndCloseToolbox(toolId, host) {
   const tab = await addTab(URL);
-  const target = TargetFactory.forTab(tab);
+  const target = await TargetFactory.forTab(tab);
   const toolbox = await gDevTools.showToolbox(target, toolId);
 
   await toolbox.switchHost(host);
   await toolbox.destroy();
 }
 
 function checkResults() {
   const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
--- a/devtools/server/tests/mochitest/test_framerate_04.html
+++ b/devtools/server/tests/mochitest/test_framerate_04.html
@@ -23,17 +23,17 @@ window.onload = function() {
   const url = document.getElementById("testContent").href;
   attachURL(url, onTab);
 
   async function onTab(_, client, form, contentDoc) {
     const contentWin = contentDoc.defaultView;
     const chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
     const selectedTab = chromeWin.gBrowser.selectedTab;
 
-    const target = TargetFactory.forTab(selectedTab);
+    const target = await TargetFactory.forTab(selectedTab);
     await target.makeRemote();
     const front = FramerateFront(client, form);
 
     front.startRecording().then(() => {
       window.setTimeout(() => {
         front.getPendingTicks().then(firstBatch => {
           /* eslint-disable max-nested-callbacks */
           target.once("will-navigate", () => {
--- a/dom/security/test/cors/head.js
+++ b/dom/security/test/cors/head.js
@@ -18,17 +18,17 @@ let promise = require("promise");
  * @param {String} toolId Optional. The ID of the tool to be selected.
  * @param {String} hostType Optional. The type of toolbox host to be used.
  * @return {Promise} Resolves with the toolbox, when it has been opened.
  */
 var openToolboxForTab = async function(tab, toolId, hostType) {
   info("Opening the toolbox");
 
   let toolbox;
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   // Check if the toolbox is already loaded.
   toolbox = gDevTools.getToolbox(target);
   if (toolbox) {
     if (!toolId || (toolId && toolbox.getPanel(toolId))) {
       info("Toolbox is already opened");
       return toolbox;
--- a/dom/security/test/general/browser_test_FTP_console_warning.js
+++ b/dom/security/test/general/browser_test_FTP_console_warning.js
@@ -20,17 +20,17 @@ let promise = require("promise");
  * @param {String} toolId Optional. The ID of the tool to be selected.
  * @param {String} hostType Optional. The type of toolbox host to be used.
  * @return {Promise} Resolves with the toolbox, when it has been opened.
  */
 var openToolboxForTab = async function(tab, toolId, hostType) {
   info("Opening the toolbox");
 
   let toolbox;
-  let target = TargetFactory.forTab(tab);
+  let target = await TargetFactory.forTab(tab);
   await target.makeRemote();
 
   // Check if the toolbox is already loaded.
   toolbox = gDevTools.getToolbox(target);
   if (toolbox) {
     if (!toolId || (toolId && toolbox.getPanel(toolId))) {
       info("Toolbox is already opened");
       return toolbox;