Bug 1465635 - Remove Target.activeTab property. r=yulia
authorAlexandre Poirot <poirot.alex@gmail.com>
Sat, 02 Feb 2019 11:24:24 +0000
changeset 456551 aff30c79fa91fa4b444cc76f1d9e2a4ac487b6af
parent 456550 1dfe4f2eb472d1dd9251297f9476e786c2cd751a
child 456552 cb3aef2a4aff23ebfbe56076c5ee9edf60ad0da8
push id35489
push userrmaries@mozilla.com
push dateSat, 02 Feb 2019 21:36:03 +0000
treeherdermozilla-central@63348118ef1d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyulia
bugs1465635
milestone67.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 1465635 - Remove Target.activeTab property. r=yulia Depends on D15831 Differential Revision: https://phabricator.services.mozilla.com/D16874
devtools/client/accessibility/test/browser/head.js
devtools/client/application/initializer.js
devtools/client/application/test/head.js
devtools/client/canvasdebugger/test/head.js
devtools/client/debugger/new/src/client/firefox.js
devtools/client/debugger/new/src/client/firefox/commands.js
devtools/client/debugger/new/src/client/firefox/workers.js
devtools/client/debugger/new/test/mochitest/browser_dbg-inline-cache.js
devtools/client/framework/attach-thread.js
devtools/client/framework/test/browser_target_server_compartment.js
devtools/client/framework/test/browser_toolbox_options_disable_js.js
devtools/client/framework/test/browser_toolbox_target.js
devtools/client/framework/toolbox-options.js
devtools/client/framework/toolbox.js
devtools/client/inspector/test/browser_inspector_reload_xul.js
devtools/client/inspector/test/browser_inspector_select-last-selected.js
devtools/client/inspector/test/browser_inspector_startup.js
devtools/client/inspector/test/head.js
devtools/client/netmonitor/src/connector/firefox-connector.js
devtools/client/netmonitor/src/har/har-automation.js
devtools/client/netmonitor/test/head.js
devtools/client/performance/test/helpers/actions.js
devtools/client/scratchpad/scratchpad.js
devtools/client/shadereditor/test/head.js
devtools/client/shared/test/browser_dbg_WorkerTargetActor.attach.js
devtools/client/shared/test/browser_dbg_debugger-statement.js
devtools/client/shared/test/browser_dbg_listworkers.js
devtools/client/shared/test/browser_dbg_navigation.js
devtools/client/shared/test/browser_dbg_target-scoped-actor-01.js
devtools/client/shared/test/browser_dbg_target-scoped-actor-02.js
devtools/client/shared/test/browser_dbg_worker-window.js
devtools/client/shared/test/helper_workers.js
devtools/client/webaudioeditor/test/head.js
devtools/client/webconsole/enhancers/css-error-reporting.js
devtools/client/webconsole/test/components/new-console-output-wrapper.test.js
devtools/client/webconsole/test/helpers.js
devtools/client/webconsole/webconsole-output-wrapper.js
devtools/client/webconsole/webconsole.js
devtools/client/webide/modules/app-manager.js
devtools/docs/backend/client-api.md
devtools/server/tests/browser/browser_navigateEvents.js
devtools/server/tests/browser/browser_spawn_actor_in_parent.js
devtools/server/tests/browser/browser_webextension_inspected_window.js
devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
devtools/server/tests/mochitest/webextension-helpers.js
devtools/shared/webconsole/test/common.js
--- a/devtools/client/accessibility/test/browser/head.js
+++ b/devtools/client/accessibility/test/browser/head.js
@@ -392,22 +392,22 @@ function addA11YPanelTask(msg, uri, task
 }
 
 /**
  * Reload panel target.
  * @param  {Object} target             Panel target.
  * @param  {String} waitForTargetEvent Event to wait for after reload.
  */
 function reload(target, waitForTargetEvent = "navigate") {
-  executeSoon(() => target.activeTab.reload());
+  executeSoon(() => target.reload());
   return once(target, waitForTargetEvent);
 }
 
 /**
  * Navigate to a new URL within the panel target.
  * @param  {Object} target             Panel target.
  * @param  {Srting} url                URL to navigate to.
  * @param  {String} waitForTargetEvent Event to wait for after reload.
  */
 function navigate(target, url, waitForTargetEvent = "navigate") {
-  executeSoon(() => target.activeTab.navigateTo({ url }));
+  executeSoon(() => target.navigateTo({ url }));
   return once(target, waitForTargetEvent);
 }
--- a/devtools/client/application/initializer.js
+++ b/devtools/client/application/initializer.js
@@ -39,17 +39,17 @@ window.Application = {
     this.actions = bindActionCreators(actions, this.store.dispatch);
     this.serviceWorkerRegistrationFronts = [];
 
     const serviceContainer = {
       selectTool(toolId) {
         return toolbox.selectTool(toolId);
       },
     };
-    this.toolbox.target.activeTab.on("workerListChanged", this.updateWorkers);
+    this.toolbox.target.on("workerListChanged", this.updateWorkers);
     this.client.mainRoot.on("serviceWorkerRegistrationListChanged", this.updateWorkers);
     this.client.mainRoot.on("processListChanged", this.updateWorkers);
     this.client.mainRoot.onFront("serviceWorkerRegistration", front => {
       this.serviceWorkerRegistrationFronts.push(front);
       front.on("push-subscription-modified", this.updateWorkers);
       front.on("registration-changed", this.updateWorkers);
     });
     this.toolbox.target.on("navigate", this.updateDomain);
@@ -96,17 +96,17 @@ window.Application = {
     this.serviceWorkerRegistrationFronts = [];
   },
 
   updateDomain() {
     this.actions.updateDomain(this.toolbox.target.url);
   },
 
   destroy() {
-    this.toolbox.target.activeTab.off("workerListChanged", this.updateWorkers);
+    this.toolbox.target.off("workerListChanged", this.updateWorkers);
     this.client.mainRoot.off("serviceWorkerRegistrationListChanged",
       this.updateWorkers);
     this.client.mainRoot.off("processListChanged", this.updateWorkers);
     this.removeRegistrationFrontListeners();
     this.toolbox.target.off("navigate", this.updateDomain);
 
     unmountComponentAtNode(this.mount);
     this.mount = null;
--- a/devtools/client/application/test/head.js
+++ b/devtools/client/application/test/head.js
@@ -36,17 +36,17 @@ async function enableApplicationPanel() 
   await pushPref("devtools.application.enabled", true);
 }
 
 function getWorkerContainers(doc) {
   return doc.querySelectorAll(".js-sw-container");
 }
 
 function navigate(target, url, waitForTargetEvent = "navigate") {
-  executeSoon(() => target.activeTab.navigateTo({ url }));
+  executeSoon(() => target.navigateTo({ url }));
   return once(target, waitForTargetEvent);
 }
 
 async function openNewTabAndApplicationPanel(url) {
   const tab = await addTab(url);
   const target = await TargetFactory.forTab(tab);
 
   const toolbox = await gDevTools.showToolbox(target, "application");
--- a/devtools/client/canvasdebugger/test/head.js
+++ b/devtools/client/canvasdebugger/test/head.js
@@ -100,22 +100,22 @@ function isTestingSupported() {
 }
 
 function navigateInHistory(aTarget, aDirection, aWaitForTargetEvent = "navigate") {
   executeSoon(() => content.history[aDirection]());
   return once(aTarget, aWaitForTargetEvent);
 }
 
 function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
-  executeSoon(() => aTarget.activeTab.navigateTo({ url: aUrl }));
+  executeSoon(() => aTarget.navigateTo({ url: aUrl }));
   return once(aTarget, aWaitForTargetEvent);
 }
 
 function reload(aTarget, aWaitForTargetEvent = "navigate") {
-  executeSoon(() => aTarget.activeTab.reload());
+  executeSoon(() => aTarget.reload());
   return once(aTarget, aWaitForTargetEvent);
 }
 
 function initServer() {
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
 }
 
--- a/devtools/client/debugger/new/src/client/firefox.js
+++ b/devtools/client/debugger/new/src/client/firefox.js
@@ -50,17 +50,17 @@ export async function onConnect(connecti
 
   // In Firefox, we need to initially request all of the sources. This
   // usually fires off individual `newSource` notifications as the
   // debugger finds them, but there may be existing sources already in
   // the debugger (if it's paused already, or if loading the page from
   // bfcache) so explicity fire `newSource` events for all returned
   // sources.
   const sources = await clientCommands.fetchSources();
-  const traits = tabTarget.activeTab ? tabTarget.activeTab.traits : null;
+  const traits = tabTarget.traits;
   await actions.connect(
     tabTarget.url,
     threadClient.actor,
     traits && traits.canRewind
   );
   await actions.newSources(sources);
 
   // If the threadClient is already paused, make sure to show a
--- a/devtools/client/debugger/new/src/client/firefox/commands.js
+++ b/devtools/client/debugger/new/src/client/firefox/commands.js
@@ -296,21 +296,21 @@ function autocomplete(
       cursor,
       result => resolve(result),
       frameId
     );
   });
 }
 
 function navigate(url: string): Promise<*> {
-  return tabTarget.activeTab.navigateTo({ url });
+  return tabTarget.navigateTo({ url });
 }
 
 function reload(): Promise<*> {
-  return tabTarget.activeTab.reload();
+  return tabTarget.reload();
 }
 
 function getProperties(thread: string, grip: Grip): Promise<*> {
   const objClient = lookupThreadClient(thread).pauseGrip(grip);
 
   return objClient.getPrototypeAndProperties().then(resp => {
     const { ownProperties, safeGetterValues } = resp;
     for (const name in safeGetterValues) {
@@ -443,17 +443,17 @@ async function fetchWorkers(): Promise<W
       createWorker(actor, workerClients[actor].url)
     );
   }
 
   if (!supportsWorkers(tabTarget)) {
     return Promise.resolve([]);
   }
 
-  const { workers } = await tabTarget.activeTab.listWorkers();
+  const { workers } = await tabTarget.listWorkers();
   return workers;
 }
 
 function getMainThread() {
   return threadClient.actor;
 }
 
 const clientCommands = {
--- a/devtools/client/debugger/new/src/client/firefox/workers.js
+++ b/devtools/client/debugger/new/src/client/firefox/workers.js
@@ -18,17 +18,17 @@ export async function updateWorkerClient
   workerClients
 }: Object) {
   if (!supportsWorkers(tabTarget)) {
     return {};
   }
 
   const newWorkerClients = {};
 
-  const { workers } = await tabTarget.activeTab.listWorkers();
+  const { workers } = await tabTarget.listWorkers();
   for (const workerTargetFront of workers) {
     await workerTargetFront.attach();
     const [, workerThread] = await workerTargetFront.attachThread();
 
     if (workerClients[workerThread.actor]) {
       if (workerClients[workerThread.actor].thread != workerThread) {
         throw new Error(`Multiple clients for actor ID: ${workerThread.actor}`);
       }
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-inline-cache.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-inline-cache.js
@@ -71,17 +71,17 @@ add_task(async function() {
   let dbgValue = await findSource(dbg, "inline-cache.html");
   info(`Debugger text: ${dbgValue.text}`);
   ok(
     dbgValue.text.includes(pageValue),
     "Debugger loads from cache, gets value 1 like page"
   );
 
   info("Disable HTTP cache for page");
-  await toolbox.target.activeTab.reconfigure({ options: { cacheDisabled: true } });
+  await toolbox.target.reconfigure({ options: { cacheDisabled: true } });
   makeChanges();
 
   info("Reload inside debugger with toolbox caching disabled (attempt 1)");
   await reloadTabAndDebugger(tab, dbg);
   pageValue = await getPageValue(tab);
   is(pageValue, "let x = 2;", "Content loads from network, has doc value 2");
   await waitForLoadedSource(dbg, "inline-cache.html");
   dbgValue = await findSource(dbg, "inline-cache.html");
@@ -101,17 +101,17 @@ add_task(async function() {
   dbgValue = await findSource(dbg, "inline-cache.html");
   info(`Debugger text: ${dbgValue.text}`);
   ok(
     dbgValue.text.includes(pageValue),
     "Debugger loads from network, gets value 3 like page"
   );
 
   info("Enable HTTP cache for page");
-  await toolbox.target.activeTab.reconfigure({ options: { cacheDisabled: false } });
+  await toolbox.target.reconfigure({ options: { cacheDisabled: false } });
   makeChanges();
 
   // Even though the HTTP cache is now enabled, Gecko sets the VALIDATE_ALWAYS flag when
   // reloading the page.  So, it will always make a request to the server for the main
   // document contents.
 
   info("Reload inside debugger with toolbox caching enabled (attempt 1)");
   await reloadTabAndDebugger(tab, dbg);
--- a/devtools/client/framework/attach-thread.js
+++ b/devtools/client/framework/attach-thread.js
@@ -76,22 +76,17 @@ function attachThread(toolbox) {
             box.PRIORITY_WARNING_HIGH
           );
         }
 
         resolve(threadClient);
       });
     };
 
-    if (target.activeTab) {
-      target.activeTab.attachThread(threadOptions).then(handleResponse);
-    } else {
-      // Now, all targets should have a front set on activeTab attribute.
-      throw new Error("Target is missing an activeTab attribute");
-    }
+    target.attachThread(threadOptions).then(handleResponse);
   });
 }
 
 function detachThread(threadClient) {
   threadClient.removeListener("paused");
   threadClient.removeListener("resumed");
 }
 
--- a/devtools/client/framework/test/browser_target_server_compartment.js
+++ b/devtools/client/framework/test/browser_target_server_compartment.js
@@ -33,17 +33,17 @@ async function testChromeTab() {
       }
     };
     Services.obs.addObserver(observe, "devtools-thread-instantiated");
   });
 
   const target = await TargetFactory.forTab(tab);
   await target.attach();
 
-  const [, threadClient] = await target.activeTab.attachThread();
+  const [, threadClient] = await target.attachThread();
   await threadClient.resume();
 
   const { sources } = await threadClient.getSources();
   ok(sources.find(s => s.url == CHROME_PAGE),
     "The thread actor is able to attach to the chrome page and its sources");
 
   const threadActor = await onThreadActorInstantiated;
   const serverGlobal = Cu.getGlobalForObject(threadActor);
@@ -97,17 +97,17 @@ async function testMainProcess() {
   const targetFront = await client.mainRoot.getMainProcess();
   const target = await TargetFactory.forRemoteTab({
     client,
     activeTab: targetFront,
     chrome: true,
   });
   await target.attach();
 
-  const [, threadClient] = await target.activeTab.attachThread();
+  const [, threadClient] = await target.attachThread();
   await threadClient.resume();
   const { sources } = await threadClient.getSources();
   ok(sources.find(s => s.url == "resource://devtools/client/framework/devtools.js"),
     "The thread actor is able to attach to the chrome script, like client modules");
 
   const threadActor = await onThreadActorInstantiated;
   const serverGlobal = Cu.getGlobalForObject(threadActor);
   isnot(loader.id, serverGlobal.loader.id,
--- a/devtools/client/framework/test/browser_toolbox_options_disable_js.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_js.js
@@ -68,25 +68,25 @@ async function toggleJS(toolbox) {
   const cbx = panel.panelDoc.getElementById("devtools-disable-javascript");
 
   if (cbx.checked) {
     info("Clearing checkbox to re-enable JS");
   } else {
     info("Checking checkbox to disable JS");
   }
 
-  let { javascriptEnabled } = toolbox.target.activeTab.configureOptions;
+  let { javascriptEnabled } = toolbox.target.configureOptions;
   is(javascriptEnabled, !cbx.checked,
     "BrowsingContextTargetFront's configureOptions is correct before the toggle");
 
   const browserLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
   cbx.click();
   await browserLoaded;
 
-  ({ javascriptEnabled } = toolbox.target.activeTab.configureOptions);
+  ({ javascriptEnabled } = toolbox.target.configureOptions);
   is(javascriptEnabled, !cbx.checked,
     "BrowsingContextTargetFront's configureOptions is correctly updated");
 }
 
 async function testJSDisabled() {
   info("Testing that JS is disabled");
 
   await ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
--- a/devtools/client/framework/test/browser_toolbox_target.js
+++ b/devtools/client/framework/test/browser_toolbox_target.js
@@ -37,17 +37,17 @@ add_task(async function() {
   // is plenty of asynchronous steps during toolbox load
   info("Waiting for toolbox-ready");
   const toolbox = await onToolboxReady;
 
   is(toolbox.hostType, Toolbox.HostType.PAGE,
      "Host type of this toolbox shuld be Toolbox.HostType.PAGE");
 
   const onToolboxDestroyed = gDevTools.once("toolbox-destroyed");
-  const onTabDetached = toolbox.target.activeTab.once("tabDetached");
+  const onTabDetached = toolbox.target.once("tabDetached");
 
   info("Removing the iframes");
   toolboxIframe.remove();
 
   // And wait for toolbox-destroyed as toolbox unload is also full of
   // asynchronous operation that outlast unload event
   info("Waiting for toolbox-destroyed");
   await onToolboxDestroyed;
--- a/devtools/client/framework/toolbox-options.js
+++ b/devtools/client/framework/toolbox-options.js
@@ -454,19 +454,19 @@ OptionsPanel.prototype = {
 
       prefSelect.addEventListener("change", function(e) {
         const select = e.target;
         SetPref(select.getAttribute("data-pref"),
           select.options[select.selectedIndex].value);
       });
     }
 
-    if (this.target.activeTab && !this.target.chrome) {
+    if (!this.target.chrome) {
       this.disableJSNode.checked =
-        !this.target.activeTab.configureOptions.javascriptEnabled;
+        !this.target.configureOptions.javascriptEnabled;
       this.disableJSNode.addEventListener("click", this._disableJSClicked);
     } else {
       // Hide the checkbox and label
       this.disableJSNode.parentNode.style.display = "none";
 
       const triggersPageRefreshLabel =
         this.panelDoc.getElementById("triggers-page-refresh-label");
       triggersPageRefreshLabel.style.display = "none";
@@ -506,26 +506,24 @@ OptionsPanel.prototype = {
    */
   _disableJSClicked: function(event) {
     const checked = event.target.checked;
 
     const options = {
       "javascriptEnabled": !checked,
     };
 
-    this.target.activeTab.reconfigure({ options });
+    this.target.reconfigure({ options });
   },
 
   destroy: function() {
     if (this.destroyed) {
       return;
     }
     this.destroyed = true;
 
     this._removeListeners();
 
-    if (this.target.activeTab) {
-      this.disableJSNode.removeEventListener("click", this._disableJSClicked);
-    }
+    this.disableJSNode.removeEventListener("click", this._disableJSClicked);
 
     this.panelWin = this.panelDoc = this.disableJSNode = this.toolbox = null;
   },
 };
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -1260,17 +1260,17 @@ Toolbox.prototype = {
   /**
    * Button to select a frame for the inspector to target.
    */
   _buildFrameButton() {
     this.frameButton = this._createButtonState({
       id: "command-button-frames",
       description: L10N.getStr("toolbox.frames.tooltip"),
       isTargetSupported: target => {
-        return target.activeTab && target.activeTab.traits.frames;
+        return target.traits.frames;
       },
       isCurrentlyVisible: () => {
         const hasFrames = this.frameMap.size > 1;
         const isOnOptionsPanel = this.currentToolId === "options";
         return hasFrames || isOnOptionsPanel;
       },
     });
 
@@ -1355,61 +1355,57 @@ Toolbox.prototype = {
    */
   _buildPickerButton() {
     this.pickerButton = this._createButtonState({
       id: "command-button-pick",
       description: L10N.getStr("pickButton.tooltip"),
       onClick: this._onPickerClick,
       isInStartContainer: true,
       isTargetSupported: target => {
-        return target.activeTab && target.activeTab.traits.frames;
+        return target.traits.frames;
       },
     });
 
     return this.pickerButton;
   },
 
   /**
    * Apply the current cache setting from devtools.cache.disabled to this
    * toolbox's tab.
    */
   _applyCacheSettings: async function() {
     const pref = "devtools.cache.disabled";
     const cacheDisabled = Services.prefs.getBoolPref(pref);
 
-    if (this.target.activeTab) {
-      await this.target.activeTab.reconfigure({
-        options: {
-          "cacheDisabled": cacheDisabled,
-        },
-      });
-
-      // This event is only emitted for tests in order to know when to reload
-      if (flags.testing) {
-        this.emit("cache-reconfigured");
-      }
+    await this.target.reconfigure({
+      options: {
+        "cacheDisabled": cacheDisabled,
+      },
+    });
+
+    // This event is only emitted for tests in order to know when to reload
+    if (flags.testing) {
+      this.emit("cache-reconfigured");
     }
   },
 
   /**
    * Apply the current service workers testing setting from
    * devtools.serviceWorkers.testing.enabled to this toolbox's tab.
    */
   _applyServiceWorkersTestingSettings: function() {
     const pref = "devtools.serviceWorkers.testing.enabled";
     const serviceWorkersTestingEnabled =
       Services.prefs.getBoolPref(pref) || false;
 
-    if (this.target.activeTab) {
-      this.target.activeTab.reconfigure({
-        options: {
-          "serviceWorkersTestingEnabled": serviceWorkersTestingEnabled,
-        },
-      });
-    }
+    this.target.reconfigure({
+      options: {
+        "serviceWorkersTestingEnabled": serviceWorkersTestingEnabled,
+      },
+    });
   },
 
   /**
    * Update the visibility of the buttons.
    */
   updateToolboxButtonsVisibility() {
     this.toolbarButtons.forEach(button => {
       button.isVisible = this._commandIsVisible(button);
@@ -1443,17 +1439,17 @@ Toolbox.prototype = {
    */
   togglePaintFlashing: function() {
     if (this.isPaintFlashing) {
       this.telemetry.toolOpened("paintflashing", this.sessionId, this);
     } else {
       this.telemetry.toolClosed("paintflashing", this.sessionId, this);
     }
     this.isPaintFlashing = !this.isPaintFlashing;
-    return this.target.activeTab.reconfigure({
+    return this.target.reconfigure({
       options: {
         "paintFlashing": this.isPaintFlashing,
       },
     });
   },
 
   /**
    * Visually update picker button.
@@ -2213,17 +2209,17 @@ Toolbox.prototype = {
   /**
    * Tells the target tab to reload.
    */
   reloadTarget: function(force) {
     if (this.target.canRewind) {
       // Recording tabs need to be reloaded in a new content process.
       reloadAndRecordTab();
     } else {
-      this.target.activeTab.reload({ force: force });
+      this.target.reload({ force: force });
     }
   },
 
   /**
    * Loads the tool next to the currently selected tool.
    */
   selectNextTool: function() {
     const definitions = this.component.panelDefinitions;
@@ -2381,32 +2377,32 @@ Toolbox.prototype = {
       return false;
     }
 
     const prefFront = await this.preferenceFront;
     return prefFront.getBoolPref(DISABLE_AUTOHIDE_PREF);
   },
 
   _listFrames: async function(event) {
-    if (!this.target.activeTab || !this.target.activeTab.traits.frames) {
+    if (!this.target.traits.frames) {
       // We are not targetting a regular BrowsingContextTargetActor
       // it can be either an addon or browser toolbox actor
       return promise.resolve();
     }
-    const { frames } = await this.target.activeTab.listFrames();
+    const { frames } = await this.target.listFrames();
     this._updateFrames({ frames });
   },
 
   /**
    * Select a frame by sending 'switchToFrame' packet to the backend.
    */
   onSelectFrame: function(frameId) {
     // Send packet to the backend to select specified frame and
     // wait for 'frameUpdate' event packet to update the UI.
-    this.target.activeTab.switchToFrame({ windowId: frameId });
+    this.target.switchToFrame({ windowId: frameId });
   },
 
   /**
    * Highlight a frame in the page
    */
   onHighlightFrame: async function(frameId) {
     // Need to initInspector to check presence of getNodeActorFromWindowID
     // and use the highlighter later
--- a/devtools/client/inspector/test/browser_inspector_reload_xul.js
+++ b/devtools/client/inspector/test/browser_inspector_reload_xul.js
@@ -27,17 +27,17 @@ async function testToolboxInitialization
 
   await selectNode("#p", inspector);
   await testMarkupView("#p", inspector);
 
   info("Reloading the page.");
   const markuploaded = inspector.once("markuploaded");
   const onNewRoot = inspector.once("new-root");
   const onUpdated = inspector.once("inspector-updated");
-  await toolbox.target.activeTab.reload();
+  await toolbox.target.reload();
   info("Waiting for inspector to be ready.");
   await markuploaded;
   await onNewRoot;
   await onUpdated;
 
   await selectNode("#q", inspector);
   await testMarkupView("#q", inspector);
 
--- a/devtools/client/inspector/test/browser_inspector_select-last-selected.js
+++ b/devtools/client/inspector/test/browser_inspector_select-last-selected.js
@@ -77,18 +77,17 @@ add_task(async function() {
 
     const current = await testActor.eval("location.href");
     if (url == current) {
       info("Reloading page.");
       const markuploaded = inspector.once("markuploaded");
       const onNewRoot = inspector.once("new-root");
       const onUpdated = inspector.once("inspector-updated");
 
-      const activeTab = toolbox.target.activeTab;
-      await activeTab.reload();
+      await toolbox.target.reload();
       info("Waiting for inspector to be ready.");
       await markuploaded;
       await onNewRoot;
       await onUpdated;
     } else {
       await navigateTo(inspector, url);
     }
   }
--- a/devtools/client/inspector/test/browser_inspector_startup.js
+++ b/devtools/client/inspector/test/browser_inspector_startup.js
@@ -36,18 +36,18 @@ add_task(async function() {
 
   const domContentLoaded = waitForLinkedBrowserEvent(tab, "DOMContentLoaded");
   const pageLoaded = waitForLinkedBrowserEvent(tab, "load");
 
   const markupLoaded = inspector.once("markuploaded");
   const onRequest = onPageResourceRequest();
 
   info("Navigate to the slow loading page");
-  const activeTab = inspector.toolbox.target.activeTab;
-  await activeTab.navigateTo({ url: TEST_URL });
+  const target = inspector.toolbox.target;
+  await target.navigateTo({ url: TEST_URL });
 
   info("Wait for request made to the image");
   const response = await onRequest;
 
   // The request made to the image shouldn't block the DOMContentLoaded event
   info("Wait for DOMContentLoaded");
   await domContentLoaded;
 
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -42,18 +42,18 @@ registerCleanupFunction(function() {
 });
 
 var navigateTo = async function(inspector, url) {
   const markuploaded = inspector.once("markuploaded");
   const onNewRoot = inspector.once("new-root");
   const onUpdated = inspector.once("inspector-updated");
 
   info("Navigating to: " + url);
-  const activeTab = inspector.toolbox.target.activeTab;
-  await activeTab.navigateTo({ url });
+  const target = inspector.toolbox.target;
+  await target.navigateTo({ url });
 
   info("Waiting for markup view to load after navigation.");
   await markuploaded;
 
   info("Waiting for new root.");
   await onNewRoot;
 
   info("Waiting for inspector to update after new-root event.");
--- a/devtools/client/netmonitor/src/connector/firefox-connector.js
+++ b/devtools/client/netmonitor/src/connector/firefox-connector.js
@@ -264,17 +264,17 @@ class FirefoxConnector {
             resolve();
           });
         });
       });
     };
 
     // Reconfigures the tab, optionally triggering a reload.
     const reconfigureTab = options => {
-      return this.tabTarget.activeTab.reconfigure({ options });
+      return this.tabTarget.reconfigure({ options });
     };
 
     // Reconfigures the tab and waits for the target to finish navigating.
     const reconfigureTabAndWaitForNavigation = (options) => {
       options.performReload = true;
       const navigationFinished = waitForNavigation();
       return reconfigureTab(options).then(() => navigationFinished);
     };
--- a/devtools/client/netmonitor/src/har/har-automation.js
+++ b/devtools/client/netmonitor/src/har/har-automation.js
@@ -61,17 +61,16 @@ HarAutomation.prototype = {
   // Automation
 
   startMonitoring: function(client, callback) {
     if (!client) {
       return;
     }
 
     this.debuggerClient = client;
-    this.targetFront = this.toolbox.target.activeTab;
     this.webConsoleClient = this.toolbox.target.activeConsole;
 
     this.tabWatcher = new TabWatcher(this.toolbox, this);
     this.tabWatcher.connect();
   },
 
   pageLoadBegin: function(response) {
     this.resetCollector();
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -139,17 +139,17 @@ function waitForNavigation(target) {
 
 function toggleCache(target, disabled) {
   const options = { cacheDisabled: disabled, performReload: true };
   const navigationFinished = waitForNavigation(target);
 
   // Disable the cache for any toolbox that it is opened from this point on.
   Services.prefs.setBoolPref("devtools.cache.disabled", disabled);
 
-  return target.activeTab.reconfigure({ options }).then(() => navigationFinished);
+  return target.reconfigure({ options }).then(() => navigationFinished);
 }
 
 /**
  * Wait for 2 markers during document load.
  */
 function waitForTimelineMarkers(monitor) {
   return new Promise(resolve => {
     const markers = [];
--- a/devtools/client/performance/test/helpers/actions.js
+++ b/devtools/client/performance/test/helpers/actions.js
@@ -145,11 +145,11 @@ exports.waitForOverviewRenderedWithMarke
     ),
   ]);
 };
 
 /**
  * Reloads the given tab target.
  */
 exports.reload = (target) => {
-  target.activeTab.reload();
+  target.reload();
   return once(target, "navigate");
 };
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -554,17 +554,17 @@ var Scratchpad = {
       console.error(this.strings
                     .GetStringFromName("scratchpadContext.invalid"));
       return;
     }
 
     const target = await TargetFactory.forTab(this.gBrowser.selectedTab);
     await target.attach();
     const onNavigate = target.once("navigate");
-    target.activeTab.reload();
+    target.reload();
     await onNavigate;
     await this.run();
   },
 
   /**
    * Execute the selected text (if any) or the entire editor content in the
    * current context. The evaluation result is inserted into the editor after
    * the selected text, or at the end of the editor content if there is no
--- a/devtools/client/shadereditor/test/head.js
+++ b/devtools/client/shadereditor/test/head.js
@@ -126,23 +126,23 @@ function navigateInHistory(aTarget, aDir
     mm.sendAsyncMessage("devtools:test:history", { direction: aDirection });
   } else {
     executeSoon(() => content.history[aDirection]());
   }
   return once(aTarget, aWaitForTargetEvent);
 }
 
 function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
-  executeSoon(() => aTarget.activeTab.navigateTo({ url: aUrl }));
+  executeSoon(() => aTarget.navigateTo({ url: aUrl }));
   return once(aTarget, aWaitForTargetEvent);
 }
 
 async function reload(aTarget, aWaitForTargetEvent = "navigate") {
   const onTargetEvent = once(aTarget, aWaitForTargetEvent);
-  await aTarget.activeTab.reload();
+  await aTarget.reload();
   return onTargetEvent;
 }
 
 function initBackend(aUrl) {
   info("Initializing a shader editor front.");
 
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
--- a/devtools/client/shared/test/browser_dbg_WorkerTargetActor.attach.js
+++ b/devtools/client/shared/test/browser_dbg_WorkerTargetActor.attach.js
@@ -24,49 +24,48 @@ var WORKER2_URL = "code_WorkerTargetActo
 function test() {
   Task.spawn(function* () {
     const oldMaxTotalViewers = SpecialPowers.getIntPref(MAX_TOTAL_VIEWERS);
     SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, 10);
 
     const tab = yield addTab(TAB1_URL);
     const target = yield TargetFactory.forTab(tab);
     yield target.attach();
-    const targetFront = target.activeTab;
-    yield listWorkers(targetFront);
+    yield listWorkers(target);
 
     // If a page still has pending network requests, it will not be moved into
     // the bfcache. Consequently, we cannot use waitForWorkerListChanged here,
     // because the worker is not guaranteed to have finished loading when it is
     // registered. Instead, we have to wait for the promise returned by
     // createWorker in the tab to be resolved.
     yield createWorkerInTab(tab, WORKER1_URL);
-    let { workers } = yield listWorkers(targetFront);
+    let { workers } = yield listWorkers(target);
     let workerTargetFront1 = findWorker(workers, WORKER1_URL);
     yield workerTargetFront1.attach();
     is(workerTargetFront1.isClosed, false, "worker in tab 1 should not be closed");
 
     executeSoon(() => {
       BrowserTestUtils.loadURI(tab.linkedBrowser, TAB2_URL);
     });
     yield waitForWorkerClose(workerTargetFront1);
     is(workerTargetFront1.isClosed, true, "worker in tab 1 should be closed");
 
     yield createWorkerInTab(tab, WORKER2_URL);
-    ({ workers } = yield listWorkers(targetFront));
+    ({ workers } = yield listWorkers(target));
     const workerTargetFront2 = findWorker(workers, WORKER2_URL);
     yield workerTargetFront2.attach();
     is(workerTargetFront2.isClosed, false, "worker in tab 2 should not be closed");
 
     executeSoon(() => {
       tab.linkedBrowser.goBack();
     });
     yield waitForWorkerClose(workerTargetFront2);
     is(workerTargetFront2.isClosed, true, "worker in tab 2 should be closed");
 
-    ({ workers } = yield listWorkers(targetFront));
+    ({ workers } = yield listWorkers(target));
     workerTargetFront1 = findWorker(workers, WORKER1_URL);
     yield workerTargetFront1.attach();
     is(workerTargetFront1.isClosed, false, "worker in tab 1 should not be closed");
 
     yield target.destroy();
     SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
     finish();
   });
--- a/devtools/client/shared/test/browser_dbg_debugger-statement.js
+++ b/devtools/client/shared/test/browser_dbg_debugger-statement.js
@@ -17,19 +17,18 @@ Services.scriptloader.loadSubScript(
 
 const TAB_URL = TEST_URI_ROOT + "doc_inline-debugger-statement.html";
 
 add_task(async () => {
   const tab = await addTab(TAB_URL);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
   const { client } = target;
-  const targetFront = target.activeTab;
 
-  const threadClient = await testEarlyDebuggerStatement(client, tab, targetFront);
+  const threadClient = await testEarlyDebuggerStatement(client, tab, target);
   await testDebuggerStatement(client, tab, threadClient);
 
   await target.destroy();
 });
 
 async function testEarlyDebuggerStatement(client, tab, targetFront) {
   const onPaused = function(event, packet) {
     ok(false, "Pause shouldn't be called before we've attached!");
--- a/devtools/client/shared/test/browser_dbg_listworkers.js
+++ b/devtools/client/shared/test/browser_dbg_listworkers.js
@@ -20,52 +20,51 @@ Services.scriptloader.loadSubScript(
 var TAB_URL = EXAMPLE_URL + "doc_listworkers-tab.html";
 var WORKER1_URL = "code_listworkers-worker1.js";
 var WORKER2_URL = "code_listworkers-worker2.js";
 
 add_task(async function test() {
   const tab = await addTab(TAB_URL);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
 
-  let { workers } = await listWorkers(targetFront);
+  let { workers } = await listWorkers(target);
   is(workers.length, 0);
 
   executeSoon(() => {
     evalInTab(tab, "var worker1 = new Worker('" + WORKER1_URL + "');");
   });
-  await waitForWorkerListChanged(targetFront);
+  await waitForWorkerListChanged(target);
 
-  ({ workers } = await listWorkers(targetFront));
+  ({ workers } = await listWorkers(target));
   is(workers.length, 1);
   is(workers[0].url, WORKER1_URL);
 
   executeSoon(() => {
     evalInTab(tab, "var worker2 = new Worker('" + WORKER2_URL + "');");
   });
-  await waitForWorkerListChanged(targetFront);
+  await waitForWorkerListChanged(target);
 
-  ({ workers } = await listWorkers(targetFront));
+  ({ workers } = await listWorkers(target));
   is(workers.length, 2);
   is(workers[0].url, WORKER1_URL);
   is(workers[1].url, WORKER2_URL);
 
   executeSoon(() => {
     evalInTab(tab, "worker1.terminate()");
   });
-  await waitForWorkerListChanged(targetFront);
+  await waitForWorkerListChanged(target);
 
-  ({ workers } = await listWorkers(targetFront));
+  ({ workers } = await listWorkers(target));
   is(workers.length, 1);
   is(workers[0].url, WORKER2_URL);
 
   executeSoon(() => {
     evalInTab(tab, "worker2.terminate()");
   });
-  await waitForWorkerListChanged(targetFront);
+  await waitForWorkerListChanged(target);
 
-  ({ workers } = await listWorkers(targetFront));
+  ({ workers } = await listWorkers(target));
   is(workers.length, 0);
 
   await target.destroy();
   finish();
 });
--- a/devtools/client/shared/test/browser_dbg_navigation.js
+++ b/devtools/client/shared/test/browser_dbg_navigation.js
@@ -12,37 +12,36 @@
 const TAB1_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
 const TAB2_FILE = "doc_empty-tab-02.html";
 const TAB2_URL = EXAMPLE_URL + TAB2_FILE;
 
 add_task(async () => {
   const tab = await addTab(TAB1_URL);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
 
-  await testNavigate(targetFront);
+  await testNavigate(target);
   await testDetach(target);
 });
 
-function testNavigate(targetFront) {
+function testNavigate(target) {
   const outstanding = [promise.defer(), promise.defer()];
 
-  targetFront.on("tabNavigated", function onTabNavigated(packet) {
+  target.on("tabNavigated", function onTabNavigated(packet) {
     is(packet.url.split("/").pop(), TAB2_FILE,
       "Got a tab navigation notification.");
 
     info(JSON.stringify(packet));
 
     if (packet.state == "start") {
       ok(true, "Tab started to navigate.");
       outstanding[0].resolve();
     } else {
       ok(true, "Tab finished navigating.");
-      targetFront.off("tabNavigated", onTabNavigated);
+      target.off("tabNavigated", onTabNavigated);
       outstanding[1].resolve();
     }
   });
 
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TAB2_URL);
   return promise.all(outstanding.map(e => e.promise));
 }
 
--- a/devtools/client/shared/test/browser_dbg_target-scoped-actor-01.js
+++ b/devtools/client/shared/test/browser_dbg_target-scoped-actor-01.js
@@ -19,18 +19,17 @@ add_task(async function test() {
     prefix: "testOne",
     constructor: "TestActor1",
     type: { target: true },
   });
 
   const target = await TargetFactory.forTab(tab);
   await target.attach();
   const { client } = target;
-  const targetFront = target.activeTab;
-  const form = targetFront.targetForm;
+  const form = target.targetForm;
 
   await testTargetScopedActor(client, form);
   await removeTab(gBrowser.selectedTab);
   await target.destroy();
 });
 
 async function testTargetScopedActor(client, form) {
   ok(form.testOneActor,
--- a/devtools/client/shared/test/browser_dbg_target-scoped-actor-02.js
+++ b/devtools/client/shared/test/browser_dbg_target-scoped-actor-02.js
@@ -19,18 +19,17 @@ add_task(async function() {
     prefix: "testOne",
     constructor: "TestActor1",
     type: { target: true },
   });
 
   const target = await TargetFactory.forTab(tab);
   await target.attach();
   const { client } = target;
-  const targetFront = target.activeTab;
-  const form = targetFront.targetForm;
+  const form = target.targetForm;
 
   await testTargetScopedActor(client, form);
   await closeTab(client, form);
   await target.destroy();
 });
 
 async function testTargetScopedActor(client, form) {
   ok(form.testOneActor,
--- a/devtools/client/shared/test/browser_dbg_worker-window.js
+++ b/devtools/client/shared/test/browser_dbg_worker-window.js
@@ -13,22 +13,21 @@ const TAB_URL = EXAMPLE_URL + "doc_Worke
 const WORKER_URL = "code_WorkerTargetActor.attachThread-worker.js";
 
 add_task(async function() {
   await pushPrefs(["devtools.scratchpad.enabled", true]);
 
   const tab = await addTab(TAB_URL);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
 
-  await listWorkers(targetFront);
+  await listWorkers(target);
   await createWorkerInTab(tab, WORKER_URL);
 
-  const { workers } = await listWorkers(targetFront);
+  const { workers } = await listWorkers(target);
   const workerTargetFront = findWorker(workers, WORKER_URL);
 
   const toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
                                             "jsdebugger",
                                             Toolbox.HostType.WINDOW);
 
   is(toolbox.hostType, "window", "correct host");
 
--- a/devtools/client/shared/test/helper_workers.js
+++ b/devtools/client/shared/test/helper_workers.js
@@ -171,34 +171,33 @@ function getSplitConsole(toolbox, win) {
   });
 }
 
 async function initWorkerDebugger(TAB_URL, WORKER_URL) {
   const tab = await addTab(TAB_URL);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
   const { client } = target;
-  const targetFront = target.activeTab;
 
   await createWorkerInTab(tab, WORKER_URL);
 
-  const { workers } = await listWorkers(targetFront);
+  const { workers } = await listWorkers(target);
   const workerTargetFront = findWorker(workers, WORKER_URL);
 
   const toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerTargetFront),
                                             "jsdebugger",
                                             Toolbox.HostType.WINDOW);
 
   const debuggerPanel = toolbox.getCurrentPanel();
 
   const gDebugger = debuggerPanel.panelWin;
 
   const context = createDebuggerContext(toolbox);
 
-  return { ...context, client, tab, targetFront, workerTargetFront, toolbox, gDebugger};
+  return { ...context, client, tab, target, workerTargetFront, toolbox, gDebugger};
 }
 
 // Override addTab/removeTab as defined by shared-head, since these have
 // an extra window parameter and add a frame script
 this.addTab = function addTab(url, win) {
   info("Adding tab: " + url);
 
   const deferred = getDeferredPromise().defer();
@@ -236,18 +235,17 @@ this.removeTab = function removeTab(tab,
 
   targetBrowser.removeTab(tab);
   return deferred.promise;
 };
 
 async function attachThreadActorForTab(tab) {
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
-  const [, threadClient] = await targetFront.attachThread();
+  const [, threadClient] = await target.attachThread();
   await threadClient.resume();
   return { client: target.client, threadClient };
 }
 
 function pushPrefs(...aPrefs) {
   const deferred = getDeferredPromise().defer();
   SpecialPowers.pushPrefEnv({"set": aPrefs}, deferred.resolve);
   return deferred.promise;
--- a/devtools/client/webaudioeditor/test/head.js
+++ b/devtools/client/webaudioeditor/test/head.js
@@ -38,22 +38,22 @@ var gToolEnabled = Services.prefs.getBoo
 
 registerCleanupFunction(() => {
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
   Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", gToolEnabled);
   Cu.forceGC();
 });
 
 function reload(aTarget, aWaitForTargetEvent = "navigate") {
-  aTarget.activeTab.reload();
+  aTarget.reload();
   return once(aTarget, aWaitForTargetEvent);
 }
 
 function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
-  executeSoon(() => aTarget.activeTab.navigateTo({ url: aUrl }));
+  executeSoon(() => aTarget.navigateTo({ url: aUrl }));
   return once(aTarget, aWaitForTargetEvent);
 }
 
 /**
  * Adds a new tab, and instantiate a WebAudiFront object.
  * This requires calling removeTab before the test ends.
  */
 function initBackend(aUrl) {
--- a/devtools/client/webconsole/enhancers/css-error-reporting.js
+++ b/devtools/client/webconsole/enhancers/css-error-reporting.js
@@ -24,17 +24,17 @@ function ensureCSSErrorReportingEnabled(
       state = reducer(state, action);
       if (!state.filters.css) {
         return state;
       }
 
       const cssFilterToggled =
         action.type == FILTER_TOGGLE && action.filter == "css";
       if (cssFilterToggled || action.type == INITIALIZE) {
-        proxy.target.activeTab.ensureCSSErrorReportingEnabled();
+        proxy.target.ensureCSSErrorReportingEnabled();
       }
       return state;
     }
     return next(ensureErrorReportingEnhancer, initialState, enhancer);
   };
 }
 
 module.exports = ensureCSSErrorReportingEnabled;
--- a/devtools/client/webconsole/test/components/new-console-output-wrapper.test.js
+++ b/devtools/client/webconsole/test/components/new-console-output-wrapper.test.js
@@ -20,19 +20,17 @@ const WebConsoleOutputWrapper =
 const { messagesAdd } =
   require("devtools/client/webconsole/actions/messages");
 
 async function getWebConsoleOutputWrapper() {
   const hud = {
     proxy: {
       releaseActor: () => {},
       target: {
-        activeTab: {
-          ensureCSSErrorReportingEnabled: () => {},
-        },
+        ensureCSSErrorReportingEnabled: () => {},
       },
     },
   };
 
   const owner = { target: {client: {} } };
   const wcow = new WebConsoleOutputWrapper(null, hud, null, owner);
   await wcow.init();
   return wcow;
--- a/devtools/client/webconsole/test/helpers.js
+++ b/devtools/client/webconsole/test/helpers.js
@@ -40,19 +40,17 @@ function setupStore(input = [], {
   actions,
   hud,
 } = {}) {
   if (!hud) {
     hud = {
       proxy: {
         releaseActor: () => {},
         target: {
-          activeTab: {
-            ensureCSSErrorReportingEnabled: () => {},
-          },
+          ensureCSSErrorReportingEnabled: () => {},
         },
       },
     };
   }
   const store = configureStore(hud, {
     ...storeOptions,
     sessionId: -1,
     telemetry: new Telemetry(),
--- a/devtools/client/webconsole/webconsole-output-wrapper.js
+++ b/devtools/client/webconsole/webconsole-output-wrapper.js
@@ -64,21 +64,21 @@ WebConsoleOutputWrapper.prototype = {
             timeStamp,
           }]));
         },
         hudProxy: hud.proxy,
         openLink: (url, e) => {
           hud.owner.openLink(url, e);
         },
         canRewind: () => {
-          if (!(hud.owner && hud.owner.target && hud.owner.target.activeTab)) {
+          if (!(hud.owner && hud.owner.target && hud.owner.target)) {
             return false;
           }
 
-          return hud.owner.target.activeTab.traits.canRewind;
+          return hud.owner.target.traits.canRewind;
         },
         createElement: nodename => {
           return this.document.createElement(nodename);
         },
         getLongString: (grip) => {
           return hud.proxy.webConsoleClient.getString(grip);
         },
         requestData(id, type) {
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -319,17 +319,17 @@ WebConsole.prototype = {
       this.hudService.consoles.delete(this.hudId);
 
       if (this.ui) {
         await this.ui.destroy();
       }
 
       if (!this._browserConsole) {
         try {
-          await this.target.activeTab.focus();
+          await this.target.focus();
         } catch (ex) {
           // Tab focus can fail if the tab or target is closed.
         }
       }
 
       if (this._parserService) {
         this._parserService.stop();
         this._parserService = null;
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.js
@@ -241,17 +241,17 @@ var AppManager = exports.AppManager = {
     this.selectedProject = null;
   },
 
   reloadTab: function() {
     if (this.selectedProject && this.selectedProject.type != "tab") {
       return Promise.reject("tried to reload non-tab project");
     }
     return this.getTarget().then(target => {
-      target.activeTab.reload();
+      target.reload();
     }, console.error);
   },
 
   getTarget: function() {
     if (this.selectedProject.type == "mainProcess") {
       return this.connection.client.mainRoot.getMainProcess().then(front => {
         return TargetFactory.forRemoteTab({
           activeTab: front,
--- a/devtools/docs/backend/client-api.md
+++ b/devtools/docs/backend/client-api.md
@@ -94,17 +94,17 @@ The debugger client will send event noti
 
 When the user navigates away from a page, a `tabNavigated` event will be fired. The proper way to handle this event is to detach from the previous thread and tab and attach to the new ones:
 
 ```javascript
 async function onTab() {
   // Detach from the previous thread.
   await client.activeThread.detach();
   // Detach from the previous tab.
-  await targetFront.activeTab.detach();
+  await targetFront.detach();
   // Start debugging the new tab.
   start();
 }
 ```
 
 ## Debugging JavaScript running in a browser tab
 
 Once the application is attached to a tab, it can attach to its thread in order to interact with the JavaScript debugger:
@@ -204,17 +204,17 @@ function debugTab() {
 
 /**
  * Handler for location changes.
  */
 function onTab() {
   // Detach from the previous thread.
   client.activeThread.detach(() => {
     // Detach from the previous tab.
-    client.activeTab.detach(() => {
+    client.detach(() => {
       // Start debugging the new tab.
       debugTab();
     });
   });
 }
 
 /**
  * Handler for entering pause state.
--- a/devtools/server/tests/browser/browser_navigateEvents.js
+++ b/devtools/server/tests/browser/browser_navigateEvents.js
@@ -93,19 +93,18 @@ Services.obs.addObserver(httpObserver, "
 
 function onMessage({ data }) {
   assertEvent(data.event, data.data);
 }
 
 async function connectAndAttachTab(tab) {
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
-  const actorID = targetFront.targetForm.actor;
-  targetFront.on("tabNavigated", function(packet) {
+  const actorID = target.targetForm.actor;
+  target.on("tabNavigated", function(packet) {
     assertEvent("tabNavigated", packet);
   });
   return { target, actorID };
 }
 
 add_task(async function() {
   // Open a test tab
   const browser = await addTab(URL1);
--- a/devtools/server/tests/browser/browser_spawn_actor_in_parent.js
+++ b/devtools/server/tests/browser/browser_spawn_actor_in_parent.js
@@ -20,19 +20,18 @@ add_task(async function() {
     prefix: "inContent",
     constructor: "InContentActor",
     type: { target: true },
   });
 
   const tab = gBrowser.getTabForBrowser(browser);
   const target = await TargetFactory.forTab(tab);
   await target.attach();
-  const targetFront = target.activeTab;
   const { client } = target;
-  const form = targetFront.targetForm;
+  const form = target.targetForm;
 
   // As this Front isn't instantiated by protocol.js, we have to manually
   // set its actor ID and manage it:
   const inContentFront = new InContentFront(client);
   inContentFront.actorID = form.inContentActor;
   inContentFront.manage(inContentFront);
 
   const isInContent = await inContentFront.isInContent();
--- a/devtools/server/tests/browser/browser_webextension_inspected_window.js
+++ b/devtools/server/tests/browser/browser_webextension_inspected_window.js
@@ -22,40 +22,39 @@ async function setup(pageUrl) {
     addonId: extension.id,
   };
 
   const target = await addTabTarget(pageUrl);
 
   await target.attach();
 
   const { client } = target;
-  const targetFront = target.activeTab;
   const consoleClient = target.activeConsole;
   const inspectedWindowFront = await target.getFront("webExtensionInspectedWindow");
 
   return {
     client,
-    targetFront, consoleClient,
+    target, consoleClient,
     inspectedWindowFront,
     extension, fakeExtCallerInfo,
   };
 }
 
 async function teardown({client, extension}) {
   await client.close();
   DebuggerServer.destroy();
   gBrowser.removeCurrentTab();
   await extension.unload();
 }
 
-function waitForNextTabNavigated(targetFront) {
+function waitForNextTabNavigated(target) {
   return new Promise(resolve => {
-    targetFront.on("tabNavigated", function tabNavigatedListener(pkt) {
+    target.on("tabNavigated", function tabNavigatedListener(pkt) {
       if (pkt.state == "stop" && !pkt.isFrameSwitching) {
-        targetFront.off("tabNavigated", tabNavigatedListener);
+        target.off("tabNavigated", tabNavigatedListener);
         resolve();
       }
     });
   });
 }
 
 // Script used as the injectedScript option in the inspectedWindow.reload tests.
 function injectedScript() {
@@ -216,108 +215,108 @@ add_task(async function test_exception_i
      "Got the expected stack trace in the exception message");
 
   await teardown({client, extension});
 });
 
 add_task(async function test_exception_inspectedWindowReload() {
   const {
     client, consoleClient, inspectedWindowFront,
-    extension, fakeExtCallerInfo, targetFront,
+    extension, fakeExtCallerInfo, target,
   } = await setup(`${TEST_RELOAD_URL}?test=cache`);
 
   // Test reload with bypassCache=false.
 
-  const waitForNoBypassCacheReload = waitForNextTabNavigated(targetFront);
+  const waitForNoBypassCacheReload = waitForNextTabNavigated(target);
   const reloadResult = await inspectedWindowFront.reload(fakeExtCallerInfo,
                                                          {ignoreCache: false});
 
   ok(!reloadResult, "Got the expected undefined result from inspectedWindow reload");
 
   await waitForNoBypassCacheReload;
 
   const noBypassCacheEval = await consoleClient.evaluateJS("document.body.textContent");
 
   is(noBypassCacheEval.result, "empty cache headers",
      "Got the expected result with reload forceBypassCache=false");
 
   // Test reload with bypassCache=true.
 
-  const waitForForceBypassCacheReload = waitForNextTabNavigated(targetFront);
+  const waitForForceBypassCacheReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo, {ignoreCache: true});
 
   await waitForForceBypassCacheReload;
 
   const forceBypassCacheEval =
     await consoleClient.evaluateJS("document.body.textContent");
 
   is(forceBypassCacheEval.result, "no-cache:no-cache",
      "Got the expected result with reload forceBypassCache=true");
 
   await teardown({client, extension});
 });
 
 add_task(async function test_exception_inspectedWindowReload_customUserAgent() {
   const {
     client, consoleClient, inspectedWindowFront,
-    extension, fakeExtCallerInfo, targetFront,
+    extension, fakeExtCallerInfo, target,
   } = await setup(`${TEST_RELOAD_URL}?test=user-agent`);
 
   // Test reload with custom userAgent.
 
-  const waitForCustomUserAgentReload = waitForNextTabNavigated(targetFront);
+  const waitForCustomUserAgentReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo,
                                     {userAgent: "Customized User Agent"});
 
   await waitForCustomUserAgentReload;
 
   const customUserAgentEval = await consoleClient.evaluateJS("document.body.textContent");
 
   is(customUserAgentEval.result, "Customized User Agent",
      "Got the expected result on reload with a customized userAgent");
 
   // Test reload with no custom userAgent.
 
-  const waitForNoCustomUserAgentReload = waitForNextTabNavigated(targetFront);
+  const waitForNoCustomUserAgentReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo, {});
 
   await waitForNoCustomUserAgentReload;
 
   const noCustomUserAgentEval =
     await consoleClient.evaluateJS("document.body.textContent");
 
   is(noCustomUserAgentEval.result, window.navigator.userAgent,
      "Got the expected result with reload without a customized userAgent");
 
   await teardown({client, extension});
 });
 
 add_task(async function test_exception_inspectedWindowReload_injectedScript() {
   const {
     client, consoleClient, inspectedWindowFront,
-    extension, fakeExtCallerInfo, targetFront,
+    extension, fakeExtCallerInfo, target,
   } = await setup(`${TEST_RELOAD_URL}?test=injected-script&frames=3`);
 
   // Test reload with an injectedScript.
 
-  const waitForInjectedScriptReload = waitForNextTabNavigated(targetFront);
+  const waitForInjectedScriptReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo,
                                     {injectedScript: `new ${injectedScript}`});
   await waitForInjectedScriptReload;
 
   const injectedScriptEval = await consoleClient.evaluateJS(`(${collectEvalResults})()`);
 
   const expectedResult = (new Array(5)).fill("injected script executed first");
 
   SimpleTest.isDeeply(JSON.parse(injectedScriptEval.result), expectedResult,
      "Got the expected result on reload with an injected script");
 
   // Test reload without an injectedScript.
 
-  const waitForNoInjectedScriptReload = waitForNextTabNavigated(targetFront);
+  const waitForNoInjectedScriptReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo, {});
   await waitForNoInjectedScriptReload;
 
   const noInjectedScriptEval =
     await consoleClient.evaluateJS(`(${collectEvalResults})()`);
 
   const newExpectedResult = (new Array(5)).fill("injected script NOT executed");
 
@@ -325,67 +324,67 @@ add_task(async function test_exception_i
                       "Got the expected result on reload with no injected script");
 
   await teardown({client, extension});
 });
 
 add_task(async function test_exception_inspectedWindowReload_multiple_calls() {
   const {
     client, consoleClient, inspectedWindowFront,
-    extension, fakeExtCallerInfo, targetFront,
+    extension, fakeExtCallerInfo, target,
   } = await setup(`${TEST_RELOAD_URL}?test=user-agent`);
 
   // Test reload with custom userAgent three times (and then
   // check that only the first one has affected the page reload.
 
-  const waitForCustomUserAgentReload = waitForNextTabNavigated(targetFront);
+  const waitForCustomUserAgentReload = waitForNextTabNavigated(target);
 
   inspectedWindowFront.reload(fakeExtCallerInfo, {userAgent: "Customized User Agent 1"});
   inspectedWindowFront.reload(fakeExtCallerInfo, {userAgent: "Customized User Agent 2"});
 
   await waitForCustomUserAgentReload;
 
   const customUserAgentEval = await consoleClient.evaluateJS("document.body.textContent");
 
   is(customUserAgentEval.result, "Customized User Agent 1",
      "Got the expected result on reload with a customized userAgent");
 
   // Test reload with no custom userAgent.
 
-  const waitForNoCustomUserAgentReload = waitForNextTabNavigated(targetFront);
+  const waitForNoCustomUserAgentReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo, {});
 
   await waitForNoCustomUserAgentReload;
 
   const noCustomUserAgentEval =
     await consoleClient.evaluateJS("document.body.textContent");
 
   is(noCustomUserAgentEval.result, window.navigator.userAgent,
      "Got the expected result with reload without a customized userAgent");
 
   await teardown({client, extension});
 });
 
 add_task(async function test_exception_inspectedWindowReload_stopped() {
   const {
     client, consoleClient, inspectedWindowFront,
-    extension, fakeExtCallerInfo, targetFront,
+    extension, fakeExtCallerInfo, target,
   } = await setup(`${TEST_RELOAD_URL}?test=injected-script&frames=3`);
 
   // Test reload on a page that calls window.stop() immediately during the page loading
 
-  const waitForPageLoad = waitForNextTabNavigated(targetFront);
+  const waitForPageLoad = waitForNextTabNavigated(target);
   await inspectedWindowFront.eval(fakeExtCallerInfo,
                                   "window.location += '&stop=windowStop'");
 
   info("Load a webpage that calls 'window.stop()' while is still loading");
   await waitForPageLoad;
 
   info("Starting a reload with an injectedScript");
-  const waitForInjectedScriptReload = waitForNextTabNavigated(targetFront);
+  const waitForInjectedScriptReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo,
                                     {injectedScript: `new ${injectedScript}`});
   await waitForInjectedScriptReload;
 
   const injectedScriptEval =
     await consoleClient.evaluateJS(`(${collectEvalResults})()`);
 
   // The page should have stopped during the reload and only one injected script
@@ -393,17 +392,17 @@ add_task(async function test_exception_i
   const expectedResult = (new Array(1)).fill("injected script executed first");
 
   SimpleTest.isDeeply(JSON.parse(injectedScriptEval.result), expectedResult,
      "The injected script has been executed on the 'stopped' page reload");
 
   // Reload again with no options.
 
   info("Reload the tab again without any reload options");
-  const waitForNoInjectedScriptReload = waitForNextTabNavigated(targetFront);
+  const waitForNoInjectedScriptReload = waitForNextTabNavigated(target);
   await inspectedWindowFront.reload(fakeExtCallerInfo, {});
   await waitForNoInjectedScriptReload;
 
   const noInjectedScriptEval =
     await consoleClient.evaluateJS(`(${collectEvalResults})()`);
 
   // The page should have stopped during the reload and no injected script should
   // have been executed during this second reload (or it would mean that the previous
--- a/devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
+++ b/devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
@@ -51,22 +51,21 @@ async function test_connect_addon(oopMod
   });
   is(addonTarget.targetForm.isOOP, oopMode,
      "Got the expected oop mode in the webextension actor form");
   const frames = await waitForFramesUpdated(addonTarget);
   const backgroundPageFrame = frames.filter((frame) => {
     return frame.url && frame.url.endsWith("/_generated_background_page.html");
   }).pop();
   is(backgroundPageFrame.addonID, extension.id, "Got an extension frame");
-  ok(addonTarget.activeTab, "The addon target has an activeTab");
 
   // When running in oop mode we can explicitly attach the thread without locking
   // the main process.
   if (oopMode) {
-    const [, threadFront] = await addonTarget.activeTab.attachThread();
+    const [, threadFront] = await addonTarget.attachThread();
 
     ok(threadFront, "Got a threadFront for the target addon");
     is(threadFront.paused, true, "The addon threadActor is paused");
     await threadFront.resume();
     is(threadFront.paused, false, "The addon threadActor has been resumed");
 
     await threadFront.detach();
   }
--- a/devtools/server/tests/mochitest/webextension-helpers.js
+++ b/devtools/server/tests/mochitest/webextension-helpers.js
@@ -55,20 +55,20 @@ function waitForFramesUpdated(target, ma
   return new Promise(resolve => {
     const listener = data => {
       if (typeof matchFn === "function" && !matchFn(data)) {
         return;
       } else if (!data.frames) {
         return;
       }
 
-      target.activeTab.off("frameUpdate", listener);
+      target.off("frameUpdate", listener);
       resolve(data.frames);
     };
-    target.activeTab.on("frameUpdate", listener);
+    target.on("frameUpdate", listener);
   });
 }
 
 function collectFrameUpdates({client}, matchFn) {
   const collected = [];
 
   const listener = (evt, data) => {
     if (matchFn(data)) {
--- a/devtools/shared/webconsole/test/common.js
+++ b/devtools/shared/webconsole/test/common.js
@@ -79,17 +79,17 @@ var _attachConsole = async function(
         client,
         activeTab: targetFront,
       });
       if (attachToWorker) {
         const workerName = "console-test-worker.js#" + new Date().getTime();
         worker = new Worker(workerName);
         await waitForMessage(worker);
 
-        const { workers } = await target.activeTab.listWorkers();
+        const { workers } = await target.listWorkers();
         const workerTargetFront = workers.filter(w => w.url == workerName)[0];
         if (!workerTargetFront) {
           console.error("listWorkers failed. Unable to find the worker actor\n");
           return null;
         }
         target = await TargetFactory.forRemoteTab({
           client,
           activeTab: workerTargetFront,