Bug 1172897 - Rename TabActor to BrowsingContextTargetActor. r=ochameau draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 25 May 2018 18:20:28 -0500
changeset 805432 c99c7454fa7761d37073c0fa81d6e3694d0750ed
parent 805204 199a085199815cc99daa658956a7c9436e1d436b
child 805433 59bc2e8c70dc0f7da6bdfbef52cc2647679f077d
push id112656
push userbmo:jryans@gmail.com
push dateThu, 07 Jun 2018 20:15:26 +0000
reviewersochameau
bugs1172897
milestone62.0a1
Bug 1172897 - Rename TabActor to BrowsingContextTargetActor. r=ochameau MozReview-Commit-ID: LPTEx2h4F1o
devtools/client/aboutdebugging/modules/addon.js
devtools/client/debugger/debugger-controller.js
devtools/client/debugger/test/mochitest/head.js
devtools/client/framework/ToolboxProcess.jsm
devtools/client/framework/attach-thread.js
devtools/client/framework/connect/connect.js
devtools/client/framework/devtools-browser.js
devtools/client/framework/target-from-url.js
devtools/client/framework/target.js
devtools/client/framework/test/browser_target_from_url.js
devtools/client/framework/test/browser_toolbox_target.js
devtools/client/framework/toolbox-process-window.js
devtools/client/framework/toolbox.js
devtools/client/inspector/shared/tooltips-overlay.js
devtools/client/shared/test/test-actor-registry.js
devtools/client/shared/test/test-actor.js
devtools/client/webconsole/hudservice.js
devtools/client/webconsole/webconsole-connection-proxy.js
devtools/client/webide/modules/app-manager.js
devtools/docs/backend/actor-best-practices.md
devtools/docs/backend/actor-hierarchy.md
devtools/docs/backend/actor-registration.md
devtools/docs/backend/protocol.md
devtools/docs/tools/highlighters.md
devtools/server/actors/accessibility.js
devtools/server/actors/addon-console.js
devtools/server/actors/addon.js
devtools/server/actors/animation.js
devtools/server/actors/call-watcher.js
devtools/server/actors/canvas.js
devtools/server/actors/canvas/primitive.js
devtools/server/actors/chrome.js
devtools/server/actors/common.js
devtools/server/actors/content.js
devtools/server/actors/csscoverage.js
devtools/server/actors/emulation.js
devtools/server/actors/framerate.js
devtools/server/actors/gcli.js
devtools/server/actors/highlighters.js
devtools/server/actors/inspector/inspector.js
devtools/server/actors/inspector/node.js
devtools/server/actors/inspector/walker.js
devtools/server/actors/layout.js
devtools/server/actors/moz.build
devtools/server/actors/performance.js
devtools/server/actors/promises.js
devtools/server/actors/reflow.js
devtools/server/actors/root.js
devtools/server/actors/storage.js
devtools/server/actors/styles.js
devtools/server/actors/stylesheets.js
devtools/server/actors/tab.js
devtools/server/actors/targets/browsing-context.js
devtools/server/actors/targets/moz.build
devtools/server/actors/thread.js
devtools/server/actors/timeline.js
devtools/server/actors/utils/walker-search.js
devtools/server/actors/webaudio.js
devtools/server/actors/webconsole.js
devtools/server/actors/webextension-inspected-window.js
devtools/server/actors/webextension.js
devtools/server/actors/webgl.js
devtools/server/actors/window.js
devtools/server/main.js
devtools/server/performance/framerate.js
devtools/server/performance/recorder.js
devtools/server/performance/timeline.js
devtools/server/tests/browser/browser_navigateEvents.js
devtools/server/tests/browser/head.js
devtools/server/tests/mochitest/chrome.ini
devtools/server/tests/mochitest/test_connectToFrame.html
devtools/server/tests/mochitest/test_inspector_getNodeFromActor.html
devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
devtools/server/tests/mochitest/webextension-helpers.js
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/test_dbgactor.js
devtools/server/tests/unit/test_layout-reflows-observer.js
devtools/server/tests/unit/test_promises_actor_attach.js
devtools/server/tests/unit/test_promises_actor_exist.js
devtools/server/tests/unit/test_promises_actor_list_promises.js
devtools/server/tests/unit/test_promises_actor_onnewpromise.js
devtools/server/tests/unit/test_promises_actor_onpromisesettled.js
devtools/server/tests/unit/test_promises_object_creationtimestamp.js
devtools/server/tests/unit/test_promises_object_timetosettle-01.js
devtools/server/tests/unit/test_promises_object_timetosettle-02.js
devtools/server/tests/unit/test_register_actor.js
devtools/shared/client/debugger-client.js
devtools/shared/client/property-iterator-client.js
devtools/shared/client/root-client.js
devtools/shared/client/symbol-iterator-client.js
devtools/shared/content-observer.js
devtools/shared/protocol.js
devtools/shared/specs/index.js
devtools/shared/specs/moz.build
devtools/shared/specs/tab.js
devtools/shared/specs/targets/browsing-context.js
devtools/shared/specs/targets/moz.build
devtools/shared/tests/unit/test_protocol_index.js
devtools/shared/webconsole/network-monitor.js
--- a/devtools/client/aboutdebugging/modules/addon.js
+++ b/devtools/client/aboutdebugging/modules/addon.js
@@ -55,17 +55,17 @@ exports.debugLocalAddon = async function
 exports.debugRemoteAddon = async function(addonForm, client) {
   // Close previous addon debugging toolbox.
   closeToolbox();
 
   const options = {
     form: addonForm,
     chrome: true,
     client,
-    isTabActor: addonForm.isWebExtension
+    isBrowsingContext: addonForm.isWebExtension
   };
 
   const target = await TargetFactory.forRemoteTab(options);
 
   const hostType = Toolbox.HostType.WINDOW;
   remoteAddonToolbox = await gDevTools.showToolbox(target, null, hostType);
   remoteAddonToolbox.once("destroy", () => {
     remoteAddonToolbox = null;
--- a/devtools/client/debugger/debugger-controller.js
+++ b/devtools/client/debugger/debugger-controller.js
@@ -247,17 +247,17 @@ var DebuggerController = {
   shutdownDebugger: Task.async(function* () {
     if (this._shutdown) {
       return;
     }
 
     DebuggerView.destroy();
     this.StackFrames.disconnect();
     this.ThreadState.disconnect();
-    if (this._target.isTabActor) {
+    if (this._target.isBrowsingContext) {
       this.Workers.disconnect();
     }
 
     this.disconnect();
 
     this._shutdown = true;
   }),
 
@@ -304,17 +304,17 @@ var DebuggerController = {
       newSource(packet.source);
 
       // Make sure the events listeners are up to date.
       if (DebuggerView.instrumentsPaneTab == "events-tab") {
         fetchEventListeners();
       }
     });
 
-    if (this._target.isTabActor) {
+    if (this._target.isBrowsingContext) {
       this.Workers.connect();
     }
     this.ThreadState.connect();
     this.StackFrames.connect();
 
     // Load all of the sources. Note that the server will actually
     // emit individual `newSource` notifications, which trigger
     // separate actions, so this won't do anything other than force
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -646,17 +646,17 @@ AddonDebugger.prototype = {
     yield this.client.connect();
 
     let addonActor = yield getAddonActorForId(this.client, aAddonId);
 
     let targetOptions = {
       form: addonActor,
       client: this.client,
       chrome: true,
-      isTabActor: false
+      isBrowsingContext: false
     };
 
     let toolboxOptions = {
       customIframe: this.frame
     };
 
     this.target = TargetFactory.forTab(targetOptions);
     let toolbox = yield gDevTools.showToolbox(this.target, "jsdebugger", Toolbox.HostType.CUSTOM, toolboxOptions);
--- a/devtools/client/framework/ToolboxProcess.jsm
+++ b/devtools/client/framework/ToolboxProcess.jsm
@@ -153,17 +153,17 @@ BrowserToolboxProcess.prototype = {
     const { DebuggerServer } = this.loader.require("devtools/server/main");
     this.debuggerServer = DebuggerServer;
     dumpn("Created a separate loader instance for the DebuggerServer.");
 
     // Forward interesting events.
     this.debuggerServer.on("connectionchange", this._onConnectionChange);
 
     this.debuggerServer.init();
-    // We mainly need a root actor and tab actors for opening a toolbox, even
+    // We mainly need a root actor and target actors for opening a toolbox, even
     // against chrome/content/addon. But the "no auto hide" button uses the
     // preference actor, so also register the browser actors.
     this.debuggerServer.registerAllActors();
     this.debuggerServer.allowChromeProcess = true;
     dumpn("initialized and added the browser actors for the DebuggerServer.");
 
     const chromeDebuggingWebSocket =
       Services.prefs.getBoolPref("devtools.debugger.chrome-debugging-websocket");
--- a/devtools/client/framework/attach-thread.js
+++ b/devtools/client/framework/attach-thread.js
@@ -91,17 +91,17 @@ function attachThread(toolbox) {
           box.PRIORITY_WARNING_HIGH
         );
       }
 
       deferred.resolve(threadClient);
     });
   };
 
-  if (target.isTabActor) {
+  if (target.isBrowsingContext) {
     // Attaching a tab, a browser process, or a WebExtensions add-on.
     target.activeTab.attachThread(threadOptions, handleResponse);
   } else if (target.isAddon) {
     // Attaching a legacy addon.
     target.client.attachAddon(actor, res => {
       target.client.attachThread(res.threadActor, handleResponse);
     });
   } else {
--- a/devtools/client/framework/connect/connect.js
+++ b/devtools/client/framework/connect/connect.js
@@ -117,17 +117,17 @@ var onConnectionReady = async function([
   // Add one entry for each open tab.
   for (let i = 0; i < response.tabs.length; i++) {
     buildTabLink(response.tabs[i], parent, i == response.selected);
   }
 
   const gParent = document.getElementById("globalActors");
 
   // Build the Remote Process button
-  // If Fx<39, tab actors were used to be exposed on RootActor
+  // If Fx<39, chrome target actors were used to be exposed on RootActor
   // but in Fx>=39, chrome is debuggable via getProcess() and ChromeActor
   if (globals.consoleActor || gClient.mainRoot.traits.allowChromeProcess) {
     const a = document.createElement("a");
     a.onclick = function() {
       if (gClient.mainRoot.traits.allowChromeProcess) {
         gClient.getProcess()
                .then(aResponse => {
                  openToolbox(aResponse.form, true);
@@ -158,18 +158,18 @@ var onConnectionReady = async function([
 };
 
 /**
  * Build one button for an add-on actor.
  */
 function buildAddonLink(addon, parent) {
   const a = document.createElement("a");
   a.onclick = async function() {
-    const isTabActor = addon.isWebExtension;
-    openToolbox(addon, true, "webconsole", isTabActor);
+    const isBrowsingContext = addon.isWebExtension;
+    openToolbox(addon, true, "webconsole", isBrowsingContext);
   };
 
   a.textContent = addon.name;
   a.title = addon.id;
   a.href = "#";
 
   parent.appendChild(a);
 }
@@ -218,22 +218,22 @@ function showError(type) {
 function handleConnectionTimeout() {
   showError("timeout");
 }
 
 /**
  * The user clicked on one of the buttons.
  * Opens the toolbox.
  */
-function openToolbox(form, chrome = false, tool = "webconsole", isTabActor) {
+function openToolbox(form, chrome = false, tool = "webconsole", isBrowsingContext) {
   const options = {
     form: form,
     client: gClient,
     chrome: chrome,
-    isTabActor: isTabActor
+    isBrowsingContext: isBrowsingContext
   };
   TargetFactory.forRemoteTab(options).then((target) => {
     const hostType = Toolbox.HostType.WINDOW;
     gDevTools.showToolbox(target, tool, hostType).then((toolbox) => {
       toolbox.once("destroyed", function() {
         gClient.close();
       });
     }, console.error);
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -312,17 +312,17 @@ var gDevToolsBrowser = exports.gDevTools
     const deferred = defer();
     client.connect().then(() => {
       client.getProcess(processId)
             .then(response => {
               const options = {
                 form: response.form,
                 client: client,
                 chrome: true,
-                isTabActor: false
+                isBrowsingContext: false
               };
               return TargetFactory.forRemoteTab(options);
             })
             .then(target => {
               // Ensure closing the connection in order to cleanup
               // the debugger client and also the server created in the
               // content process
               target.on("close", () => {
--- a/devtools/client/framework/target-from-url.js
+++ b/devtools/client/framework/target-from-url.js
@@ -16,17 +16,17 @@ const { DebuggerClient } = require("devt
  * - type: tab, process, window
  *      {String} The type of target to connect to.
  *
  * If type == "tab":
  * - id:
  *      {Number} the tab outerWindowID
  * - chrome: Optional
  *      {Boolean} Force the creation of a chrome target. Gives more privileges to
- *      the tab actor. Allows chrome execution in the webconsole and see chrome
+ *      the target actor. Allows chrome execution in the webconsole and see chrome
  *      files in the debugger. (handy when contributing to firefox)
  *
  * If type == "process":
  * - id:
  *      {Number} the process id to debug. Default to 0, which is the parent process.
  *
  * If type == "window":
  * - id:
@@ -46,17 +46,17 @@ exports.targetFromURL = async function t
   if (!type) {
     throw new Error("targetFromURL, missing type parameter");
   }
   let id = params.get("id");
   // Allows to spawn a chrome enabled target for any context
   // (handy to debug chrome stuff in a child process)
   let chrome = params.has("chrome");
 
-  let form, isTabActor;
+  let form, isBrowsingContext;
   if (type === "tab") {
     // Fetch target for a remote tab
     id = parseInt(id, 10);
     if (isNaN(id)) {
       throw new Error(`targetFromURL, wrong tab id '${id}', should be a number`);
     }
     try {
       const response = await client.getTab({ outerWindowID: id });
@@ -74,18 +74,20 @@ exports.targetFromURL = async function t
       id = parseInt(id, 10);
       if (isNaN(id)) {
         id = 0;
       }
       const response = await client.getProcess(id);
       form = response.form;
       chrome = true;
       if (id != 0) {
-        // Child process are not exposing tab actors and only support debugger+console
-        isTabActor = false;
+        // Child processes are not exposing browsing context target actors with the full
+        // set of tab-scoped actors we would get from a browser tab. Instead, they only
+        // support debugger and console.
+        isBrowsingContext = false;
       }
     } catch (ex) {
       if (ex.error == "noProcess") {
         throw new Error(`targetFromURL, process with id '${id}' doesn't exist`);
       }
       throw ex;
     }
   } else if (type == "window") {
@@ -106,17 +108,17 @@ exports.targetFromURL = async function t
         throw new Error(`targetFromURL, window with id '${id}' doesn't exist`);
       }
       throw ex;
     }
   } else {
     throw new Error(`targetFromURL, unsupported type '${type}' parameter`);
   }
 
-  return TargetFactory.forRemoteTab({ client, form, chrome, isTabActor });
+  return TargetFactory.forRemoteTab({ client, form, chrome, isBrowsingContext });
 };
 
 /**
  * Create a DebuggerClient for a given URL object having various query parameters:
  *
  * host:
  *    {String} The hostname or IP address to connect to.
  * port:
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -128,21 +128,21 @@ function TabTarget(tab) {
   } else {
     this._form = tab.form;
     this._url = this._form.url;
     this._title = this._form.title;
 
     this._client = tab.client;
     this._chrome = tab.chrome;
   }
-  // Default isTabActor to true if not explicitly specified
-  if (typeof tab.isTabActor == "boolean") {
-    this._isTabActor = tab.isTabActor;
+  // Default isBrowsingContext to true if not explicitly specified
+  if (typeof tab.isBrowsingContext == "boolean") {
+    this._isBrowsingContext = tab.isBrowsingContext;
   } else {
-    this._isTabActor = true;
+    this._isBrowsingContext = true;
   }
 }
 
 exports.TabTarget = TabTarget;
 
 TabTarget.prototype = {
   /**
    * Returns a promise for the protocol description from the root actor. Used
@@ -303,21 +303,23 @@ TabTarget.prototype = {
   // Tells us if we are debugging content document
   // or if we are debugging chrome stuff.
   // Allows to controls which features are available against
   // a chrome or a content document.
   get chrome() {
     return this._chrome;
   },
 
-  // Tells us if the related actor implements TabActor interface
-  // and requires to call `attach` request before being used
-  // and `detach` during cleanup
-  get isTabActor() {
-    return this._isTabActor;
+  // Tells us if the related actor implements BrowsingContextTargetActor
+  // interface and requires to call `attach` request before being used and
+  // `detach` during cleanup.
+  // TODO: This flag is quite confusing, try to find a better way.
+  // Bug 1465635 hopes to blow up these classes entirely.
+  get isBrowsingContext() {
+    return this._isBrowsingContext;
   },
 
   get window() {
     // XXX - this is a footgun for e10s - there .contentWindow will be null,
     // and even though .contentWindowAsCPOW *might* work, it will not work
     // in all contexts.  Consumers of .window need to be refactored to not
     // rely on this.
     if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
@@ -414,22 +416,22 @@ TabTarget.prototype = {
       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) {
       // The addonActor form is related to a WebExtensionParentActor instance,
-      // which isn't a tab 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 TabActor instance, we call its "connect" method,
-      // (which fetches the TabActor form from a WebExtensionChildActor 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 WebExtensionChildActor instance).
       const {form} = await this._client.request({
         to: this._form.actor, type: "connect",
       });
 
       this._form = form;
       this._url = form.url;
       this._title = form.title;
     }
@@ -471,23 +473,23 @@ TabTarget.prototype = {
         .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 => this._remote.reject(e));
-    } else if (this.isTabActor) {
+    } else 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 inherits from
-      // TabActor and doesn't need to be attached.
+      // AddonActor and chrome debugging on RootActor doesn't inherit from
+      // BrowsingContextTargetActor and doesn't need to be attached.
       attachConsole();
     }
 
     return this._remote.promise;
   },
 
   /**
    * Listen to the different events.
@@ -767,17 +769,17 @@ function WorkerTarget(workerClient) {
  * possible. This allows us to debug workers as if they were ordinary tabs,
  * requiring only minimal changes to the rest of the frontend.
  */
 WorkerTarget.prototype = {
   get isRemote() {
     return true;
   },
 
-  get isTabActor() {
+  get isBrowsingContext() {
     return true;
   },
 
   get name() {
     return "Worker";
   },
 
   get url() {
--- a/devtools/client/framework/test/browser_target_from_url.js
+++ b/devtools/client/framework/test/browser_target_from_url.js
@@ -14,17 +14,17 @@ SimpleTest.registerCleanupFunction(() =>
   Services.prefs.clearUserPref("devtools.debugger.remote-enabled");
   Services.prefs.clearUserPref("devtools.debugger.prompt-connection");
 });
 
 function assertIsTabTarget(target, url, chrome = false) {
   is(target.url, url);
   is(target.isLocalTab, false);
   is(target.chrome, chrome);
-  is(target.isTabActor, true);
+  is(target.isBrowsingContext, true);
   is(target.isRemote, true);
 }
 
 add_task(async function() {
   const tab = await addTab(TEST_URI);
   const browser = tab.linkedBrowser;
   let target;
 
@@ -39,17 +39,17 @@ add_task(async function() {
   info("Test browser window");
   let windowId = window.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDOMWindowUtils)
                        .outerWindowID;
   target = await targetFromURL(new URL("http://foo?type=window&id=" + windowId));
   is(target.url, window.location.href);
   is(target.isLocalTab, false);
   is(target.chrome, true);
-  is(target.isTabActor, true);
+  is(target.isBrowsingContext, true);
   is(target.isRemote, true);
 
   info("Test tab");
   windowId = browser.outerWindowID;
   target = await targetFromURL(new URL("http://foo?type=tab&id=" + windowId));
   assertIsTabTarget(target, TEST_URI);
 
   info("Test tab with chrome privileges");
--- a/devtools/client/framework/test/browser_toolbox_target.js
+++ b/devtools/client/framework/test/browser_toolbox_target.js
@@ -44,17 +44,17 @@ add_task(async function() {
 
   // 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;
   info("Toolbox destroyed");
 
   // Also wait for tabDetached. Toolbox destroys the Target which calls
-  // TabActor.detach(). But Target doesn't wait for detach's end to resolve.
-  // Whereas it is quite important as it is a significant part of toolbox
-  // cleanup. If we do not wait for it and starts removing debugged document,
-  // the actor is still considered as being attached and continues processing
-  // events.
+  // BrowsingContextTargetActor.detach(). But Target doesn't wait for detach's
+  // end to resolve. Whereas it is quite important as it is a significant part
+  // of toolbox cleanup. If we do not wait for it and starts removing debugged
+  // document, the actor is still considered as being attached and continues
+  // processing events.
   await onTabActorDetached;
 
   iframe.remove();
 });
--- a/devtools/client/framework/toolbox-process-window.js
+++ b/devtools/client/framework/toolbox-process-window.js
@@ -78,18 +78,18 @@ var connect = async function() {
   gClient = new DebuggerClient(transport);
   appendStatusMessage("Start protocol client for connection");
   await gClient.connect();
 
   appendStatusMessage("Get root form for toolbox");
   if (addonID) {
     const { addons } = await gClient.listAddons();
     const addonActor = addons.filter(addon => addon.id === addonID).pop();
-    const isTabActor = addonActor.isWebExtension;
-    await openToolbox({form: addonActor, chrome: true, isTabActor});
+    const isBrowsingContext = addonActor.isWebExtension;
+    await openToolbox({form: addonActor, chrome: true, isBrowsingContext});
   } else {
     const response = await gClient.getProcess();
     await openToolbox({form: response.form, chrome: true});
   }
 };
 
 // Certain options should be toggled since we can assume chrome debugging here
 function setPrefDefaults() {
@@ -125,22 +125,22 @@ window.addEventListener("load", async fu
     console.error(e);
   }
 }, { once: true });
 
 function onCloseCommand(event) {
   window.close();
 }
 
-async function openToolbox({ form, chrome, isTabActor }) {
+async function openToolbox({ form, chrome, isBrowsingContext }) {
   let options = {
     form: form,
     client: gClient,
     chrome: chrome,
-    isTabActor: isTabActor
+    isBrowsingContext: isBrowsingContext
   };
   appendStatusMessage(`Create toolbox target: ${JSON.stringify(arguments, null, 2)}`);
   const target = await TargetFactory.forRemoteTab(options);
   const frame = document.getElementById("toolbox-iframe");
 
   // Remember the last panel that was used inside of this profile.
   // But if we are testing, then it should always open the debugger panel.
   const selectedTool =
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -2198,17 +2198,17 @@ Toolbox.prototype = {
     }
 
     const prefFront = await this.preferenceFront;
     return prefFront.getBoolPref(DISABLE_AUTOHIDE_PREF);
   },
 
   _listFrames: function(event) {
     if (!this._target.activeTab || !this._target.activeTab.traits.frames) {
-      // We are not targetting a regular TabActor
+      // We are not targetting a regular BrowsingContextTargetActor
       // it can be either an addon or browser toolbox actor
       return promise.resolve();
     }
     const packet = {
       to: this._target.form.actor,
       type: "listFrames"
     };
     return this._target.client.request(packet, resp => {
--- a/devtools/client/inspector/shared/tooltips-overlay.js
+++ b/devtools/client/inspector/shared/tooltips-overlay.js
@@ -79,17 +79,17 @@ TooltipsOverlay.prototype = {
    */
   addToView: function() {
     if (this._isStarted || this._isDestroyed) {
       return;
     }
 
     this._isStarted = true;
 
-    // For now, preview tooltip has to be instanciated on startup in order to
+    // For now, preview tooltip has to be instantiated on startup in order to
     // call tooltip.startTogglingOnHover. Ideally startTogglingOnHover wouldn't be part
     // of HTMLTooltip and offer a way to lazy load this tooltip.
     this.getTooltip("previewTooltip");
   },
 
   /**
    * Lazily fetch and initialize the different tooltips that are used in the inspector.
    * These tooltips are attached to the toolbox document if they require a popup panel.
--- a/devtools/client/shared/test/test-actor-registry.js
+++ b/devtools/client/shared/test/test-actor-registry.js
@@ -35,17 +35,17 @@
     const principal = CC("@mozilla.org/systemprincipal;1", "nsIPrincipal")();
     const sandbox = Cu.Sandbox(principal);
     sandbox.exports = {};
     sandbox.require = require;
     Cu.evalInSandbox(sourceText, sandbox, "1.8", ACTOR_URL, 1);
     return sandbox.exports;
   };
 
-  // Ensure fetching a live TabActor form for the targeted app
+  // Ensure fetching a live target actor form
   // (helps fetching the test actor registered dynamically)
   const getUpdatedForm = function(client, tab) {
     return client.getTab({tab: tab})
                  .then(response => response.tab);
   };
 
   // Spawn an instance of the test actor for the given toolbox
   exports.getTestActor = async function(toolbox) {
--- a/devtools/client/shared/test/test-actor.js
+++ b/devtools/client/shared/test/test-actor.js
@@ -288,23 +288,23 @@ var testSpec = protocol.generateActorSpe
       response: {
         value: RetVal("json")
       }
     }
   }
 });
 
 var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
-  initialize: function(conn, tabActor, options) {
+  initialize: function(conn, targetActor, options) {
     this.conn = conn;
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
   },
 
   get content() {
-    return this.tabActor.window;
+    return this.targetActor.window;
   },
 
   /**
    * Helper to retrieve a DOM element.
    * @param {string | array} selector Either a regular selector string
    *   or a selector array. If an array, each item, except the last one
    *   are considered matching an iframe, so that we can query element
    *   within deep iframes.
@@ -527,17 +527,17 @@ var TestActor = exports.TestActor = prot
     const node = this._querySelector(selector);
     return InspectorUtils.hasPseudoClassLock(node, pseudo);
   },
 
   loadAndWaitForCustomEvent: function(url) {
     return new Promise(resolve => {
       // Wait for DOMWindowCreated first, as listening on the current outerwindow
       // doesn't allow receiving test-page-processing-done.
-      this.tabActor.chromeEventHandler.addEventListener("DOMWindowCreated", () => {
+      this.targetActor.chromeEventHandler.addEventListener("DOMWindowCreated", () => {
         this.content.addEventListener(
           "test-page-processing-done", resolve, { once: true }
         );
       }, { once: true });
 
       this.content.location = url;
     });
   },
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -172,17 +172,17 @@ HUD_SERVICE.prototype =
       DebuggerServer.init();
       DebuggerServer.registerActors({ root: true, tab: true });
 
       DebuggerServer.allowChromeProcess = true;
 
       const client = new DebuggerClient(DebuggerServer.connectPipe());
       await client.connect();
       const response = await client.getProcess();
-      return { form: response.form, client, chrome: true, isTabActor: true };
+      return { form: response.form, client, chrome: true, isBrowsingContext: true };
     }
 
     async function openWindow(t) {
       const win = Services.ww.openWindow(null, Tools.webConsole.browserConsoleURL,
                                        "_blank", BC_WINDOW_FEATURES, null);
       let iframeWindow = win;
 
       await new Promise(resolve => {
--- a/devtools/client/webconsole/webconsole-connection-proxy.js
+++ b/devtools/client/webconsole/webconsole-connection-proxy.js
@@ -140,17 +140,17 @@ WebConsoleConnectionProxy.prototype = {
     client.addListener("reflowActivity", this._onReflowActivity);
     client.addListener("lastPrivateContextExited",
                        this._onLastPrivateContextExited);
 
     this.target.on("will-navigate", this._onTabWillNavigate);
     this.target.on("navigate", this._onTabNavigated);
 
     this._consoleActor = this.target.form.consoleActor;
-    if (this.target.isTabActor) {
+    if (this.target.isBrowsingContext) {
       const tab = this.target.form;
       this.webConsoleFrame.onLocationChange(tab.url, tab.title);
     }
     this._attachConsole();
 
     return connPromise;
   },
 
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.js
@@ -247,38 +247,38 @@ var AppManager = exports.AppManager = {
                    .then(aResponse => {
                      return TargetFactory.forRemoteTab({
                        form: aResponse.form,
                        client: this.connection.client,
                        chrome: true
                      });
                    });
       }
-        // Fx <39 exposes tab actors on the root actor
+      // Fx <39 exposes chrome target actors on the root actor
       return TargetFactory.forRemoteTab({
           form: this._listTabsResponse,
           client: this.connection.client,
           chrome: true,
-          isTabActor: false
+          isBrowsingContext: false
       });
     }
 
     if (this.selectedProject.type == "tab") {
       return this.tabStore.getTargetForTab();
     }
 
     const app = this._getProjectFront(this.selectedProject);
     if (!app) {
       return Promise.reject("Can't find app front for selected project");
     }
 
     return (async function() {
       // Once we asked the app to launch, the app isn't necessary completely loaded.
       // launch request only ask the app to launch and immediatly returns.
-      // We have to keep trying to get app tab actors required to create its target.
+      // We have to keep trying to get app target actors required to create its target.
 
       for (let i = 0; i < 10; i++) {
         try {
           return await app.getTarget();
         } catch (e) {}
         return new Promise(resolve => {
           setTimeout(resolve, 500);
         });
@@ -490,17 +490,17 @@ var AppManager = exports.AppManager = {
         .add(d.apptype, true);
     this._telemetry
         .getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_VERSION")
         .add(d.version, true);
     this.update("runtime-telemetry");
   },
 
   isMainProcessDebuggable: function() {
-    // Fx <39 exposes chrome tab actors on RootActor
+    // Fx <39 exposes chrome target actors on RootActor
     // Fx >=39 exposes a dedicated actor via getProcess request
     return this.connection.client &&
            this.connection.client.mainRoot &&
            this.connection.client.mainRoot.traits.allowChromeProcess ||
            (this._listTabsResponse &&
             this._listTabsResponse.consoleActor);
   },
 
--- a/devtools/docs/backend/actor-best-practices.md
+++ b/devtools/docs/backend/actor-best-practices.md
@@ -14,21 +14,21 @@ Then there's no need for the client to s
 
 ## Actor Destruction
 
 Ensure that the actor's destroy is really destroying everything that it should. Here's an example from the animation actor:
 
 ```js
 destroy: function() {
   Actor.prototype.destroy.call(this);
-  this.tabActor.off("will-navigate", this.onWillNavigate);
-  this.tabActor.off("navigate", this.onNavigate);
+  this.targetActor.off("will-navigate", this.onWillNavigate);
+  this.targetActor.off("navigate", this.onNavigate);
 
   this.stopAnimationPlayerUpdates();
-  this.tabActor = this.observer = this.actors = null;
+  this.targetActor = this.observer = this.actors = null;
 },
 ```
 
 ## Child Actors
 
 With protocol.js actors, if your creates child actors for further functionality, in most cases you should call:
 
 ```js
--- a/devtools/docs/backend/actor-hierarchy.md
+++ b/devtools/docs/backend/actor-hierarchy.md
@@ -1,38 +1,49 @@
 # How actors are organized
 
-To start with, actors are living within /devtools/server/actors/ folder.
-They are organized in a hierarchy for easier lifecycle/memory management:
+To start with, actors are living within devtools/server/actors folder.
+They are organized in a hierarchy for easier lifecycle and memory management:
 once a parent is removed from the pool, its children are removed as well.
 (See actor-registration.md for more information about how to implement one)
 
 The overall hierarchy of actors looks like this:
 
 ```
 RootActor: First one, automatically instantiated when we start connecting.
-   |         Mostly meant to instantiate new actors.
+   |       Mostly meant to instantiate new actors.
    |
-   |--> Global-scoped actors:
-   |    Actors exposing features related to the main process,
-   |    that are not specific to any particular context (document, tab, app,
-   |    add-on, or worker).
-   |    A good example is the preference actor.
+   |-- Global-scoped actors:
+   |   Actors exposing features related to the main process, that are not
+   |   specific to any particular target (document, tab, add-on, or worker).
+   |   These actors are registered with `global: true` in
+   |   devtools/server/main.js.
+   |   Examples include:
+   |   PreferenceActor (for Firefox prefs)
    |
-   \--> "TabActor" (or alike):
-          |    Actors meant to designate one context (document, tab, app,
-          |    add-on, or worker) and track its lifetime.  Generally, there is
-          |    one of these for each thing you can point a toolbox at.
-          |
-          \--> Tab-scoped actors:
-               Actors exposing one particular feature set, this time,
-               specific to a given context (document, tab, app, add-on, or
-               worker).  Examples include the console and inspector actors.
-               These actors may extend this hierarchy by having their
-               own children, like LongStringActor, WalkerActor, etc.
+   \-- Target actors:
+       Actors that represent the main "thing" being targeted by a given toolbox,
+       such as a tab, frame, worker, add-on, etc. and track its lifetime.
+       Generally, there is a target actor for each thing you can point a
+       toolbox at.
+       Examples include:
+       ContentActor (for a frame, such as a tab)
+       WorkerActor (for various kind of workers)
+       |
+       \-- Tab-scoped actors:
+           Actors exposing one particular feature set. They are children of a
+           given target actor and the data they return is filtered to reflect
+           the target.
+           These actors are registered with `tab: true` in
+           devtools/server/main.js.
+           Examples include:
+           WebConsoleActor
+           InspectorActor
+           These actors may extend this hierarchy by having their own children,
+           like LongStringActor, WalkerActor, etc.
 ```
 
 ## RootActor
 
 The root actor is special. It is automatically created when a client connects.
 It has a special `actorID` which is unique and is "root".
 All other actors have an `actorID` which is computed dynamically,
 so that you need to ask an existing actor to create an Actor
@@ -43,93 +54,116 @@ RootActor (root.js)
    |
    |-- BrowserTabActor (webbrowser.js)
    |   Targets tabs living in the parent or child process. Note that this is
    |   just a proxy for ContentActor, which is loaded via the tab's message
    |   manager as a frame script in the process containing the tab. This proxy
    |   via message manager is always used, even when e10s is disabled.
    |   Returned by "listTabs" or "getTab" requests.
    |   |
-   |   \-> ContentActor (content.js)
+   |   \-- ContentActor (content.js)
    |       The "real" actor for a tab, which runs in whichever process holds the
    |       content.  BrowserTabActor communicates with this via the tab's
    |       message manager.
+   |       Extends the abstract class BrowsingContextTargetActor.
    |       Returned by "connect" on BrowserTabActor.
    |
    |-- WorkerActor (worker.js)
    |   Targets a worker (applies to various kinds like web worker, service
    |   worker, etc.).
    |   Returned by "listWorkers" request to the root actor to get all workers.
    |   Returned by "listWorkers" request to a BrowserTabActor to get workers for
    |   a specific tab.
    |   Returned by "listWorkers" request to a ChildProcessActor to get workers
    |   for the chrome of the child process.
    |
    |-- WindowActor (window.js)
    |   Targets a single window, such as a browser window in Firefox, but it can
    |   be used to reach any window in the parent process.
+   |   Extends the abstract class BrowsingContextTargetActor.
    |   Returned by "getWindow" request to the root actor.
    |
    |-- ChromeActor (chrome.js)
    |   Targets all resources in the parent process of firefox
    |   (chrome documents, JSM, JS XPCOM, etc.).
+   |   Extends the abstract class BrowsingContextTargetActor.
    |   Returned by "getProcess" request without any argument.
    |
    |-- ChildProcessActor (child-process.js)
    |   Targets the chrome of the child process (e10s).
    |   Returned by "getProcess" request with a id argument,
    |   matching the targeted process.
    |
    \-- BrowserAddonActor (addon.js)
        Targets the javascript of add-ons.
        Returned by "listAddons" request.
 ```
 
-## "TabActor"
+## Target Actors
 
 Those are the actors exposed by the root actors which are meant to track the
-lifetime of a given context: tab, app, process, add-on, or worker. It also
-allows to fetch the tab-scoped actors connected to this context. Actors like
-console, inspector, thread (for debugger), styleinspector, etc. Most of them
-inherit from TabActor (defined in tab.js) which is document centric. It
-automatically tracks the lifetime of the targeted document, but it also tracks
-its iframes and allows switching the context to one of its iframes. For
-historical reasons, these actors also handle creating the ThreadActor, used to
-manage breakpoints in the debugger. All the other tab-scoped actors are created
-when we access the TabActor's grip. We return the tab-scoped actors `actorID` in
-it. Actors inheriting from TabActor expose `attach`/`detach` requests, that
-allows to start/stop the ThreadActor.
+lifetime of a given target: tab, process, add-on, or worker. It also allows to
+fetch the tab-scoped actors connected to this target, which are actors like
+console, inspector, thread (for debugger), style inspector, etc.
+
+Some target actors inherit from BrowsingContextTargetActor (defined in
+browsing-context.js) which is meant for "browsing contexts" which present
+documents to the user. It automatically tracks the lifetime of the targeted
+browsing context, but it also tracks its iframes and allows switching the
+target to one of its iframes.
 
-The tab-scoped actors expect to find the following properties on the "TabActor":
+For historical reasons, target actors also handle creating the ThreadActor, used
+to manage breakpoints in the debugger. Actors inheriting from
+BrowsingContextTargetActor expose `attach`/`detach` requests, that allows to
+start/stop the ThreadActor.
+
+Tab-scoped actors are accessed via the target actor's RDP form which contains
+the `actorID` for each tab-scoped actor.
+
+The tab-scoped actors expect to find the following properties on the target
+actor:
  - threadActor:
-   ThreadActor instance for the given context,
+   ThreadActor instance for the given target,
    only defined once `attach` request is called, or on construction.
  - isRootActor: (historical name)
    Always false, except on ChromeActor.
    Despite the attribute name, it is being used to accept all resources
    (like chrome one) instead of limiting only to content resources.
  - makeDebugger:
-   Helper function used to create Debugger object for the targeted context.
+   Helper function used to create Debugger object for the target.
    (See actors/utils/make-debugger.js for more info)
 
-In addition to this, the actors inheriting from TabActor, expose many other
-attributes and events:
+In addition to this, the actors inheriting from BrowsingContextTargetActor,
+expose many other attributes and events:
  - window:
    Reference to the window global object currently targeted.
-   It can change over time if we switch context to an iframe, so it
+   It can change over time if we switch target to an iframe, so it
    shouldn't be stored in a variable, but always retrieved from the actor.
  - windows:
-   List of all document globals including the main window object and all iframes.
+   List of all document globals including the main window object and all
+   iframes.
  - docShell:
-   DocShell reference for the targeted context.
+   Primary docShell reference for the targeted document.
  - docShells:
-   List of all docshells for the targeted document and all its iframes.
+   List of all docShells for the targeted document and all its iframes.
  - chromeEventHandler:
-   The chrome event handler for the current context. Allows to listen to events
+   The chrome event handler for the current target. Allows to listen to events
    that can be missing/cancelled on this document itself.
 
-See TabActor documentation for events definition.
+See BrowsingContextTargetActor documentation for more details.
 
 ## Tab-scoped actors
 
-Each of these actors focuses on providing one particular feature set, specific
-to one context, that can be a web page, an app, a top level firefox window, a
-process, an add-on, or a worker.
+Each of these actors focuses on providing one particular feature set. They are
+children of a given target actor.
+
+The data they return is filtered to reflect the target. For example, the
+InspectorActor that you fetch from a ContentActor gives you information about
+the markup and styles for only that frame.
+
+These actors may extend this hierarchy by having their own children, like
+LongStringActor, WalkerActor, etc.
+
+To improve performance, tab-scoped actors are created lazily. The target actor
+lists the actor ID for each one, but the actor modules aren't actually loaded
+and instantiated at that point. Once the first request for a given tab-scoped
+actor is received by the server, that specific actor is instantiated just in
+time to service the request.
--- a/devtools/docs/backend/actor-registration.md
+++ b/devtools/docs/backend/actor-registration.md
@@ -1,17 +1,17 @@
 # How to register an actor
 
 ## Tab actors vs. global actors
 
 Tab actors are the most common types of actors. That's the type of actors you will most probably be adding.
 
 Tab actors target a document, this could be a tab in Firefox or a remote document in Firefox for Android.
 
-Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/Chrome/Safari intance the toolbox is connected to (e.g. the preference actor).
+Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/Chrome/Safari instance the toolbox is connected to (e.g. the preference actor).
 
 ## The DebuggerServer.registerModule function
 
 To register a tab actor:
 
 ```
 DebuggerServer.registerModule("devtools/server/actors/webconsole", {
   prefix: "console",
--- a/devtools/docs/backend/protocol.md
+++ b/devtools/docs/backend/protocol.md
@@ -653,79 +653,79 @@ The root actor replies:
 { "from":"root", "tabs":[<tab>, ...], "selected":<selected> }
 ```
 
 where each *tab* describes a single open tab, and *selected* is the index in the array of tabs of the currently selected tab. This form may have other properties describing other global actors; for one example, see [Chrome Debugging](#chrome-debugging).
 
 Each *tab* has the form:
 
 ```
-{ "actor":<tabActor>, "title":<title>, "url":<URL> }
+{ "actor":<targetActor>, "title":<title>, "url":<URL> }
 ```
 
-where *tabActor* is the name of an actor representing the tab, and *title* and *URL* are the title and URL of the web page currently visible in that tab. This form may have other properties describing other tab-specific actors.
+where *targetActor* is the name of an actor representing the tab, and *title* and *URL* are the title and URL of the web page currently visible in that tab. This form may have other properties describing other tab-specific actors.
 
-To attach to a *tabActor*, a client sends a message of the form:
+To attach to a *targetActor*, a client sends a message of the form:
 
 ```
-{ "to":<tabActor>, "type":"attach" }
+{ "to":<targetActor>, "type":"attach" }
 ```
 
-The tab actor replies:
+The target actor replies:
 
 ```
-{ "from":<tabActor>, "type":"tabAttached", "threadActor":<tabThreadActor> }
+{ "from":<targetActor>, "type":"tabAttached", "threadActor":<tabThreadActor> }
 ```
 
 where *tabThreadActor* is the name of a thread-like actor representing the tab's current content. If the user navigates the tab, *tabThreadActor* switches to the new content; we do not create a separate thread-like actor each page the tab visits.
 
-If the user closes the tab before the client attaches to it, *tabActor* replies:
+If the user closes the tab before the client attaches to it, *targetActor* replies:
 
 ```
-{ "from":<tabActor>, "type":"exited" }
+{ "from":<targetActor>, "type":"exited" }
 ```
 
 When the client is no longer interested in interacting with the tab, the client can request:
 
 ```
-{ "to":<tabActor>, "type":"detach" }
+{ "to":<targetActor>, "type":"detach" }
 ```
 
-The *tabActor* replies:
+The *targetActor* replies:
 
 ```
-{ "from":<tabActor>, "type":"detached" }
+{ "from":<targetActor>, "type":"detached" }
 ```
 
-If the client was not already attached to *tabActor*, *tabActor* sends an error reply of the form:
+If the client was not already attached to *targetActor*, *targetActor* sends an error reply of the form:
 
 ```
-{ "from":<tabActor>, "error":"wrongState" }
+{ "from":<targetActor>, "error":"wrongState" }
 ```
 
-While the client is attached, *tabActor* sends notifications to the client whenever the user navigates the tab to a new page. When navigation begins, *tabActor* sends a packet of the form:
+While the client is attached, *targetActor* sends notifications to the client whenever the user navigates the tab to a new page. When navigation begins, *targetActor* sends a packet of the form:
 
 ```
-{ "from":<tabActor>, "type":"tabNavigated", "state":"start",
+{ "from":<targetActor>, "type":"tabNavigated", "state":"start",
   "url":<newURL> }
 ```
 
-This indicates that the tab has begun navigating to *newURL*; JavaScript execution in the tab's prior page is suspended. When navigation is complete, *tabActor* sends a packet of the form:
+This indicates that the tab has begun navigating to *newURL*; JavaScript execution in the tab's prior page is suspended. When navigation is complete, *targetActor* sends a packet of the form:
 
 ```
-{ "from":<tabActor>, "type":"tabNavigated", "state":"stop",
+{ "from":<targetActor>, "type":"tabNavigated", "state":"stop",
   "url":<newURL>, "title":<newTitle> }
 ```
 
 where *newURL* and *newTitle* are the URL and title of the page the tab is now showing. The *tabThreadActor* given in the response to the original `"attach"` packet is now debugging the new page's code.
 
-If the user closes a tab to which the client is attached, its *tabActor* sends a notification packet of the form:
+If the user closes a tab to which the client is attached, its *targetActor* sends a notification packet of the form:
 
 ```
-{ "from":<tabActor>, "type":"tabDetached" }
+{ "from":<targetActor>, "type":"tabDetached" }
 ```
 
 The client is now detached from the tab.
 
 ### Chrome Debugging
 
 If the server supports debugging chrome code, the root actor's reply to a `"listTabs"` request includes a property named `"chromeDebugger"`, whose value is the name of a thread-like actor to which the client can attach to debug chrome code.
 
--- a/devtools/docs/tools/highlighters.md
+++ b/devtools/docs/tools/highlighters.md
@@ -118,20 +118,20 @@ Because of the way content is inserted i
 
 In order to help with the API described in the previous section, the `CanvasFrameAnonymousContentHelper` class was introduced.
 
 Its goal is to provide a simple way for highlighters to insert their content into the page and modify it dynamically later. One of its goal is also to re-insert the highlighters' content on page navigation. Indeed, the frame tree is destroyed when the page is navigated away from since it represents the document element.
 
 Using this helper is quite simple:
 
 ```js
-let helper = new CanvasFrameAnonymousContentHelper(tabActor, this.buildMarkup.bind(this));
+let helper = new CanvasFrameAnonymousContentHelper(targetActor, this.buildMarkup.bind(this));
 ```
 
-It only requires a `tabActor`, which highlighters get when they are instantiated, and a callback function that will be used to create and insert the content the first time the highlighter is shown, and every time there's a page navigation.
+It only requires a `targetActor`, which highlighters get when they are instantiated, and a callback function that will be used to create and insert the content the first time the highlighter is shown, and every time there's a page navigation.
 
 The returned object provides the following API:
 
 | Method                                    | Description                                                |
 |-------------------------------------------|------------------------------------------------------------|
 | `getTextContentForElement(id)`            | Get the textContent of an element given its ID.            |
 | `setTextContentForElement(id, text)`      | Set the textContent of an element given its ID.            |
 | `setAttributeForElement(id, name, value)` | Set an attribute value of an element given its ID.         |
@@ -142,19 +142,19 @@ The returned object provides the followi
 
   ### Creating a new highlighter class
 
 A good way to get started is by taking a look at [existing highlighters here](https://dxr.mozilla.org/mozilla-central/source/devtools/server/actors/highlighters.js#697-727).
 
 Here is some boilerplate code for a new highlighter class:
 
 ```js
- function MyNewHighlighter(tabActor) {
-   this.doc = tabActor.window.document;
-   this.markup = new CanvasFrameAnonymousContentHelper(tabActor, this._buildMarkup.bind(this));
+ function MyNewHighlighter(targetActor) {
+   this.doc = targetActor.window.document;
+   this.markup = new CanvasFrameAnonymousContentHelper(targetActor, this._buildMarkup.bind(this));
  }
 
  MyNewHighlighter.prototype = {
    destroy: function() {
      this.doc = null;
      this.markup.destroy();
    },
 
--- a/devtools/server/actors/accessibility.js
+++ b/devtools/server/actors/accessibility.js
@@ -377,19 +377,19 @@ const AccessibleActor = ActorClassWithSp
  * The AccessibleWalkerActor stores a cache of AccessibleActors that represent
  * accessible objects in a given document.
  *
  * It is also responsible for implicitely initializing and shutting down
  * accessibility engine by storing a reference to the XPCOM accessibility
  * service.
  */
 const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
-  initialize(conn, tabActor) {
+  initialize(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
     this.refMap = new Map();
     this.setA11yServiceGetter();
     this.onPick = this.onPick.bind(this);
     this.onHovered = this.onHovered.bind(this);
     this.onKey = this.onKey.bind(this);
 
     this.highlighter = CustomHighlighterActor(this, isXUL(this.rootWin) ?
       "XULWindowAccessibleHighlighter" : "AccessibleHighlighter");
@@ -399,21 +399,21 @@ const AccessibleWalkerActor = ActorClass
     DevToolsUtils.defineLazyGetter(this, "a11yService", () => {
       Services.obs.addObserver(this, "accessible-event");
       return Cc["@mozilla.org/accessibilityService;1"].getService(
         Ci.nsIAccessibilityService);
     });
   },
 
   get rootWin() {
-    return this.tabActor && this.tabActor.window;
+    return this.targetActor && this.targetActor.window;
   },
 
   get rootDoc() {
-    return this.tabActor && this.tabActor.window.document;
+    return this.targetActor && this.targetActor.window.document;
   },
 
   reset() {
     try {
       Services.obs.removeObserver(this, "accessible-event");
     } catch (e) {
       // Accessible event observer might not have been initialized if a11y
       // service was never used.
@@ -442,17 +442,17 @@ const AccessibleWalkerActor = ActorClass
   destroy() {
     Actor.prototype.destroy.call(this);
 
     this.reset();
 
     this.highlighter.destroy();
     this.highlighter = null;
 
-    this.tabActor = null;
+    this.targetActor = null;
     this.refMap = null;
   },
 
   getRef(rawAccessible) {
     return this.refMap.get(rawAccessible);
   },
 
   addRef(rawAccessible) {
@@ -913,31 +913,31 @@ const AccessibleWalkerActor = ActorClass
 
     return accessible;
   },
 
   /**
    * Start picker content listeners.
    */
   _startPickerListeners: function() {
-    const target = this.tabActor.chromeEventHandler;
+    const target = this.targetActor.chromeEventHandler;
     target.addEventListener("mousemove", this.onHovered, true);
     target.addEventListener("click", this.onPick, true);
     target.addEventListener("mousedown", this._preventContentEvent, true);
     target.addEventListener("mouseup", this._preventContentEvent, true);
     target.addEventListener("dblclick", this._preventContentEvent, true);
     target.addEventListener("keydown", this.onKey, true);
     target.addEventListener("keyup", this._preventContentEvent, true);
   },
 
   /**
    * If content is still alive, stop picker content listeners.
    */
   _stopPickerListeners: function() {
-    const target = this.tabActor.chromeEventHandler;
+    const target = this.targetActor.chromeEventHandler;
 
     if (!target) {
       return;
     }
 
     target.removeEventListener("mousemove", this.onHovered, true);
     target.removeEventListener("click", this.onPick, true);
     target.removeEventListener("mousedown", this._preventContentEvent, true);
@@ -962,17 +962,17 @@ const AccessibleWalkerActor = ActorClass
 });
 
 /**
  * The AccessibilityActor is a top level container actor that initializes
  * accessible walker and is the top-most point of interaction for accessibility
  * tools UI.
  */
 const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
-  initialize(conn, tabActor) {
+  initialize(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
 
     this.initializedDeferred = defer();
 
     if (DebuggerServer.isInChildProcess) {
       this._msgName = `debug:${this.conn.prefix}accessibility`;
       this.conn.setupInParent({
         module: "devtools/server/actors/accessibility-parent",
@@ -984,17 +984,17 @@ const AccessibilityActor = ActorClassWit
     } else {
       this.userPref = Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED);
       Services.obs.addObserver(this, "a11y-consumers-changed");
       Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
       this.initializedDeferred.resolve();
     }
 
     Services.obs.addObserver(this, "a11y-init-or-shutdown");
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
   },
 
   bootstrap() {
     return this.initializedDeferred.promise.then(() => ({
       enabled: this.enabled,
       canBeEnabled: this.canBeEnabled,
       canBeDisabled: this.canBeDisabled
     }));
@@ -1176,17 +1176,17 @@ const AccessibilityActor = ActorClassWit
   /**
    * Get or create AccessibilityWalker actor, similar to WalkerActor.
    *
    * @return {Object}
    *         AccessibleWalkerActor for the current tab.
    */
   getWalker() {
     if (!this.walker) {
-      this.walker = new AccessibleWalkerActor(this.conn, this.tabActor);
+      this.walker = new AccessibleWalkerActor(this.conn, this.targetActor);
     }
     return this.walker;
   },
 
   /**
    * Destroy accessibility service actor. This method also shutsdown
    * accessibility service if possible.
    */
@@ -1211,16 +1211,16 @@ const AccessibilityActor = ActorClassWit
                                                 this.onMessage);
     } else {
       Services.obs.removeObserver(this, "a11y-consumers-changed");
       Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
     }
 
     Actor.prototype.destroy.call(this);
     this.walker = null;
-    this.tabActor = null;
+    this.targetActor = null;
     resolver();
   }
 });
 
 exports.AccessibleActor = AccessibleActor;
 exports.AccessibleWalkerActor = AccessibleWalkerActor;
 exports.AccessibilityActor = AccessibilityActor;
--- a/devtools/server/actors/addon-console.js
+++ b/devtools/server/actors/addon-console.js
@@ -11,18 +11,18 @@ loader.lazyRequireGetter(this, "WebConso
 
 const { extend } = require("devtools/shared/extend");
 const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol");
 const { webconsoleSpec } = require("devtools/shared/specs/webconsole");
 
 /**
  * Protocol.js expects only the prototype object, and does not maintain the prototype
  * chain when it constructs the ActorClass. For this reason we are using `extend` to
- * maintain the properties of TabActor.prototype
- * */
+ * maintain the properties of BrowsingContextTargetActor.prototype
+ */
 const addonConsolePrototype = extend({}, WebConsoleActor.prototype);
 
 /**
  * The AddonConsoleActor implements capabilities needed for the add-on web
  * console feature.
  *
  * @constructor
  * @param object addon
--- a/devtools/server/actors/addon.js
+++ b/devtools/server/actors/addon.js
@@ -130,17 +130,17 @@ BrowserAddonActor.prototype = {
   onUninstalled: function BAAOnUninstalled(addon) {
     if (addon != this._addon) {
       return;
     }
 
     if (this.attached) {
       this.onDetach();
 
-      // The BrowserAddonActor is not a TabActor and it has to send
+      // The BrowserAddonActor is not a BrowsingContextTargetActor and it has to send
       // "tabDetached" directly to close the devtools toolbox window.
       this.conn.send({ from: this.actorID, type: "tabDetached" });
     }
 
     this.destroy();
   },
 
   onAttach: function BAAOnAttach() {
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -600,38 +600,38 @@ var AnimationPlayerActor = protocol.Acto
 });
 
 exports.AnimationPlayerActor = AnimationPlayerActor;
 
 /**
  * The Animations actor lists animation players for a given node.
  */
 exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
 
     this.onWillNavigate = this.onWillNavigate.bind(this);
     this.onNavigate = this.onNavigate.bind(this);
     this.onAnimationMutation = this.onAnimationMutation.bind(this);
 
     this.allAnimationsPaused = false;
-    this.tabActor.on("will-navigate", this.onWillNavigate);
-    this.tabActor.on("navigate", this.onNavigate);
+    this.targetActor.on("will-navigate", this.onWillNavigate);
+    this.targetActor.on("navigate", this.onNavigate);
 
     this.animationCreatedTimeMap = new Map();
   },
 
   destroy: function() {
     Actor.prototype.destroy.call(this);
-    this.tabActor.off("will-navigate", this.onWillNavigate);
-    this.tabActor.off("navigate", this.onNavigate);
+    this.targetActor.off("will-navigate", this.onWillNavigate);
+    this.targetActor.off("navigate", this.onNavigate);
 
     this.stopAnimationPlayerUpdates();
-    this.tabActor = this.observer = this.actors = this.walker = null;
+    this.targetActor = this.observer = this.actors = this.walker = null;
 
     this.animationCreatedTimeMap.clear();
     this.animationCreatedTimeMap = null;
   },
 
   /**
    * Clients can optionally call this with a reference to their WalkerActor.
    * If they do, then AnimationPlayerActor's forms are going to also include
@@ -787,17 +787,17 @@ exports.AnimationsActor = protocol.Actor
    * @return {Array} An array of AnimationPlayer objects.
    */
   getAllAnimations: function(rootNode, traverseFrames) {
     if (!traverseFrames) {
       return rootNode.getAnimations({subtree: true});
     }
 
     let animations = [];
-    for (const {document} of this.tabActor.windows) {
+    for (const {document} of this.targetActor.windows) {
       animations = [...animations, ...document.getAnimations({subtree: true})];
     }
     return animations;
   },
 
   onWillNavigate: function({isTopLevel}) {
     if (isTopLevel) {
       this.stopAnimationPlayerUpdates();
@@ -806,37 +806,37 @@ exports.AnimationsActor = protocol.Actor
 
   onNavigate: function({isTopLevel}) {
     if (isTopLevel) {
       this.allAnimationsPaused = false;
     }
   },
 
   /**
-   * Pause all animations in the current tabActor's frames.
+   * Pause all animations in the current targetActor's frames.
    */
   pauseAll: function() {
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (const player of
-         this.getAllAnimations(this.tabActor.window.document, true)) {
+         this.getAllAnimations(this.targetActor.window.document, true)) {
       this.pauseSync(player);
     }
     this.allAnimationsPaused = true;
   },
 
   /**
-   * Play all animations in the current tabActor's frames.
+   * Play all animations in the current targetActor's frames.
    * This method only returns when animations have left their pending states.
    */
   playAll: function() {
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (const player of
-      this.getAllAnimations(this.tabActor.window.document, true)) {
+      this.getAllAnimations(this.targetActor.window.document, true)) {
       this.playSync(player);
     }
     this.allAnimationsPaused = false;
   },
 
   toggleAll: function() {
     if (this.allAnimationsPaused) {
       this.playAll();
@@ -961,17 +961,17 @@ exports.AnimationsActor = protocol.Actor
   getCreatedTime(animation) {
     return this.animationCreatedTimeMap.get(animation);
   },
 
   /**
    * Update all animation created time map.
    */
   updateAllAnimationsCreatedTime() {
-    const currentAnimations = this.getAllAnimations(this.tabActor.window.document);
+    const currentAnimations = this.getAllAnimations(this.targetActor.window.document);
 
     // Remove invalid animations.
     for (const previousAnimation of this.animationCreatedTimeMap.keys()) {
       if (!currentAnimations.includes(previousAnimation)) {
         this.animationCreatedTimeMap.delete(previousAnimation);
       }
     }
 
--- a/devtools/server/actors/call-watcher.js
+++ b/devtools/server/actors/call-watcher.js
@@ -226,41 +226,41 @@ var FunctionCallActor = protocol.ActorCl
     return data + "";
   }
 });
 
 /**
  * This actor observes function calls on certain objects or globals.
  */
 exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
     this._onGlobalCreated = this._onGlobalCreated.bind(this);
     this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
     this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
-    this.tabActor.on("window-ready", this._onGlobalCreated);
-    this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.on("window-ready", this._onGlobalCreated);
+    this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
   },
   destroy: function(conn) {
     protocol.Actor.prototype.destroy.call(this, conn);
-    this.tabActor.off("window-ready", this._onGlobalCreated);
-    this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.off("window-ready", this._onGlobalCreated);
+    this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
     this.finalize();
   },
 
   /**
    * Lightweight listener invoked whenever an instrumented function is called
    * while recording. We're doing this to avoid the event emitter overhead,
    * since this is expected to be a very hot function.
    */
   onCall: null,
 
   /**
-   * Starts waiting for the current tab actor's document global to be
+   * Starts waiting for the current target actor's document global to be
    * created, in order to instrument the specified objects and become
    * aware of everything the content does with them.
    */
   setup: function({
     tracedGlobals, tracedFunctions, startRecording, performReload, holdWeak, storeCalls
   }) {
     if (this._initialized) {
       return;
@@ -273,17 +273,17 @@ exports.CallWatcherActor = protocol.Acto
     this._tracedFunctions = tracedFunctions || [];
     this._holdWeak = !!holdWeak;
     this._storeCalls = !!storeCalls;
 
     if (startRecording) {
       this.resumeRecording();
     }
     if (performReload) {
-      this.tabActor.window.location.reload();
+      this.targetActor.window.location.reload();
     }
   },
 
   /**
    * Stops listening for document global changes and puts this actor
    * to hibernation. This method is called automatically just before the
    * actor is destroyed.
    */
@@ -304,17 +304,17 @@ exports.CallWatcherActor = protocol.Acto
   isRecording: function() {
     return this._recording;
   },
 
   /**
    * Initialize the timestamp epoch used to offset function call timestamps.
    */
   initTimestampEpoch: function() {
-    this._timestampEpoch = this.tabActor.window.performance.now();
+    this._timestampEpoch = this.targetActor.window.performance.now();
   },
 
   /**
    * Starts recording function calls.
    */
   resumeRecording: function() {
     this._recording = true;
   },
@@ -331,17 +331,17 @@ exports.CallWatcherActor = protocol.Acto
    * Erases all the recorded function calls.
    * Calling `resumeRecording` or `pauseRecording` does not erase history.
    */
   eraseRecording: function() {
     this._functionCalls = [];
   },
 
   /**
-   * Invoked whenever the current tab actor's document global is created.
+   * Invoked whenever the current target actor's document global is created.
    */
   _onGlobalCreated: function({window, id, isTopLevel}) {
     if (!this._initialized) {
       return;
     }
 
     // TODO: bug 981748, support more than just the top-level documents.
     if (!isTopLevel) {
@@ -394,17 +394,18 @@ exports.CallWatcherActor = protocol.Acto
           result = Cu.waiveXrays(originalFunc.apply(this, args));
         } catch (e) {
           throw createContentError(e, unwrappedWindow);
         }
 
         if (self._recording) {
           const type = CallWatcherFront.METHOD_FUNCTION;
           const stack = getStack(name);
-          const timestamp = self.tabActor.window.performance.now() - self._timestampEpoch;
+          const now = self.targetActor.window.performance.now();
+          const timestamp = now - self._timestampEpoch;
           subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
             args, result);
         }
         return result;
       }, target, { defineAs: name });
 
       Object.defineProperty(target, name, {
         configurable: descriptor.configurable,
@@ -427,34 +428,34 @@ exports.CallWatcherActor = protocol.Acto
           if (!originalGetter) {
             return undefined;
           }
           const result = Cu.waiveXrays(originalGetter.apply(this, args));
 
           if (self._recording) {
             const type = CallWatcherFront.GETTER_FUNCTION;
             const stack = getStack(name);
-            const timestamp =
-              self.tabActor.window.performance.now() - self._timestampEpoch;
+            const now = self.targetActor.window.performance.now();
+            const timestamp = now - self._timestampEpoch;
             subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
               args, result);
           }
           return result;
         },
         set: function(...args) {
           if (!originalSetter) {
             return;
           }
           originalSetter.apply(this, args);
 
           if (self._recording) {
             const type = CallWatcherFront.SETTER_FUNCTION;
             const stack = getStack(name);
-            const timestamp =
-              self.tabActor.window.performance.now() - self._timestampEpoch;
+            const now = self.targetActor.window.performance.now();
+            const timestamp = now - self._timestampEpoch;
             subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
               args, undefined);
           }
         },
         configurable: descriptor.configurable,
         enumerable: descriptor.enumerable
       });
     }
@@ -511,17 +512,17 @@ exports.CallWatcherActor = protocol.Acto
         callIndex++;
       }
 
       return calls;
     }
   },
 
   /**
-   * Invoked whenever the current tab actor's inner window is destroyed.
+   * Invoked whenever the current target actor's inner window is destroyed.
    */
   _onGlobalDestroyed: function({window, id, isTopLevel}) {
     if (this._tracedWindowId == id) {
       this.pauseRecording();
       this.eraseRecording();
       this._timestampEpoch = 0;
     }
   },
--- a/devtools/server/actors/canvas.js
+++ b/devtools/server/actors/canvas.js
@@ -119,41 +119,41 @@ var FrameSnapshotActor = protocol.ActorC
  * of a 2D or WebGL context, to provide information regarding all the calls
  * made when drawing frame inside an animation loop.
  */
 exports.CanvasActor = protocol.ActorClassWithSpec(canvasSpec, {
   // Reset for each recording, boolean indicating whether or not
   // any draw calls were called for a recording.
   _animationContainsDrawCall: false,
 
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
-    this._webGLPrimitiveCounter = new WebGLPrimitiveCounter(tabActor);
+    this.targetActor = targetActor;
+    this._webGLPrimitiveCounter = new WebGLPrimitiveCounter(targetActor);
     this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
   },
   destroy: function(conn) {
     protocol.Actor.prototype.destroy.call(this, conn);
     this._webGLPrimitiveCounter.destroy();
     this.finalize();
   },
 
   /**
    * Starts listening for function calls.
    */
   setup: function({ reload }) {
     if (this._initialized) {
       if (reload) {
-        this.tabActor.window.location.reload();
+        this.targetActor.window.location.reload();
       }
       return;
     }
     this._initialized = true;
 
-    this._callWatcher = new CallWatcherActor(this.conn, this.tabActor);
+    this._callWatcher = new CallWatcherActor(this.conn, this.targetActor);
     this._callWatcher.onCall = this._onContentFunctionCall;
     this._callWatcher.setup({
       tracedGlobals: CANVAS_CONTEXTS,
       tracedFunctions: [...ANIMATION_GENERATORS, ...LOOP_GENERATORS],
       performReload: reload,
       storeCalls: true
     });
   },
--- a/devtools/server/actors/canvas/primitive.js
+++ b/devtools/server/actors/canvas/primitive.js
@@ -9,38 +9,38 @@ const WebGLPrimitivesType = {
   "LINE_LOOP": 2,
   "LINE_STRIP": 3,
   "TRIANGLES": 4,
   "TRIANGLE_STRIP": 5,
   "TRIANGLE_FAN": 6
 };
 
 /**
- * A utility for monitoring WebGL primitive draws. Takes a `tabActor`
+ * A utility for monitoring WebGL primitive draws. Takes a `targetActor`
  * and monitors primitive draws over time.
  */
 const WebGLDrawArrays = "drawArrays";
 const WebGLDrawElements = "drawElements";
 
 exports.WebGLPrimitiveCounter = class WebGLPrimitiveCounter {
-  constructor(tabActor) {
-    this.tabActor = tabActor;
+  constructor(targetActor) {
+    this.targetActor = targetActor;
   }
 
   destroy() {}
 
   /**
    * Starts monitoring primitive draws, storing the primitives count per tick.
    */
   resetCounts() {
     this._tris = 0;
     this._vertices = 0;
     this._points = 0;
     this._lines = 0;
-    this._startTime = this.tabActor.docShell.now();
+    this._startTime = this.targetActor.docShell.now();
   }
 
   /**
    * Stops monitoring primitive draws, returning the recorded values.
    */
   getCounts() {
     const result = {
       tris: this._tris,
--- a/devtools/server/actors/chrome.js
+++ b/devtools/server/actors/chrome.js
@@ -2,64 +2,68 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { Ci } = require("chrome");
 const Services = require("Services");
 const { DebuggerServer } = require("../main");
-const { getChildDocShells, TabActor, tabPrototype } = require("./tab");
+const {
+  getChildDocShells,
+  BrowsingContextTargetActor,
+  browsingContextTargetPrototype
+} = require("devtools/server/actors/targets/browsing-context");
 const makeDebugger = require("./utils/make-debugger");
 
 const { extend } = require("devtools/shared/extend");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
-const { tabSpec } = require("devtools/shared/specs/tab");
+const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
 
 /**
- * Creates a TabActor for debugging all the chrome content in the
- * current process. Most of the implementation is inherited from TabActor.
- * ChromeActor is a child of RootActor, it can be instanciated via
- * RootActor.getProcess request.
- * ChromeActor exposes all tab actors via its form() request, like TabActor.
+ * Creates a target actor for debugging all the chrome content in the current process.
+ * Most of the implementation is inherited from BrowsingContextTargetActor. ChromeActor is
+ * a child of RootActor, it can be instantiated via RootActor.getProcess request.
+ * ChromeActor exposes all tab actors via its form() request, like
+ * BrowsingContextTargetActor.
  *
  * History lecture:
- * All tab actors used to also be registered as global actors,
- * so that the root actor was also exposing tab actors for the main process.
- * Tab actors ended up having RootActor as parent actor,
- * but more and more features of the tab actors were relying on TabActor.
- * So we are now exposing a process actor that offers the same API as TabActor
- * by inheriting its functionality.
- * Global actors are now only the actors that are meant to be global,
- * and are no longer related to any specific scope/document.
+ * All tab actors used to also be registered as global actors, so that the root actor was
+ * also exposing tab actors for the main process. Tab actors ended up having RootActor as
+ * parent actor, but more and more features of the tab actors were relying on
+ * BrowsingContextTargetActor. So we are now exposing a process actor that offers the same
+ * API as BrowsingContextTargetActor by inheriting its functionality. Global actors are
+ * now only the actors that are meant to be global, and are no longer related to any
+ * specific scope/document.
  *
  * @param connection DebuggerServerConnection
  *        The connection to the client.
  */
 
 /**
  * Protocol.js expects only the prototype object, and does not maintain the prototype
  * chain when it constructs the ActorClass. For this reason we are using `extend` to
- * maintain the properties of TabActor.prototype
+ * maintain the properties of BrowsingContextTargetActor.prototype
  * */
 
-const chromePrototype = extend({}, tabPrototype);
+const chromePrototype = extend({}, browsingContextTargetPrototype);
 
 chromePrototype.initialize = function(connection) {
-  TabActor.prototype.initialize.call(this, connection);
+  BrowsingContextTargetActor.prototype.initialize.call(this, connection);
+
   // This creates a Debugger instance for chrome debugging all globals.
   this.makeDebugger = makeDebugger.bind(null, {
     findDebuggees: dbg => dbg.findAllGlobals(),
     shouldAddNewGlobalAsDebuggee: () => true
   });
 
   // Ensure catching the creation of any new content docshell
   this.listenForNewDocShells = true;
 
-  // Defines the default docshell selected for the tab actor
+  // Defines the default docshell selected for the target actor
   let window = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
 
   // Default to any available top level window if there is no expected window
   // (for example when we open firefox with -webide argument)
   if (!window) {
     window = Services.wm.getMostRecentWindow(null);
   }
 
@@ -81,17 +85,17 @@ chromePrototype.initialize = function(co
     value: docShell,
     configurable: true
   });
 };
 
 chromePrototype.isRootActor = true;
 
 /**
- * Getter for the list of all docshells in this tabActor
+ * Getter for the list of all docshells in this targetActor
  * @return {Array}
  */
 Object.defineProperty(chromePrototype, "docShells", {
   get: function() {
     // Iterate over all top-level windows and all their docshells.
     let docShells = [];
     const e = Services.ww.getWindowEnumerator();
     while (e.hasMoreElements()) {
@@ -102,17 +106,17 @@ Object.defineProperty(chromePrototype, "
       docShells = docShells.concat(getChildDocShells(docShell));
     }
 
     return docShells;
   }
 });
 
 chromePrototype.observe = function(subject, topic, data) {
-  TabActor.prototype.observe.call(this, subject, topic, data);
+  BrowsingContextTargetActor.prototype.observe.call(this, subject, topic, data);
   if (!this.attached) {
     return;
   }
 
   subject.QueryInterface(Ci.nsIDocShell);
 
   if (topic == "chrome-webnavigation-create") {
     this._onDocShellCreated(subject);
@@ -121,17 +125,17 @@ chromePrototype.observe = function(subje
   }
 };
 
 chromePrototype._attach = function() {
   if (this.attached) {
     return false;
   }
 
-  TabActor.prototype._attach.call(this);
+  BrowsingContextTargetActor.prototype._attach.call(this);
 
   // Listen for any new/destroyed chrome docshell
   Services.obs.addObserver(this, "chrome-webnavigation-create");
   Services.obs.addObserver(this, "chrome-webnavigation-destroy");
 
   // Iterate over all top-level windows.
   const e = Services.ww.getWindowEnumerator();
   while (e.hasMoreElements()) {
@@ -163,17 +167,17 @@ chromePrototype._detach = function() {
                          .getInterface(Ci.nsIWebNavigation)
                          .QueryInterface(Ci.nsIDocShell);
     if (docShell == this.docShell) {
       continue;
     }
     this._progressListener.unwatch(docShell);
   }
 
-  TabActor.prototype._detach.call(this);
+  BrowsingContextTargetActor.prototype._detach.call(this);
   return undefined;
 };
 
 /* ThreadActor hooks. */
 
 /**
  * Prepare to enter a nested event loop by disabling debuggee events.
  */
@@ -201,9 +205,9 @@ chromePrototype.postNest = function(nest
                          .getInterface(Ci.nsIDOMWindowUtils);
     windowUtils.resumeTimeouts();
     windowUtils.suppressEventHandling(false);
   }
 };
 
 chromePrototype.typeName = "Chrome";
 exports.chromePrototype = chromePrototype;
-exports.ChromeActor = ActorClassWithSpec(tabSpec, chromePrototype);
+exports.ChromeActor = ActorClassWithSpec(browsingContextTargetSpec, chromePrototype);
--- a/devtools/server/actors/common.js
+++ b/devtools/server/actors/common.js
@@ -128,23 +128,23 @@ exports.ObservedActorFactory = ObservedA
  * Methods shared between RootActor and BrowserTabActor.
  */
 
 /**
  * Populate |this._extraActors| as specified by |factories|, reusing whatever
  * actors are already there. Add all actors in the final extra actors table to
  * |pool|.
  *
- * The root actor and the tab actor use this to instantiate actors that other
+ * The root actor and the target actor use this to instantiate actors that other
  * parts of the browser have specified with DebuggerServer.addTabActor and
  * DebuggerServer.addGlobalActor.
  *
  * @param factories
  *     An object whose own property names are the names of properties to add to
- *     some reply packet (say, a tab actor grip or the "listTabs" response
+ *     some reply packet (say, a target actor grip or the "listTabs" response
  *     form), and whose own property values are actor constructor functions, as
  *     documented for addTabActor and addGlobalActor.
  *
  * @param this
  *     The BrowserRootActor or BrowserTabActor with which the new actors will
  *     be associated. It should support whatever API the |factories|
  *     constructor functions might be interested in, as it is passed to them.
  *     For the sake of CommonCreateExtraActors itself, it should have at least
--- a/devtools/server/actors/content.js
+++ b/devtools/server/actors/content.js
@@ -1,52 +1,55 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var { Cr } = require("chrome");
-var { TabActor, tabPrototype } = require("devtools/server/actors/tab");
+var {
+  BrowsingContextTargetActor,
+  browsingContextTargetPrototype
+} = require("devtools/server/actors/targets/browsing-context");
 
 const { extend } = require("devtools/shared/extend");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
-const { tabSpec } = require("devtools/shared/specs/tab");
+const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
 
 /**
- * Tab actor for documents living in a child process.
+ * Target actor for documents living in a child process.
  *
- * Depends on TabActor, defined in tab.js.
+ * Depends on BrowsingContextTargetActor, defined in browsing-context.js.
  */
 
 /**
- * Creates a tab actor for handling requests to the single tab, like
+ * Creates a target actor for handling requests to the single tab, like
  * attaching and detaching. ContentActor respects the actor factories
  * registered with DebuggerServer.addTabActor.
  *
  * @param connection DebuggerServerConnection
  *        The conection to the client.
  * @param chromeGlobal
  *        The content script global holding |content| and |docShell| properties for a tab.
  * @param prefix
  *        the prefix used in protocol to create IDs for each actor.
- *        Used as ID identifying this particular TabActor from the parent process.
+ *        Used as ID identifying this particular target actor from the parent process.
  */
 
 /**
  * Protocol.js expects only the prototype object, and does not maintain the prototype
  * chain when it constructs the ActorClass. For this reason we are using `extend` to
- * maintain the properties of TabActor.prototype
- * */
+ * maintain the properties of BrowsingContextTargetActor.prototype
+ */
 
-const contentPrototype = extend({}, tabPrototype);
+const contentPrototype = extend({}, browsingContextTargetPrototype);
 
 contentPrototype.initialize = function(connection, chromeGlobal) {
   this._chromeGlobal = chromeGlobal;
-  TabActor.prototype.initialize.call(this, connection, chromeGlobal);
+  BrowsingContextTargetActor.prototype.initialize.call(this, connection, chromeGlobal);
   this.traits.reconfigure = false;
   this._sendForm = this._sendForm.bind(this);
   this._chromeGlobal.addMessageListener("debug:form", this._sendForm);
 
   Object.defineProperty(this, "docShell", {
     value: this._chromeGlobal.docShell,
     configurable: true
   });
@@ -70,22 +73,22 @@ contentPrototype.exit = function() {
       }
       // In some cases, especially when using messageManagers in non-e10s mode, we reach
       // this point with a dead messageManager which only throws errors but does not
       // seem to indicate in any other way that it is dead.
     }
     this._sendForm = null;
   }
 
-  TabActor.prototype.exit.call(this);
+  BrowsingContextTargetActor.prototype.exit.call(this);
 
   this._chromeGlobal = null;
 };
 
 /**
  * On navigation events, our URL and/or title may change, so we update our
  * counterpart in the parent process that participates in the tab list.
  */
 contentPrototype._sendForm = function() {
   this._chromeGlobal.sendAsyncMessage("debug:form", this.form());
 };
 
-exports.ContentActor = ActorClassWithSpec(tabSpec, contentPrototype);
+exports.ContentActor = ActorClassWithSpec(browsingContextTargetSpec, contentPrototype);
--- a/devtools/server/actors/csscoverage.js
+++ b/devtools/server/actors/csscoverage.js
@@ -57,30 +57,30 @@ const l10n = exports.l10n = {
  *         isUsed: true,
  *         presentOn: Set([ "http://eg.com/page1.html", ... ]),
  *         preLoadOn: Set([ "http://eg.com/page1.html" ]),
  *         isError: false,
  *       }, ...
  *     });
  */
 var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
 
-    this._tabActor = tabActor;
+    this._targetActor = targetActor;
     this._running = false;
 
     this._onTabLoad = this._onTabLoad.bind(this);
     this._onChange = this._onChange.bind(this);
 
     this._notifyOn = Ci.nsIWebProgress.NOTIFY_STATE_ALL;
   },
 
   destroy: function() {
-    this._tabActor = undefined;
+    this._targetActor = undefined;
 
     delete this._onTabLoad;
     delete this._onChange;
 
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
@@ -112,26 +112,26 @@ var CSSUsageActor = protocol.ActorClassW
         if (isStop && isWindow) {
           this._onTabLoad(progress.DOMWindow.document);
         }
       },
 
       destroy: () => {}
     };
 
-    this._progress = this._tabActor.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
+    this._progress = this._targetActor.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                             .getInterface(Ci.nsIWebProgress);
     this._progress.addProgressListener(this._progressListener, this._notifyOn);
 
     if (noreload) {
       // If we're not starting by reloading the page, then pretend that onload
       // has just happened.
-      this._onTabLoad(this._tabActor.window.document);
+      this._onTabLoad(this._targetActor.window.document);
     } else {
-      this._tabActor.window.location.reload();
+      this._targetActor.window.location.reload();
     }
 
     this.emit("state-change", { isRunning: true });
   },
 
   /**
    * Cease recording usage data
    */
@@ -162,18 +162,18 @@ var CSSUsageActor = protocol.ActorClassW
     if (this._running) {
       throw new Error(l10n.lookup("csscoverageRunningError"));
     }
 
     this._isOneShot = true;
     this._visitedPages = new Set();
     this._knownRules = new Map();
 
-    this._populateKnownRules(this._tabActor.window.document);
-    this._updateUsage(this._tabActor.window.document, false);
+    this._populateKnownRules(this._targetActor.window.document);
+    this._updateUsage(this._targetActor.window.document, false);
   },
 
   /**
    * Called by the ProgressListener to simulate a "load" event
    */
   _onTabLoad: function(document) {
     this._populateKnownRules(document);
     this._updateUsage(document, true);
--- a/devtools/server/actors/emulation.js
+++ b/devtools/server/actors/emulation.js
@@ -19,44 +19,44 @@ const { TouchSimulator } = require("devt
  * that property to the way it was found before the change.
  *
  * A subtle aspect of the code below is that all get* methods must return non-undefined
  * values, so that the absence of a previous value can be distinguished from the value for
  * "no override" for each of the properties.
  */
 const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
 
-  initialize(conn, tabActor) {
+  initialize(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
-    this.docShell = tabActor.docShell;
-    this.touchSimulator = new TouchSimulator(tabActor.chromeEventHandler);
+    this.targetActor = targetActor;
+    this.docShell = targetActor.docShell;
+    this.touchSimulator = new TouchSimulator(targetActor.chromeEventHandler);
   },
 
   destroy() {
     this.clearDPPXOverride();
     this.clearNetworkThrottling();
     this.clearTouchEventsOverride();
     this.clearUserAgentOverride();
-    this.tabActor = null;
+    this.targetActor = null;
     this.docShell = null;
     this.touchSimulator = null;
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
    * Retrieve the console actor for this tab.  This allows us to expose network throttling
    * as part of emulation settings, even though it's internally connected to the network
    * monitor, which for historical reasons is part of the console actor.
    */
   get _consoleActor() {
-    if (this.tabActor.exited) {
+    if (this.targetActor.exited) {
       return null;
     }
-    const form = this.tabActor.form();
+    const form = this.targetActor.form();
     return this.conn._getOrCreateActor(form.consoleActor);
   },
 
   /* DPPX override */
 
   _previousDPPXOverride: undefined,
 
   setDPPXOverride(dppx) {
--- a/devtools/server/actors/framerate.js
+++ b/devtools/server/actors/framerate.js
@@ -10,19 +10,19 @@ const { framerateSpec } = require("devto
 
 /**
  * An actor wrapper around Framerate. Uses exposed
  * methods via bridge and provides RDP definitions.
  *
  * @see devtools/server/performance/framerate.js for documentation.
  */
 exports.FramerateActor = ActorClassWithSpec(framerateSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
-    this.bridge = new Framerate(tabActor);
+    this.bridge = new Framerate(targetActor);
   },
   destroy: function(conn) {
     Actor.prototype.destroy.call(this, conn);
     this.bridge.destroy();
   },
 
   startRecording: actorBridgeWithSpec("startRecording"),
   stopRecording: actorBridgeWithSpec("stopRecording"),
--- a/devtools/server/actors/gcli.js
+++ b/devtools/server/actors/gcli.js
@@ -7,45 +7,45 @@
 const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
 const { gcliSpec } = require("devtools/shared/specs/gcli");
 const { createSystem } = require("gcli/system");
 
 /**
  * Manage remote connections that want to talk to GCLI
  */
 const GcliActor = ActorClassWithSpec(gcliSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
 
     this._commandsChanged = this._commandsChanged.bind(this);
 
-    this._tabActor = tabActor;
+    this._targetActor = targetActor;
     // see _getRequisition()
     this._requisitionPromise = undefined;
   },
 
   destroy: function() {
     Actor.prototype.destroy.call(this);
 
     // If _getRequisition has not been called, just bail quickly
     if (this._requisitionPromise == null) {
       this._commandsChanged = undefined;
-      this._tabActor = undefined;
+      this._targetActor = undefined;
       return Promise.resolve();
     }
 
     return this._getRequisition().then(requisition => {
       requisition.destroy();
 
       this._system.commands.onCommandsChange.remove(this._commandsChanged);
       this._system.destroy();
       this._system = undefined;
 
       this._requisitionPromise = undefined;
-      this._tabActor = undefined;
+      this._targetActor = undefined;
 
       this._commandsChanged = undefined;
     });
   },
 
   /**
    * Load a module into the requisition
    */
@@ -165,26 +165,26 @@ const GcliActor = ActorClassWithSpec(gcl
       });
     });
   },
 
   /**
    * Lazy init for a Requisition
    */
   _getRequisition: function() {
-    if (this._tabActor == null) {
+    if (this._targetActor == null) {
       throw new Error("GcliActor used post-destroy");
     }
 
     if (this._requisitionPromise != null) {
       return this._requisitionPromise;
     }
 
     const Requisition = require("gcli/cli").Requisition;
-    const tabActor = this._tabActor;
+    const targetActor = this._targetActor;
 
     this._system = createSystem({ location: "server" });
     this._system.commands.onCommandsChange.add(this._commandsChanged);
 
     const gcliInit = require("devtools/shared/gcli/commands/index");
     gcliInit.addAllItemsByModule(this._system);
 
     // this._requisitionPromise should be created synchronously with the call
@@ -198,21 +198,21 @@ const GcliActor = ActorClassWithSpec(gcl
         },
 
         get chromeDocument() {
           throw new Error("environment.chromeDocument is not available in runAt:server" +
             " commands");
         },
 
         get window() {
-          return tabActor.window;
+          return targetActor.window;
         },
 
         get document() {
-          return tabActor.window && tabActor.window.document;
+          return targetActor.window && targetActor.window.document;
         }
       };
 
       return new Requisition(this._system, { environment: environment });
     });
 
     return this._requisitionPromise;
   },
--- a/devtools/server/actors/highlighters.js
+++ b/devtools/server/actors/highlighters.js
@@ -81,51 +81,51 @@ exports.register = register;
  */
 exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
   initialize: function(inspector, autohide) {
     protocol.Actor.prototype.initialize.call(this, null);
 
     this._autohide = autohide;
     this._inspector = inspector;
     this._walker = this._inspector.walker;
-    this._tabActor = this._inspector.tabActor;
+    this._targetActor = this._inspector.targetActor;
     this._highlighterEnv = new HighlighterEnvironment();
-    this._highlighterEnv.initFromTabActor(this._tabActor);
+    this._highlighterEnv.initFromTargetActor(this._targetActor);
 
     this._highlighterReady = this._highlighterReady.bind(this);
     this._highlighterHidden = this._highlighterHidden.bind(this);
     this._onNavigate = this._onNavigate.bind(this);
 
-    const doc = this._tabActor.window.document;
+    const doc = this._targetActor.window.document;
     // Only try to create the highlighter when the document is loaded,
     // otherwise, wait for the navigate event to fire.
     if (doc.documentElement && doc.readyState != "uninitialized") {
       this._createHighlighter();
     }
 
     // Listen to navigation events to switch from the BoxModelHighlighter to the
     // SimpleOutlineHighlighter, and back, if the top level window changes.
-    this._tabActor.on("navigate", this._onNavigate);
+    this._targetActor.on("navigate", this._onNavigate);
   },
 
   get conn() {
     return this._inspector && this._inspector.conn;
   },
 
   form: function() {
     return {
       actor: this.actorID,
       traits: {
         autoHideOnDestroy: true
       }
     };
   },
 
   _createHighlighter: function() {
-    this._isPreviousWindowXUL = isXUL(this._tabActor.window);
+    this._isPreviousWindowXUL = isXUL(this._targetActor.window);
 
     if (!this._isPreviousWindowXUL) {
       this._highlighter = new BoxModelHighlighter(this._highlighterEnv,
                                                   this._inspector);
       this._highlighter.on("ready", this._highlighterReady);
       this._highlighter.on("hide", this._highlighterHidden);
     } else {
       this._highlighter = new SimpleOutlineHighlighter(this._highlighterEnv);
@@ -141,41 +141,41 @@ exports.HighlighterActor = protocol.Acto
       this._highlighter.destroy();
       this._highlighter = null;
     }
   },
 
   _onNavigate: function({isTopLevel}) {
     // Skip navigation events for non top-level windows, or if the document
     // doesn't exist anymore.
-    if (!isTopLevel || !this._tabActor.window.document.documentElement) {
+    if (!isTopLevel || !this._targetActor.window.document.documentElement) {
       return;
     }
 
     // Only rebuild the highlighter if the window type changed.
-    if (isXUL(this._tabActor.window) !== this._isPreviousWindowXUL) {
+    if (isXUL(this._targetActor.window) !== this._isPreviousWindowXUL) {
       this._destroyHighlighter();
       this._createHighlighter();
     }
   },
 
   destroy: function() {
     protocol.Actor.prototype.destroy.call(this);
 
     this.hideBoxModel();
     this._destroyHighlighter();
-    this._tabActor.off("navigate", this._onNavigate);
+    this._targetActor.off("navigate", this._onNavigate);
 
     this._highlighterEnv.destroy();
     this._highlighterEnv = null;
 
     this._autohide = null;
     this._inspector = null;
     this._walker = null;
-    this._tabActor = null;
+    this._targetActor = null;
   },
 
   /**
    * Display the box model highlighting on a given NodeActor.
    * There is only one instance of the box model highlighter, so calling this
    * method several times won't display several highlighters, it will just move
    * the highlighter instance to these nodes.
    *
@@ -255,17 +255,17 @@ exports.HighlighterActor = protocol.Acto
         this._walker.emit("picker-node-previewed",
           this._findAndAttachElement(event));
         return;
       }
 
       this._stopPickerListeners();
       this._isPicking = false;
       if (this._autohide) {
-        this._tabActor.window.setTimeout(() => {
+        this._targetActor.window.setTimeout(() => {
           this._highlighter.hide();
         }, HIGHLIGHTER_PICKED_TIMER);
       }
       if (!this._currentNode) {
         this._currentNode = this._findAndAttachElement(event);
       }
       this._walker.emit("picker-node-picked", this._currentNode);
     };
@@ -431,17 +431,17 @@ exports.HighlighterActor = protocol.Acto
 /**
  * A generic highlighter actor class that instantiate a highlighter given its
  * type name and allows to show/hide it.
  */
 exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSpec, {
   /**
    * Create a highlighter instance given its typename
    * The typename must be one of HIGHLIGHTER_CLASSES and the class must
-   * implement constructor(tabActor), show(node), hide(), destroy()
+   * implement constructor(targetActor), show(node), hide(), destroy()
    */
   initialize: function(parent, typeName) {
     protocol.Actor.prototype.initialize.call(this, null);
 
     this._parent = parent;
 
     const modulePath = highlighterTypes.get(typeName);
     if (!modulePath) {
@@ -450,19 +450,19 @@ exports.CustomHighlighterActor = protoco
       throw new Error(`${typeName} isn't a valid highlighter class (${list})`);
     }
 
     const constructor = require("./highlighters/" + modulePath)[typeName];
     // The assumption is that custom highlighters either need the canvasframe
     // container to append their elements and thus a non-XUL window or they have
     // to define a static XULSupported flag that indicates that the highlighter
     // supports XUL windows. Otherwise, bail out.
-    if (!isXUL(this._parent.tabActor.window) || constructor.XULSupported) {
+    if (!isXUL(this._parent.targetActor.window) || constructor.XULSupported) {
       this._highlighterEnv = new HighlighterEnvironment();
-      this._highlighterEnv.initFromTabActor(parent.tabActor);
+      this._highlighterEnv.initFromTargetActor(parent.targetActor);
       this._highlighter = new constructor(this._highlighterEnv);
       if (this._highlighter.on) {
         this._highlighter.on("highlighter-event", this._onHighlighterEvent.bind(this));
       }
     } else {
       throw new Error("Custom " + typeName +
         "highlighter cannot be created in a XUL window");
     }
@@ -540,41 +540,41 @@ exports.CustomHighlighterActor = protoco
     }
   }
 });
 
 /**
  * The HighlighterEnvironment is an object that holds all the required data for
  * highlighters to work: the window, docShell, event listener target, ...
  * It also emits "will-navigate", "navigate" and "window-ready" events,
- * similarly to the TabActor.
+ * similarly to the BrowsingContextTargetActor.
  *
- * It can be initialized either from a TabActor (which is the most frequent way
- * of using it, since highlighters are usually initialized by the
- * HighlighterActor or CustomHighlighterActor, which have a tabActor reference).
- * It can also be initialized just with a window object (which is useful for
- * when a highlighter is used outside of the debugger server context, for
- * instance from a gcli command).
+ * It can be initialized either from a BrowsingContextTargetActor (which is the
+ * most frequent way of using it, since highlighters are usually initialized by
+ * the HighlighterActor or CustomHighlighterActor, which have a targetActor
+ * reference). It can also be initialized just with a window object (which is
+ * useful for when a highlighter is used outside of the debugger server context,
+ * for instance from a gcli command).
  */
 function HighlighterEnvironment() {
-  this.relayTabActorWindowReady = this.relayTabActorWindowReady.bind(this);
-  this.relayTabActorNavigate = this.relayTabActorNavigate.bind(this);
-  this.relayTabActorWillNavigate = this.relayTabActorWillNavigate.bind(this);
+  this.relayTargetActorWindowReady = this.relayTargetActorWindowReady.bind(this);
+  this.relayTargetActorNavigate = this.relayTargetActorNavigate.bind(this);
+  this.relayTargetActorWillNavigate = this.relayTargetActorWillNavigate.bind(this);
 
   EventEmitter.decorate(this);
 }
 
 exports.HighlighterEnvironment = HighlighterEnvironment;
 
 HighlighterEnvironment.prototype = {
-  initFromTabActor: function(tabActor) {
-    this._tabActor = tabActor;
-    this._tabActor.on("window-ready", this.relayTabActorWindowReady);
-    this._tabActor.on("navigate", this.relayTabActorNavigate);
-    this._tabActor.on("will-navigate", this.relayTabActorWillNavigate);
+  initFromTargetActor: function(targetActor) {
+    this._targetActor = targetActor;
+    this._targetActor.on("window-ready", this.relayTargetActorWindowReady);
+    this._targetActor.on("navigate", this.relayTargetActorNavigate);
+    this._targetActor.on("will-navigate", this.relayTargetActorWillNavigate);
   },
 
   initFromWindow: function(win) {
     this._win = win;
 
     // We need a progress listener to know when the window will navigate/has
     // navigated.
     const self = this;
@@ -612,29 +612,29 @@ HighlighterEnvironment.prototype = {
     };
 
     this.webProgress.addProgressListener(this.listener,
       Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
       Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
   },
 
   get isInitialized() {
-    return this._win || this._tabActor;
+    return this._win || this._targetActor;
   },
 
   get isXUL() {
     return isXUL(this.window);
   },
 
   get window() {
     if (!this.isInitialized) {
-      throw new Error("Initialize HighlighterEnvironment with a tabActor " +
+      throw new Error("Initialize HighlighterEnvironment with a targetActor " +
         "or window first");
     }
-    const win = this._tabActor ? this._tabActor.window : this._win;
+    const win = this._targetActor ? this._targetActor.window : this._win;
 
     return Cu.isDeadWrapper(win) ? null : win;
   },
 
   get document() {
     return this.window && this.window.document;
   },
 
@@ -648,64 +648,63 @@ HighlighterEnvironment.prototype = {
   get webProgress() {
     return this.docShell &&
            this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIWebProgress);
   },
 
   /**
    * Get the right target for listening to events on the page.
-   * - If the environment was initialized from a TabActor *and* if we're in the
-   *   Browser Toolbox (to inspect firefox desktop): the tabActor is the
-   *   RootActor, in which case, the window property can be used to listen to
-   *   events.
-   * - With firefox desktop, that tabActor is a BrowserTabActor, and with B2G,
-   *   a ContentActor (which overrides BrowserTabActor). In both cases we use
-   *   the chromeEventHandler which gives us a target we can use to listen to
+   * - If the environment was initialized from a BrowsingContextTargetActor
+   *   *and* if we're in the Browser Toolbox (to inspect Firefox Desktop): the
+   *   targetActor is the RootActor, in which case, the window property can be
+   *   used to listen to events.
+   * - With Firefox Desktop, the targetActor is a ContentActor, and we use the
+   *   chromeEventHandler which gives us a target we can use to listen to
    *   events, even from nested iframes.
    * - If the environment was initialized from a window, we also use the
    *   chromeEventHandler.
    */
   get pageListenerTarget() {
-    if (this._tabActor && this._tabActor.isRootActor) {
+    if (this._targetActor && this._targetActor.isRootActor) {
       return this.window;
     }
     return this.docShell && this.docShell.chromeEventHandler;
   },
 
-  relayTabActorWindowReady: function(data) {
+  relayTargetActorWindowReady: function(data) {
     this.emit("window-ready", data);
   },
 
-  relayTabActorNavigate: function(data) {
+  relayTargetActorNavigate: function(data) {
     this.emit("navigate", data);
   },
 
-  relayTabActorWillNavigate: function(data) {
+  relayTargetActorWillNavigate: function(data) {
     this.emit("will-navigate", data);
   },
 
   destroy: function() {
-    if (this._tabActor) {
-      this._tabActor.off("window-ready", this.relayTabActorWindowReady);
-      this._tabActor.off("navigate", this.relayTabActorNavigate);
-      this._tabActor.off("will-navigate", this.relayTabActorWillNavigate);
+    if (this._targetActor) {
+      this._targetActor.off("window-ready", this.relayTargetActorWindowReady);
+      this._targetActor.off("navigate", this.relayTargetActorNavigate);
+      this._targetActor.off("will-navigate", this.relayTargetActorWillNavigate);
     }
 
     // In case the environment was initialized from a window, we need to remove
     // the progress listener.
     if (this._win) {
       try {
         this.webProgress.removeProgressListener(this.listener);
       } catch (e) {
         // Which may fail in case the window was already destroyed.
       }
     }
 
-    this._tabActor = null;
+    this._targetActor = null;
     this._win = null;
   }
 };
 
 register("BoxModelHighlighter", "box-model");
 register("CssGridHighlighter", "css-grid");
 register("CssTransformHighlighter", "css-transform");
 register("EyeDropper", "eye-dropper");
--- a/devtools/server/actors/inspector/inspector.js
+++ b/devtools/server/actors/inspector/inspector.js
@@ -69,54 +69,54 @@ loader.lazyRequireGetter(this, "Highligh
 const SVG_NS = "http://www.w3.org/2000/svg";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /**
  * Server side of the inspector actor, which is used to create
  * inspector-related actors, including the walker.
  */
 exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
 
     this._onColorPicked = this._onColorPicked.bind(this);
     this._onColorPickCanceled = this._onColorPickCanceled.bind(this);
     this.destroyEyeDropper = this.destroyEyeDropper.bind(this);
   },
 
   destroy: function() {
     protocol.Actor.prototype.destroy.call(this);
 
     this.destroyEyeDropper();
 
     this._highlighterPromise = null;
     this._pageStylePromise = null;
     this._walkerPromise = null;
     this.walker = null;
-    this.tabActor = null;
+    this.targetActor = null;
   },
 
   get window() {
-    return this.tabActor.window;
+    return this.targetActor.window;
   },
 
   getWalker: function(options = {}) {
     if (this._walkerPromise) {
       return this._walkerPromise;
     }
 
     const deferred = defer();
     this._walkerPromise = deferred.promise;
 
     const window = this.window;
     const domReady = () => {
-      const tabActor = this.tabActor;
+      const targetActor = this.targetActor;
       window.removeEventListener("DOMContentLoaded", domReady, true);
-      this.walker = WalkerActor(this.conn, tabActor, options);
+      this.walker = WalkerActor(this.conn, targetActor, options);
       this.manage(this.walker);
       this.walker.once("destroyed", () => {
         this._walkerPromise = null;
         this._pageStylePromise = null;
       });
       deferred.resolve(this.walker);
     };
 
@@ -233,17 +233,17 @@ exports.InspectorActor = protocol.ActorC
 
   /**
    * Create an instance of the eye-dropper highlighter and store it on this._eyeDropper.
    * Note that for now, a new instance is created every time to deal with page navigation.
    */
   createEyeDropper: function() {
     this.destroyEyeDropper();
     this._highlighterEnv = new HighlighterEnvironment();
-    this._highlighterEnv.initFromTabActor(this.tabActor);
+    this._highlighterEnv.initFromTargetActor(this.targetActor);
     this._eyeDropper = new EyeDropper(this._highlighterEnv);
   },
 
   /**
    * Destroy the current eye-dropper highlighter instance.
    */
   destroyEyeDropper: function() {
     if (this._eyeDropper) {
@@ -261,41 +261,41 @@ exports.InspectorActor = protocol.ActorC
    * cancels the picker.
    * @param {Object} options
    */
   pickColorFromPage: function(options) {
     this.createEyeDropper();
     this._eyeDropper.show(this.window.document.documentElement, options);
     this._eyeDropper.once("selected", this._onColorPicked);
     this._eyeDropper.once("canceled", this._onColorPickCanceled);
-    this.tabActor.once("will-navigate", this.destroyEyeDropper);
+    this.targetActor.once("will-navigate", this.destroyEyeDropper);
   },
 
   /**
    * After the pickColorFromPage method is called, the only way to dismiss the eye-dropper
    * highlighter is for the user to click in the page and select a color. If you need to
    * dismiss the eye-dropper programatically instead, use this method.
    */
   cancelPickColorFromPage: function() {
     if (this._eyeDropper) {
       this._eyeDropper.hide();
       this._eyeDropper.off("selected", this._onColorPicked);
       this._eyeDropper.off("canceled", this._onColorPickCanceled);
-      this.tabActor.off("will-navigate", this.destroyEyeDropper);
+      this.targetActor.off("will-navigate", this.destroyEyeDropper);
     }
   },
 
   /**
    * Check if the current document supports highlighters using a canvasFrame anonymous
    * content container (ie all highlighters except the SimpleOutlineHighlighter).
    * It is impossible to detect the feature programmatically as some document types simply
    * don't render the canvasFrame without throwing any error.
    */
   supportsHighlighters: function() {
-    const doc = this.tabActor.window.document;
+    const doc = this.targetActor.window.document;
     const ns = doc.documentElement.namespaceURI;
 
     // XUL documents do not support insertAnonymousContent().
     if (ns === XUL_NS) {
       return false;
     }
 
     // SVG documents do not render the canvasFrame (see Bug 1157592).
--- a/devtools/server/actors/inspector/node.js
+++ b/devtools/server/actors/inspector/node.js
@@ -332,17 +332,17 @@ const NodeActor = protocol.ActorClassWit
   /**
    * Gets event listeners and adds their information to the events array.
    *
    * @param  {Node} node
    *         Node for which we are to get listeners.
    */
   getEventListeners: function(node) {
     const parsers = this._eventParsers;
-    const dbg = this.parent().tabActor.makeDebugger();
+    const dbg = this.parent().targetActor.makeDebugger();
     const listenerArray = [];
 
     for (const [, {getListeners, normalizeListener}] of parsers) {
       try {
         const listeners = getListeners(node);
 
         if (!listeners) {
           continue;
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -108,20 +108,20 @@ exports.setValueSummaryLength = function
  * Server side of the DOM walker.
  */
 var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
   /**
    * Create the WalkerActor
    * @param DebuggerServerConnection conn
    *    The server connection.
    */
-  initialize: function(conn, tabActor, options) {
+  initialize: function(conn, targetActor, options) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
-    this.rootWin = tabActor.window;
+    this.targetActor = targetActor;
+    this.rootWin = targetActor.window;
     this.rootDoc = this.rootWin.document;
     this._refMap = new Map();
     this._pendingMutations = [];
     this._activePseudoClassLocks = new Set();
     this.showAllAnonymousContent = options.showAllAnonymousContent;
 
     this.walkerSearch = new WalkerSearch(this);
 
@@ -137,24 +137,24 @@ var WalkerActor = protocol.ActorClassWit
 
     this.onMutations = this.onMutations.bind(this);
     this.onSlotchange = this.onSlotchange.bind(this);
     this.onFrameLoad = this.onFrameLoad.bind(this);
     this.onFrameUnload = this.onFrameUnload.bind(this);
     this._throttledEmitNewMutations = throttle(this._emitNewMutations.bind(this),
       MUTATIONS_THROTTLING_DELAY);
 
-    tabActor.on("will-navigate", this.onFrameUnload);
-    tabActor.on("window-ready", this.onFrameLoad);
+    targetActor.on("will-navigate", this.onFrameUnload);
+    targetActor.on("window-ready", this.onFrameLoad);
 
     // Ensure that the root document node actor is ready and
     // managed.
     this.rootNode = this.document();
 
-    this.layoutChangeObserver = getLayoutChangesObserver(this.tabActor);
+    this.layoutChangeObserver = getLayoutChangesObserver(this.targetActor);
     this._onReflows = this._onReflows.bind(this);
     this.layoutChangeObserver.on("reflows", this._onReflows);
     this._onResize = this._onResize.bind(this);
     this.layoutChangeObserver.on("resize", this._onResize);
 
     this._onEventListenerChange = this._onEventListenerChange.bind(this);
     eventListenerService.addListenerChangeListener(this._onEventListenerChange);
   },
@@ -226,36 +226,36 @@ var WalkerActor = protocol.ActorClassWit
       this.rootWin = null;
       this.rootDoc = null;
       this.rootNode = null;
       this.layoutHelpers = null;
       this._orphaned = null;
       this._retainedOrphans = null;
       this._refMap = null;
 
-      this.tabActor.off("will-navigate", this.onFrameUnload);
-      this.tabActor.off("window-ready", this.onFrameLoad);
+      this.targetActor.off("will-navigate", this.onFrameUnload);
+      this.targetActor.off("window-ready", this.onFrameLoad);
 
       this.onFrameLoad = null;
       this.onFrameUnload = null;
 
       this.walkerSearch.destroy();
 
       this.layoutChangeObserver.off("reflows", this._onReflows);
       this.layoutChangeObserver.off("resize", this._onResize);
       this.layoutChangeObserver = null;
-      releaseLayoutChangesObserver(this.tabActor);
+      releaseLayoutChangesObserver(this.targetActor);
 
       eventListenerService.removeListenerChangeListener(
         this._onEventListenerChange);
 
       this.onMutations = null;
 
       this.layoutActor = null;
-      this.tabActor = null;
+      this.targetActor = null;
 
       this.emit("destroyed");
     } catch (e) {
       console.error(e);
     }
   },
 
   release: function() {},
@@ -848,17 +848,17 @@ var WalkerActor = protocol.ActorClassWit
    * Get a list of nodes that match the given selector in all known frames of
    * the current content page.
    * @param {String} selector.
    * @return {Array}
    */
   _multiFrameQuerySelectorAll: function(selector) {
     let nodes = [];
 
-    for (const {document} of this.tabActor.windows) {
+    for (const {document} of this.targetActor.windows) {
       try {
         nodes = [...nodes, ...document.querySelectorAll(selector)];
       } catch (e) {
         // Bad selector. Do nothing as the selector can come from a searchbox.
       }
     }
 
     return nodes;
@@ -1984,17 +1984,17 @@ var WalkerActor = protocol.ActorClassWit
   /**
    * Returns an instance of the LayoutActor that is used to retrieve CSS layout-related
    * information.
    *
    * @return {LayoutActor}
    */
   getLayoutInspector: function() {
     if (!this.layoutActor) {
-      this.layoutActor = new LayoutActor(this.conn, this.tabActor, this);
+      this.layoutActor = new LayoutActor(this.conn, this.targetActor, this);
     }
 
     return this.layoutActor;
   },
 
   /**
    * Returns the offset parent DOMNode of the given node if it exists, otherwise, it
    * returns null.
--- a/devtools/server/actors/layout.js
+++ b/devtools/server/actors/layout.js
@@ -122,27 +122,27 @@ const GridActor = ActorClassWithSpec(gri
     return form;
   },
 });
 
 /**
  * The CSS layout actor provides layout information for the given document.
  */
 const LayoutActor = ActorClassWithSpec(layoutSpec, {
-  initialize(conn, tabActor, walker) {
+  initialize(conn, targetActor, walker) {
     Actor.prototype.initialize.call(this, conn);
 
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
     this.walker = walker;
   },
 
   destroy() {
     Actor.prototype.destroy.call(this);
 
-    this.tabActor = null;
+    this.targetActor = null;
     this.walker = null;
   },
 
   /**
    * Helper function for getCurrentGrid and getCurrentFlexbox. Returns the grid or
    * flex container (whichever is requested) found by iterating on the given selected
    * node. The current node can be a grid/flex container or grid/flex item. If it is a
    * grid/flex item, returns the parent grid/flex container. Otherwise, returns null
--- a/devtools/server/actors/moz.build
+++ b/devtools/server/actors/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'canvas',
     'emulation',
     'highlighters',
     'inspector',
     'object',
+    'targets',
     'utils',
     'webconsole',
     'worker',
 ]
 
 DevToolsModules(
     'accessibility-parent.js',
     'accessibility.js',
@@ -58,17 +59,16 @@ DevToolsModules(
     'promises.js',
     'reflow.js',
     'root.js',
     'source.js',
     'storage.js',
     'string.js',
     'styles.js',
     'stylesheets.js',
-    'tab.js',
     'thread.js',
     'timeline.js',
     'webaudio.js',
     'webbrowser.js',
     'webconsole.js',
     'webextension-inspected-window.js',
     'webextension-parent.js',
     'webextension.js',
--- a/devtools/server/actors/performance.js
+++ b/devtools/server/actors/performance.js
@@ -36,27 +36,27 @@ var PerformanceActor = ActorClassWithSpe
       withMemory: true,
       withFrames: true,
       withGCEvents: true,
       withDocLoadingEvents: true,
       withAllocations: true,
     },
   },
 
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     Actor.prototype.initialize.call(this, conn);
 
     this._onRecordingStarted = this._onRecordingStarted.bind(this);
     this._onRecordingStopping = this._onRecordingStopping.bind(this);
     this._onRecordingStopped = this._onRecordingStopped.bind(this);
     this._onProfilerStatus = this._onProfilerStatus.bind(this);
     this._onTimelineData = this._onTimelineData.bind(this);
     this._onConsoleProfileStart = this._onConsoleProfileStart.bind(this);
 
-    this.bridge = new PerformanceRecorder(conn, tabActor);
+    this.bridge = new PerformanceRecorder(conn, targetActor);
 
     this.bridge.on("recording-started", this._onRecordingStarted);
     this.bridge.on("recording-stopping", this._onRecordingStopping);
     this.bridge.on("recording-stopped", this._onRecordingStopped);
     this.bridge.on("profiler-status", this._onProfilerStatus);
     this.bridge.on("timeline-data", this._onTimelineData);
     this.bridge.on("console-profile-start", this._onConsoleProfileStart);
   },
--- a/devtools/server/actors/promises.js
+++ b/devtools/server/actors/promises.js
@@ -14,17 +14,17 @@ const EventEmitter = require("devtools/s
 
 /**
  * The Promises Actor provides support for getting the list of live promises and
  * observing changes to their settlement state.
  */
 var PromisesActor = protocol.ActorClassWithSpec(promisesSpec, {
   /**
    * @param conn DebuggerServerConnection.
-   * @param parentActor TabActor|RootActor
+   * @param parentActor BrowsingContextTargetActor|RootActor
    */
   initialize: function(conn, parentActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
 
     this.conn = conn;
     this.parentActor = parentActor;
     this.state = "detached";
     this._dbg = null;
--- a/devtools/server/actors/reflow.js
+++ b/devtools/server/actors/reflow.js
@@ -12,47 +12,47 @@
  *   its "reflows" events to clients.
  *
  * - LayoutChangesObserver: extends Observable and uses the ReflowObserver, to
  *   track reflows on the page.
  *   Used by the LayoutActor, but is also exported on the module, so can be used
  *   by any other actor that needs it.
  *
  * - Observable: A utility parent class, meant at being extended by classes that
- *   need a to observe something on the tabActor's windows.
+ *   need a to observe something on the targetActor's windows.
  *
  * - Dedicated observers: There's only one of them for now: ReflowObserver which
  *   listens to reflow events via the docshell,
  *   These dedicated classes are used by the LayoutChangesObserver.
  */
 
 const {Ci} = require("chrome");
 const ChromeUtils = require("ChromeUtils");
 const protocol = require("devtools/shared/protocol");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {reflowSpec} = require("devtools/shared/specs/reflow");
 
 /**
  * The reflow actor tracks reflows and emits events about them.
  */
 exports.ReflowActor = protocol.ActorClassWithSpec(reflowSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
 
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
     this._onReflow = this._onReflow.bind(this);
-    this.observer = getLayoutChangesObserver(tabActor);
+    this.observer = getLayoutChangesObserver(targetActor);
     this._isStarted = false;
   },
 
   destroy: function() {
     this.stop();
-    releaseLayoutChangesObserver(this.tabActor);
+    releaseLayoutChangesObserver(this.targetActor);
     this.observer = null;
-    this.tabActor = null;
+    this.targetActor = null;
 
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
    * Start tracking reflows and sending events to clients about them.
    * This is a oneway method, do not expect a response and it won't return a
    * promise.
@@ -80,29 +80,29 @@ exports.ReflowActor = protocol.ActorClas
     if (this._isStarted) {
       this.emit("reflows", reflows);
     }
   }
 });
 
 /**
  * Base class for all sorts of observers that need to listen to events on the
- * tabActor's windows.
- * @param {TabActor} tabActor
+ * targetActor's windows.
+ * @param {BrowsingContextTargetActor} targetActor
  * @param {Function} callback Executed everytime the observer observes something
  */
-function Observable(tabActor, callback) {
-  this.tabActor = tabActor;
+function Observable(targetActor, callback) {
+  this.targetActor = targetActor;
   this.callback = callback;
 
   this._onWindowReady = this._onWindowReady.bind(this);
   this._onWindowDestroyed = this._onWindowDestroyed.bind(this);
 
-  this.tabActor.on("window-ready", this._onWindowReady);
-  this.tabActor.on("window-destroyed", this._onWindowDestroyed);
+  this.targetActor.on("window-ready", this._onWindowReady);
+  this.targetActor.on("window-destroyed", this._onWindowDestroyed);
 }
 
 Observable.prototype = {
   /**
    * Is the observer currently observing
    */
   isObserving: false,
 
@@ -112,47 +112,47 @@ Observable.prototype = {
   destroy: function() {
     if (this.isDestroyed) {
       return;
     }
     this.isDestroyed = true;
 
     this.stop();
 
-    this.tabActor.off("window-ready", this._onWindowReady);
-    this.tabActor.off("window-destroyed", this._onWindowDestroyed);
+    this.targetActor.off("window-ready", this._onWindowReady);
+    this.targetActor.off("window-destroyed", this._onWindowDestroyed);
 
     this.callback = null;
-    this.tabActor = null;
+    this.targetActor = null;
   },
 
   /**
    * Start observing whatever it is this observer is supposed to observe
    */
   start: function() {
     if (this.isObserving) {
       return;
     }
     this.isObserving = true;
 
-    this._startListeners(this.tabActor.windows);
+    this._startListeners(this.targetActor.windows);
   },
 
   /**
    * Stop observing
    */
   stop: function() {
     if (!this.isObserving) {
       return;
     }
     this.isObserving = false;
 
-    if (this.tabActor.attached && this.tabActor.docShell) {
-      // It's only worth stopping if the tabActor is still attached
-      this._stopListeners(this.tabActor.windows);
+    if (this.targetActor.attached && this.targetActor.docShell) {
+      // It's only worth stopping if the targetActor is still attached
+      this._stopListeners(this.targetActor.windows);
     }
   },
 
   _onWindowReady: function({window}) {
     if (this.isObserving) {
       this._startListeners([window]);
     }
   },
@@ -203,41 +203,41 @@ exports.setIgnoreLayoutChanges = functio
 
 /**
  * The LayoutChangesObserver class is instantiated only once per given tab
  * and is used to track reflows and dom and style changes in that tab.
  * The LayoutActor uses this class to send reflow events to its clients.
  *
  * This class isn't exported on the module because it shouldn't be instantiated
  * to avoid creating several instances per tabs.
- * Use `getLayoutChangesObserver(tabActor)`
- * and `releaseLayoutChangesObserver(tabActor)`
+ * Use `getLayoutChangesObserver(targetActor)`
+ * and `releaseLayoutChangesObserver(targetActor)`
  * which are exported to get and release instances.
  *
  * The observer loops every EVENT_BATCHING_DELAY ms and checks if layout changes
  * have happened since the last loop iteration. If there are, it sends the
  * corresponding events:
  *
  * - "reflows", with an array of all the reflows that occured,
  * - "resizes", with an array of all the resizes that occured,
  *
- * @param {TabActor} tabActor
+ * @param {BrowsingContextTargetActor} targetActor
  */
-function LayoutChangesObserver(tabActor) {
-  this.tabActor = tabActor;
+function LayoutChangesObserver(targetActor) {
+  this.targetActor = targetActor;
 
   this._startEventLoop = this._startEventLoop.bind(this);
   this._onReflow = this._onReflow.bind(this);
   this._onResize = this._onResize.bind(this);
 
   // Creating the various observers we're going to need
   // For now, just the reflow observer, but later we can add markupMutation,
   // styleSheetChanges and styleRuleChanges
-  this.reflowObserver = new ReflowObserver(this.tabActor, this._onReflow);
-  this.resizeObserver = new WindowResizeObserver(this.tabActor, this._onResize);
+  this.reflowObserver = new ReflowObserver(this.targetActor, this._onReflow);
+  this.resizeObserver = new WindowResizeObserver(this.targetActor, this._onResize);
 
   EventEmitter.decorate(this);
 }
 
 exports.LayoutChangesObserver = LayoutChangesObserver;
 
 LayoutChangesObserver.prototype = {
   /**
@@ -257,17 +257,17 @@ LayoutChangesObserver.prototype = {
     this.isObserving = false;
 
     this.reflowObserver.destroy();
     this.reflows = null;
 
     this.resizeObserver.destroy();
     this.hasResized = false;
 
-    this.tabActor = null;
+    this.targetActor = null;
   },
 
   start: function() {
     if (this.isObserving) {
       return;
     }
     this.isObserving = true;
 
@@ -296,19 +296,19 @@ LayoutChangesObserver.prototype = {
   },
 
   /**
    * Start the event loop, which regularly checks if there are any observer
    * events to be sent as batched events
    * Calls itself in a loop.
    */
   _startEventLoop: function() {
-    // Avoid emitting events if the tabActor has been detached (may happen
+    // Avoid emitting events if the targetActor has been detached (may happen
     // during shutdown)
-    if (!this.tabActor || !this.tabActor.attached) {
+    if (!this.targetActor || !this.targetActor.attached) {
       return;
     }
 
     // Send any reflows we have
     if (this.reflows && this.reflows.length) {
       this.emit("reflows", this.reflows);
       this.reflows = [];
     }
@@ -369,68 +369,68 @@ LayoutChangesObserver.prototype = {
 
     this.hasResized = true;
   }
 };
 
 /**
  * Get a LayoutChangesObserver instance for a given window. This function makes
  * sure there is only one instance per window.
- * @param {TabActor} tabActor
+ * @param {BrowsingContextTargetActor} targetActor
  * @return {LayoutChangesObserver}
  */
 var observedWindows = new Map();
-function getLayoutChangesObserver(tabActor) {
-  const observerData = observedWindows.get(tabActor);
+function getLayoutChangesObserver(targetActor) {
+  const observerData = observedWindows.get(targetActor);
   if (observerData) {
     observerData.refCounting++;
     return observerData.observer;
   }
 
-  const obs = new LayoutChangesObserver(tabActor);
-  observedWindows.set(tabActor, {
+  const obs = new LayoutChangesObserver(targetActor);
+  observedWindows.set(targetActor, {
     observer: obs,
-    // counting references allows to stop the observer when no tabActor owns an
+    // counting references allows to stop the observer when no targetActor owns an
     // instance.
     refCounting: 1
   });
   obs.start();
   return obs;
 }
 exports.getLayoutChangesObserver = getLayoutChangesObserver;
 
 /**
  * Release a LayoutChangesObserver instance that was retrieved by
- * getLayoutChangesObserver. This is required to ensure the tabActor reference
+ * getLayoutChangesObserver. This is required to ensure the targetActor reference
  * is removed and the observer is eventually stopped and destroyed.
- * @param {TabActor} tabActor
+ * @param {BrowsingContextTargetActor} targetActor
  */
-function releaseLayoutChangesObserver(tabActor) {
-  const observerData = observedWindows.get(tabActor);
+function releaseLayoutChangesObserver(targetActor) {
+  const observerData = observedWindows.get(targetActor);
   if (!observerData) {
     return;
   }
 
   observerData.refCounting--;
   if (!observerData.refCounting) {
     observerData.observer.destroy();
-    observedWindows.delete(tabActor);
+    observedWindows.delete(targetActor);
   }
 }
 exports.releaseLayoutChangesObserver = releaseLayoutChangesObserver;
 
 /**
- * Reports any reflow that occurs in the tabActor's docshells.
+ * Reports any reflow that occurs in the targetActor's docshells.
  * @extends Observable
- * @param {TabActor} tabActor
+ * @param {BrowsingContextTargetActor} targetActor
  * @param {Function} callback Executed everytime a reflow occurs
  */
 class ReflowObserver extends Observable {
-  constructor(tabActor, callback) {
-    super(tabActor, callback);
+  constructor(targetActor, callback) {
+    super(targetActor, callback);
   }
 
   _startListeners(windows) {
     for (const window of windows) {
       const docshell = window.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIWebNavigation)
                      .QueryInterface(Ci.nsIDocShell);
       docshell.addWeakReflowObserver(this);
@@ -459,24 +459,24 @@ class ReflowObserver extends Observable 
     this.notifyCallback(start, end, true);
   }
 }
 
 ReflowObserver.prototype.QueryInterface = ChromeUtils
   .generateQI([Ci.nsIReflowObserver, Ci.nsISupportsWeakReference]);
 
 /**
- * Reports window resize events on the tabActor's windows.
+ * Reports window resize events on the targetActor's windows.
  * @extends Observable
- * @param {TabActor} tabActor
+ * @param {BrowsingContextTargetActor} targetActor
  * @param {Function} callback Executed everytime a resize occurs
  */
 class WindowResizeObserver extends Observable {
-  constructor(tabActor, callback) {
-    super(tabActor, callback);
+  constructor(targetActor, callback) {
+    super(targetActor, callback);
     this.onResize = this.onResize.bind(this);
   }
 
   _startListeners() {
     this.listenerTarget.addEventListener("resize", this.onResize);
   }
 
   _stopListeners() {
@@ -484,19 +484,16 @@ class WindowResizeObserver extends Obser
   }
 
   onResize() {
     this.notifyCallback();
   }
 
   get listenerTarget() {
     // For the rootActor, return its window.
-    if (this.tabActor.isRootActor) {
-      return this.tabActor.window;
+    if (this.targetActor.isRootActor) {
+      return this.targetActor.window;
     }
 
-    // Otherwise, get the tabActor's chromeEventHandler.
-    return this.tabActor.window.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIWebNavigation)
-                               .QueryInterface(Ci.nsIDocShell)
-                               .chromeEventHandler;
+    // Otherwise, get the targetActor's chromeEventHandler.
+    return this.targetActor.chromeEventHandler;
   }
 }
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -142,39 +142,39 @@ RootActor.prototype = {
     noBlackBoxing: false,
     noPrettyPrinting: false,
     // Trait added in Gecko 38, indicating that all features necessary for
     // grabbing allocations from the MemoryActor are available for the performance tool
     memoryActorAllocations: true,
     // Added in Firefox 40. Indicates that the backend supports registering custom
     // commands through the WebConsoleCommands API.
     webConsoleCommands: true,
-    // Whether root actor exposes tab actors and access to any window.
+    // Whether root actor exposes chrome target actors and access to any window.
     // If allowChromeProcess is true, you can:
     // * get a ChromeActor instance to debug chrome and any non-content
     //   resource via getProcess requests
     // * get a WindowActor instance to debug windows which could be chrome,
     //   like browser windows via getWindow requests
     // If allowChromeProcess is defined, but not true, it means that root actor
-    // no longer expose tab actors, but also that the above requests are
+    // no longer expose chrome target actors, but also that the above requests are
     // forbidden for security reasons.
     get allowChromeProcess() {
       return DebuggerServer.allowChromeProcess;
     },
     // Whether or not `getProfile()` supports specifying a `startTime`
     // and `endTime` to filter out samples. Fx40+
     profilerDataFilterable: true,
     // Whether or not the MemoryActor's heap snapshot abilities are
     // fully equipped to handle heap snapshots for the memory tool. Fx44+
     heapSnapshots: true,
     // Whether or not the timeline actor can emit DOMContentLoaded and Load
     // markers, currently in use by the network monitor. Fx45+
     documentLoadingMarkers: true,
     // Whether or not the webextension addon actor have to be connected
-    // to retrieve the extension child process tab actors.
+    // to retrieve the extension child process target actors.
     webExtensionAddonConnect: true,
   },
 
   /**
    * Return a 'hello' packet as specified by the Remote Debugging Protocol.
    */
   sayHello: function() {
     return {
@@ -568,17 +568,17 @@ RootActor.prototype = {
    */
   removeActorByName: function(name) {
     if (name in this._extraActors) {
       const actor = this._extraActors[name];
       if (this._globalActorPool.has(actor)) {
         this._globalActorPool.removeActor(actor);
       }
       if (this._tabActorPool) {
-        // Iterate over TabActor instances to also remove tab actors
+        // Iterate over BrowsingContextTargetActor instances to also remove tab actors
         // created during listTabs for each document.
         this._tabActorPool.forEach(tab => {
           tab.removeActorByName(name);
         });
       }
       delete this._extraActors[name];
     }
   }
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -2591,20 +2591,20 @@ const StorageActor = protocol.ActorClass
   get document() {
     return this.parentActor.window.document;
   },
 
   get windows() {
     return this.childWindowPool;
   },
 
-  initialize(conn, tabActor) {
+  initialize(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
 
-    this.parentActor = tabActor;
+    this.parentActor = targetActor;
 
     this.childActorPool = new Map();
     this.childWindowPool = new Set();
 
     // Fetch all the inner iframe windows in this tab.
     this.fetchChildWindows(this.parentActor.docShell);
 
     // Initialize the registered store types
@@ -2613,17 +2613,17 @@ const StorageActor = protocol.ActorClass
     }
 
     // Notifications that help us keep track of newly added windows and windows
     // that got removed
     Services.obs.addObserver(this, "content-document-global-created");
     Services.obs.addObserver(this, "inner-window-destroyed");
     this.onPageChange = this.onPageChange.bind(this);
 
-    const handler = tabActor.chromeEventHandler;
+    const handler = targetActor.chromeEventHandler;
     handler.addEventListener("pageshow", this.onPageChange, true);
     handler.addEventListener("pagehide", this.onPageChange, true);
 
     this.destroyed = false;
     this.boundUpdate = {};
   },
 
   destroy() {
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -69,30 +69,30 @@ var PageStyleActor = protocol.ActorClass
     this.refMap = new Map();
 
     // Maps document elements to style elements, used to add new rules.
     this.styleElements = new WeakMap();
 
     this.onFrameUnload = this.onFrameUnload.bind(this);
     this.onStyleSheetAdded = this.onStyleSheetAdded.bind(this);
 
-    this.inspector.tabActor.on("will-navigate", this.onFrameUnload);
-    this.inspector.tabActor.on("stylesheet-added", this.onStyleSheetAdded);
+    this.inspector.targetActor.on("will-navigate", this.onFrameUnload);
+    this.inspector.targetActor.on("stylesheet-added", this.onStyleSheetAdded);
 
     this._styleApplied = this._styleApplied.bind(this);
     this._watchedSheets = new Set();
   },
 
   destroy: function() {
     if (!this.walker) {
       return;
     }
     protocol.Actor.prototype.destroy.call(this);
-    this.inspector.tabActor.off("will-navigate", this.onFrameUnload);
-    this.inspector.tabActor.off("stylesheet-added", this.onStyleSheetAdded);
+    this.inspector.targetActor.off("will-navigate", this.onFrameUnload);
+    this.inspector.targetActor.off("stylesheet-added", this.onStyleSheetAdded);
     this.inspector = null;
     this.walker = null;
     this.refMap = null;
     this.cssLogic = null;
     this.styleElements = null;
 
     for (const sheet of this._watchedSheets) {
       sheet.off("style-applied", this._styleApplied);
@@ -106,17 +106,17 @@ var PageStyleActor = protocol.ActorClass
 
   form: function(detail) {
     if (detail === "actorid") {
       return this.actorID;
     }
 
     // We need to use CSS from the inspected window in order to use CSS.supports() and
     // detect the right platform features from there.
-    const CSS = this.inspector.tabActor.window.CSS;
+    const CSS = this.inspector.targetActor.window.CSS;
 
     return {
       actor: this.actorID,
       traits: {
         // Whether the actor has had bug 1103993 fixed, which means that the
         // getApplied method calls cssLogic.highlight(node) to recreate the
         // style cache. Clients requesting getApplied from actors that have not
         // been fixed must make sure cssLogic.highlight(node) was called before.
@@ -185,18 +185,18 @@ var PageStyleActor = protocol.ActorClass
   /**
    * Return or create a StyleSheetActor for the given CSSStyleSheet.
    * @param  {CSSStyleSheet} sheet
    *         The style sheet to create an actor for.
    * @return {StyleSheetActor}
    *         The actor for this style sheet
    */
   _sheetRef: function(sheet) {
-    const tabActor = this.inspector.tabActor;
-    const actor = tabActor.createStyleSheetActor(sheet);
+    const targetActor = this.inspector.targetActor;
+    const actor = targetActor.createStyleSheetActor(sheet);
     return actor;
   },
 
   /**
    * Get the computed style for a node.
    *
    * @param NodeActor node
    * @param object options
@@ -258,17 +258,17 @@ var PageStyleActor = protocol.ActorClass
    *   `includePreviews`: Whether to also return image previews of the fonts.
    *   `previewText`: The text to display in the previews.
    *   `previewFontSize`: The font size of the text in the previews.
    *
    * @returns object
    *   object with 'fontFaces', a list of fonts that apply to this node.
    */
   getAllUsedFontFaces: function(options) {
-    const windows = this.inspector.tabActor.windows;
+    const windows = this.inspector.targetActor.windows;
     let fontsList = [];
     for (const win of windows) {
       fontsList = [...fontsList,
                    ...this.getUsedFontFaces(win.document.body, options)];
     }
     return fontsList;
   },
 
@@ -1136,17 +1136,17 @@ var StyleRuleActor = protocol.ActorClass
     // have the client guess it.
     if (form.authoredText || form.cssText) {
       const declarations = parseNamedDeclarations(isCssPropertyKnown,
                                                 form.authoredText || form.cssText,
                                                 true);
 
       // We need to grab CSS from the window, since calling supports() on the
       // one from the current global will fail due to not being an HTML global.
-      const CSS = this.pageStyle.inspector.tabActor.window.CSS;
+      const CSS = this.pageStyle.inspector.targetActor.window.CSS;
       form.declarations = declarations.map(decl => {
         // Use the 1-arg CSS.supports() call so that we also accept !important
         // in the value.
         decl.isValid = CSS.supports(`${decl.name}:${decl.value}`);
         // Check property name. All valid CSS properties support "initial" as a value.
         decl.isNameValid = CSS.supports(decl.name, "initial");
         return decl;
       });
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -352,17 +352,17 @@ var StyleSheetActor = protocol.ActorClas
 
     // When the style is imported, `styleSheet.ownerNode` is null,
     // so retrieve the topmost parent style sheet which has an ownerNode
     let parentStyleSheet = styleSheet;
     while (parentStyleSheet.parentStyleSheet) {
       parentStyleSheet = parentStyleSheet.parentStyleSheet;
     }
     // When the style is injected via nsIDOMWindowUtils.loadSheet, even
-    // the parent style sheet has no owner, so default back to tab actor
+    // the parent style sheet has no owner, so default back to target actor
     // document
     if (parentStyleSheet.ownerNode) {
       this.ownerDocument = parentStyleSheet.ownerNode.ownerDocument;
     } else {
       this.ownerDocument = parentActor.window;
     }
   },
 
@@ -508,17 +508,17 @@ var StyleSheetActor = protocol.ActorClas
       this.text = text;
       return text;
     });
   },
 
   /**
    * Try to locate the console actor if it exists via our parent actor (the tab).
    *
-   * Keep this in sync with the TabActor version.
+   * Keep this in sync with the BrowsingContextTargetActor version.
    */
   get _consoleActor() {
     if (this.parentActor.exited) {
       return null;
     }
     const form = this.parentActor.form();
     return this.conn._getOrCreateActor(form.consoleActor);
   },
@@ -637,20 +637,20 @@ var StyleSheetsActor = protocol.ActorCla
   get document() {
     return this.window.document;
   },
 
   form: function() {
     return { actor: this.actorID };
   },
 
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, null);
 
-    this.parentActor = tabActor;
+    this.parentActor = targetActor;
 
     this._onNewStyleSheetActor = this._onNewStyleSheetActor.bind(this);
     this._onSheetAdded = this._onSheetAdded.bind(this);
     this._onWindowReady = this._onWindowReady.bind(this);
     this._transitionSheetLoaded = false;
 
     this.parentActor.on("stylesheet-added", this._onNewStyleSheetActor);
     this.parentActor.on("window-ready", this._onWindowReady);
@@ -681,27 +681,27 @@ var StyleSheetsActor = protocol.ActorCla
 
     this.parentActor.chromeEventHandler.removeEventListener("StyleSheetAdded",
                                                             this._onSheetAdded, true);
 
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
-   * Event handler that is called when a the tab actor emits window-ready.
+   * Event handler that is called when a the target actor emits window-ready.
    *
    * @param {Event} evt
    *        The triggering event.
    */
   _onWindowReady: function(evt) {
     this._addStyleSheets(evt.window);
   },
 
   /**
-   * Event handler that is called when a the tab actor emits stylesheet-added.
+   * Event handler that is called when a the target actor emits stylesheet-added.
    *
    * @param {StyleSheetActor} actor
    *        The new style sheet actor.
    */
   _onNewStyleSheetActor: function(actor) {
     // Forward it to the client side.
     this.emit("stylesheet-added", actor, this._nextStyleSheetIsNew);
     this._nextStyleSheetIsNew = false;
rename from devtools/server/actors/tab.js
rename to devtools/server/actors/targets/browsing-context.js
--- a/devtools/server/actors/tab.js
+++ b/devtools/server/actors/targets/browsing-context.js
@@ -1,39 +1,46 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 /* global XPCNativeWrapper */
 
-// For performance matters, this file should only be loaded in the targeted
-// document process. For example, it shouldn't be evaluated in the parent
-// process until we try to debug a document living in the parent process.
+/*
+ * BrowsingContextTargetActor is an abstract class used by target actors that hold
+ * documents, such as frames, chrome windows, etc.
+ *
+ * This class is extended by ContentActor, ChromeActor, and WindowActor.
+ *
+ * See devtools/docs/backend/actor-hierarchy.md for more details.
+ *
+ * For performance matters, this file should only be loaded in the targeted context's
+ * process. For example, it shouldn't be evaluated in the parent process until we try to
+ * debug a document living in the parent process.
+ */
 
 var { Ci, Cu, Cr, Cc } = require("chrome");
 var Services = require("Services");
 const ChromeUtils = require("ChromeUtils");
 var {
   ActorPool, createExtraActors, appendExtraActors
 } = require("devtools/server/actors/common");
 var { DebuggerServer } = require("devtools/server/main");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { assert } = DevToolsUtils;
-var { TabSources } = require("./utils/TabSources");
-var makeDebugger = require("./utils/make-debugger");
+var { TabSources } = require("devtools/server/actors/utils/TabSources");
+var makeDebugger = require("devtools/server/actors/utils/make-debugger");
 const InspectorUtils = require("InspectorUtils");
 
 const EXTENSION_CONTENT_JSM = "resource://gre/modules/ExtensionContent.jsm";
 
 const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol");
-const { tabSpec } = require("devtools/shared/specs/tab");
+const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
 
 loader.lazyRequireGetter(this, "ThreadActor", "devtools/server/actors/thread", true);
 loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/thread", true);
 loader.lazyRequireGetter(this, "WorkerActorList", "devtools/server/actors/worker-list", true);
 loader.lazyImporter(this, "ExtensionContent", EXTENSION_CONTENT_JSM);
 
 loader.lazyRequireGetter(this, "StyleSheetActor", "devtools/server/actors/stylesheets", true);
 loader.lazyRequireGetter(this, "getSheetText", "devtools/server/actors/stylesheets", true);
@@ -81,115 +88,122 @@ exports.getChildDocShells = getChildDocS
  * Browser-specific actors.
  */
 
 function getInnerId(window) {
   return window.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
 }
 
-const tabPrototype = {
+const browsingContextTargetPrototype = {
 
   /**
-   * Creates a TabActor whose main goal is to manage lifetime and
-   * expose the tab actors being registered via DebuggerServer.registerModule.
-   * But also track the lifetime of the document being tracked.
+   * BrowsingContextTargetActor is an abstract class used by target actors that
+   * hold documents, such as frames, chrome windows, etc.  The term "browsing
+   * context" is defined in the HTML spec as "an environment in which `Document`
+   * objects are presented to the user".  In Gecko, this means a browsing context
+   * is a `docShell`.
+   *
+   * TODO: Bug 1465637: Rename "tab" actors to something else.
+   * The main goal of this class is to expose the tab actors being registered via
+   * `DebuggerServer.registerModule` and manage their lifetimes.  In addition,
+   * this class also tracks the lifetime of the targeted browsing context.
    *
    * ### Main requests:
    *
    * `attach`/`detach` requests:
    *  - start/stop document watching:
    *    Starts watching for new documents and emits `tabNavigated` and
    *    `frameUpdate` over RDP.
    *  - retrieve the thread actor:
    *    Instantiates a ThreadActor that can be later attached to in order to
    *    debug JS sources in the document.
    * `switchToFrame`:
-   *  Change the targeted document of the whole TabActor, and its child tab actors
+   *  Change the targeted document of the whole actor, and its child tab actors
    *  to an iframe or back to its original document.
    *
-   * Most of the TabActor properties (like `chromeEventHandler` or `docShells`)
-   * are meant to be used by the various child tab actors.
+   * Most properties (like `chromeEventHandler` or `docShells`) are meant to be
+   * used by the various child target actors.
    *
    * ### RDP events:
    *
    *  - `tabNavigated`:
-   *    Sent when the tab is about to navigate or has just navigated to
-   *    a different document.
+   *    Sent when the browsing context is about to navigate or has just navigated
+   *    to a different document.
    *    This event contains the following attributes:
-   *     * url (string) The new URI being loaded.
-   *     * nativeConsoleAPI (boolean) `false` if the console API of the page has
-   *                                          been overridden (e.g. by Firebug),
-   *                                  `true`  if the Gecko implementation is used.
-   *     * state (string) `start` if we just start requesting the new URL,
-   *                      `stop`  if the new URL is done loading.
-   *     * isFrameSwitching (boolean) Indicates the event is dispatched when
-   *                                  switching the TabActor context to
-   *                                  a different frame. When we switch to
-   *                                  an iframe, there is no document load.
-   *                                  The targeted document is most likely
-   *                                  going to be already done loading.
-   *     * title (string) The document title being loaded.
-   *                      (sent only on state=stop)
+   *     * url (string)
+   *       The new URI being loaded.
+   *     * nativeConsoleAPI (boolean)
+   *       `false` if the console API of the page has been overridden (e.g. by Firebug)
+   *       `true`  if the Gecko implementation is used
+   *     * state (string)
+   *       `start` if we just start requesting the new URL
+   *       `stop`  if the new URL is done loading
+   *     * isFrameSwitching (boolean)
+   *       Indicates the event is dispatched when switching the actor context to a
+   *       different frame. When we switch to an iframe, there is no document
+   *       load. The targeted document is most likely going to be already done
+   *       loading.
+   *     * title (string)
+   *       The document title being loaded. (sent only on state=stop)
    *
    *  - `frameUpdate`:
    *    Sent when there was a change in the child frames contained in the document
-   *    or when the tab's context was switched to another frame.
+   *    or when the actor's context was switched to another frame.
    *    This event can have four different forms depending on the type of change:
    *    * One or many frames are updated:
    *      { frames: [{ id, url, title, parentID }, ...] }
    *    * One frame got destroyed:
    *      { frames: [{ id, destroy: true }]}
    *    * All frames got destroyed:
    *      { destroyAll: true }
-   *    * We switched the context of the TabActor to a specific frame:
+   *    * We switched the context of the actor to a specific frame:
    *      { selected: #id }
    *
    * ### Internal, non-rdp events:
-   * Various events are also dispatched on the TabActor itself that are not
-   * related to RDP, so, not sent to the client. They all relate to the documents
-   * tracked by the TabActor (its main targeted document, but also any of its
-   * iframes).
+   *
+   * Various events are also dispatched on the actor itself without being sent to
+   * the client. They all relate to the documents tracked by this target actor
+   * (its main targeted document, but also any of its iframes):
    *  - will-navigate
-   *    This event fires once navigation starts.
-   *    All pending user prompts are dealt with,
-   *    but it is fired before the first request starts.
+   *    This event fires once navigation starts. All pending user prompts are
+   *    dealt with, but it is fired before the first request starts.
    *  - navigate
    *    This event is fired once the document's readyState is "complete".
    *  - window-ready
    *    This event is fired in various distinct scenarios:
    *     * When a new Window object is crafted, equivalent of `DOMWindowCreated`.
    *       It is dispatched before any page script is executed.
    *     * We will have already received a window-ready event for this window
    *       when it was created, but we received a window-destroyed event when
    *       it was frozen into the bfcache, and now the user navigated back to
    *       this page, so it's now live again and we should resume handling it.
    *     * For each existing document, when an `attach` request is received.
    *       At this point scripts in the page will be already loaded.
-   *     * When `swapFrameLoaders` is used, such as with moving tabs between
-   *       windows or toggling Responsive Design Mode.
+   *     * When `swapFrameLoaders` is used, such as with moving browsing contexts
+   *       between windows or toggling Responsive Design Mode.
    *  - window-destroyed
    *    This event is fired in two cases:
    *     * When the window object is destroyed, i.e. when the related document
-   *       is garbage collected. This can happen when the tab is closed or the
-   *       iframe is removed from the DOM.
+   *       is garbage collected. This can happen when the browsing context is
+   *       closed or the iframe is removed from the DOM.
    *       It is equivalent of `inner-window-destroyed` event.
    *     * When the page goes into the bfcache and gets frozen.
    *       The equivalent of `pagehide`.
    *  - changed-toplevel-document
-   *    This event fires when we switch the TabActor targeted document
+   *    This event fires when we switch the actor's targeted document
    *    to one of its iframes, or back to its original top document.
    *    It is dispatched between window-destroyed and window-ready.
    *  - stylesheet-added
    *    This event is fired when a StyleSheetActor is created.
-   *    It contains the following attribute :
+   *    It contains the following attribute:
    *     * actor (StyleSheetActor) The created actor.
    *
    * Note that *all* these events are dispatched in the following order
-   * when we switch the context of the TabActor to a given iframe:
+   * when we switch the context of the actor to a given iframe:
    *  - will-navigate
    *  - window-destroyed
    *  - changed-toplevel-document
    *  - window-ready
    *  - navigate
    *
    * This class is subclassed by ContentActor and others.
    * Subclasses are expected to implement a getter for the docShell property.
@@ -224,17 +238,17 @@ const tabPrototype = {
     this.listenForNewDocShells = false;
 
     this.traits = {
       reconfigure: true,
       // Supports frame listing via `listFrames` request and `frameUpdate` events
       // as well as frame switching via `switchToFrame` request
       frames: true,
       // Do not require to send reconfigure request to reset the document state
-      // to what it was before using the TabActor
+      // to what it was before using the actor
       noTabReconfigureOnClose: true,
       // Supports the logInPage request.
       logInPage: true,
     };
 
     this._workerActorList = null;
     this._workerActorPool = null;
     this._onWorkerActorListChanged = this._onWorkerActorListChanged.bind(this);
@@ -276,57 +290,59 @@ const tabPrototype = {
     return this._tabPool;
   },
 
   _contextPool: null,
   get contextActorPool() {
     return this._contextPool;
   },
 
-  // A constant prefix that will be used to form the actor ID by the server.
-  actorPrefix: "tab",
+  /**
+   * A constant prefix that will be used to form the actor ID by the server.
+   */
+  typeName: "browsingContextTarget",
 
   /**
    * An object on which listen for DOMWindowCreated and pageshow events.
    */
   get chromeEventHandler() {
     return getDocShellChromeEventHandler(this.docShell);
   },
 
   /**
-   * Getter for the nsIMessageManager associated to the tab.
+   * Getter for the nsIMessageManager associated to the browsing context.
    */
   get messageManager() {
     try {
       return this.docShell
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIContentFrameMessageManager);
     } catch (e) {
       return null;
     }
   },
 
   /**
-   * Getter for the tab's doc shell.
+   * Getter for the browsing context's `docShell`.
    */
   get docShell() {
-    throw new Error(
-      "The docShell getter should be implemented by a subclass of TabActor");
+    throw new Error("`docShell` getter should be overridden by a subclass of " +
+                    "`BrowsingContextTargetActor`");
   },
 
   /**
-   * Getter for the list of all docshell in this tabActor
+   * Getter for the list of all `docShell`s in the browsing context.
    * @return {Array}
    */
   get docShells() {
     return getChildDocShells(this.docShell);
   },
 
   /**
-   * Getter for the tab content's DOM window.
+   * Getter for the browsing context's current DOM window.
    */
   get window() {
     // On xpcshell, there is no document
     if (this.docShell) {
       return this.docShell
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindow);
     }
@@ -339,60 +355,60 @@ const tabPrototype = {
                         .getInterface(Ci.nsIDOMWindowUtils)
                         .outerWindowID;
     }
     return null;
   },
 
   /**
    * Getter for the WebExtensions ContentScript globals related to the
-   * current tab content's DOM window.
+   * browsing context's current DOM window.
    */
   get webextensionsContentScriptGlobals() {
-    // Ignore xpcshell runtime which spawn TabActors without a window
+    // Ignore xpcshell runtime which spawns target actors without a window
     // and only retrieve the content scripts globals if the ExtensionContent JSM module
     // has been already loaded (which is true if the WebExtensions internals have already
     // been loaded in the same content process).
     if (this.window && Cu.isModuleLoaded(EXTENSION_CONTENT_JSM)) {
       return ExtensionContent.getContentScriptGlobals(this.window);
     }
 
     return [];
   },
 
   /**
-   * Getter for the list of all content DOM windows in this tabActor
+   * Getter for the list of all content DOM windows in the browsing context.
    * @return {Array}
    */
   get windows() {
     return this.docShells.map(docShell => {
       return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIDOMWindow);
     });
   },
 
   /**
-   * Getter for the original docShell the tabActor got attached to in the first
+   * Getter for the original docShell this actor got attached to in the first
    * place.
    * Note that your actor should normally *not* rely on this top level docShell
    * if you want it to show information relative to the iframe that's currently
    * being inspected in the toolbox.
    */
   get originalDocShell() {
     if (!this._originalWindow) {
       return this.docShell;
     }
 
     return this._originalWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation)
                                .QueryInterface(Ci.nsIDocShell);
   },
 
   /**
-   * Getter for the original window the tabActor got attached to in the first
+   * Getter for the original window this actor got attached to in the first
    * place.
    * Note that your actor should normally *not* rely on this top level window if
    * you want it to show information relative to the iframe that's currently
    * being inspected in the toolbox.
    */
   get originalWindow() {
     return this._originalWindow || this.window;
   },
@@ -402,44 +418,40 @@ const tabPrototype = {
    */
   get webProgress() {
     return this.docShell
       .QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebProgress);
   },
 
   /**
-   * Getter for the nsIWebNavigation for the tab.
+   * Getter for the nsIWebNavigation for the target.
    */
   get webNavigation() {
     return this.docShell
       .QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebNavigation);
   },
 
   /**
-   * Getter for the tab's document.
+   * Getter for the browsing context's document.
    */
   get contentDocument() {
     return this.webNavigation.document;
   },
 
   /**
-   * Getter for the tab title.
-   * @return string
-   *         Tab title.
+   * Getter for the browsing context's title.
    */
   get title() {
     return this.contentDocument.contentTitle;
   },
 
   /**
-   * Getter for the tab URL.
-   * @return string
-   *         Tab URL.
+   * Getter for the browsing context's URL.
    */
   get url() {
     if (this.webNavigation.currentURI) {
       return this.webNavigation.currentURI.spec;
     }
     // Abrupt closing of the browser window may leave callbacks without a
     // currentURI.
     return null;
@@ -451,24 +463,24 @@ const tabPrototype = {
     }
     return this._sources;
   },
 
   form() {
     assert(!this.exited,
                "form() shouldn't be called on exited browser actor.");
     assert(this.actorID,
-               "tab should have an actorID.");
+               "Actor should have an actorID.");
 
     const response = {
       actor: this.actorID
     };
 
     // We may try to access window while the document is closing, then
-    // accessing window throws. Also on xpcshell we are using tabactor even if
+    // accessing window throws. Also on xpcshell we are using this actor even if
     // there is no valid document.
     if (this.docShell && !this.docShell.isBeingDestroyed()) {
       response.title = this.title;
       response.url = this.url;
       response.outerWindowID = this.outerWindowID;
     }
 
     // Always use the same ActorPool, so existing actor instances
@@ -492,44 +504,45 @@ const tabPrototype = {
    * Called when the actor is removed from the connection.
    */
   destroy() {
     Actor.prototype.destroy.call(this);
     this.exit();
   },
 
   /**
-   * Called by the root actor when the underlying tab is closed.
+   * Called by the root actor when the underlying browsing context is closed.
    */
   exit() {
     if (this.exited) {
       return;
     }
 
-    // Tell the thread actor that the tab is closed, so that it may terminate
+    // Tell the thread actor that the browsing context is closed, so that it may terminate
     // instead of resuming the debuggee script.
     if (this._attached) {
-      this.threadActor._tabClosed = true;
+      // TODO: Bug 997119: Remove this coupling with thread actor
+      this.threadActor._parentClosed = true;
     }
 
     this._detach();
 
     Object.defineProperty(this, "docShell", {
       value: null,
       configurable: true
     });
 
     this._extraActors = null;
 
     this._exited = true;
   },
 
   /**
-   * Return true if the given global is associated with this tab and should be
-   * added as a debuggee, false otherwise.
+   * Return true if the given global is associated with this browsing context and should
+   * be added as a debuggee, false otherwise.
    */
   _shouldAddNewGlobalAsDebuggee(wrappedGlobal) {
     if (wrappedGlobal.hostAnnotations &&
         wrappedGlobal.hostAnnotations.type == "document" &&
         wrappedGlobal.hostAnnotations.element === this.window) {
       return true;
     }
 
@@ -557,17 +570,17 @@ const tabPrototype = {
     return false;
   },
 
   /* Support for DebuggerServer.addTabActor. */
   _createExtraActors: createExtraActors,
   _appendExtraActors: appendExtraActors,
 
   /**
-   * Does the actual work of attaching to a tab.
+   * Does the actual work of attaching to a browsing context.
    */
   _attach() {
     if (this._attached) {
       return;
     }
 
     // Create a pool for tab-lifetime actors.
     assert(!this._tabPool, "Shouldn't have a tab pool if we weren't attached.");
@@ -681,18 +694,18 @@ const tabPrototype = {
   },
 
   _onWorkerActorListChanged() {
     this._workerActorList.onListChanged = null;
     this.conn.sendActorEvent(this.actorID, "workerListChanged");
   },
 
   observe(subject, topic, data) {
-    // Ignore any event that comes before/after the tab actor is attached
-    // That typically happens during firefox shutdown.
+    // Ignore any event that comes before/after the actor is attached.
+    // That typically happens during Firefox shutdown.
     if (!this.attached) {
       return;
     }
 
     subject.QueryInterface(Ci.nsIDocShell);
 
     if (topic == "webnavigation-create") {
       this._onDocShellCreated(subject);
@@ -745,26 +758,25 @@ const tabPrototype = {
                               });
       if (rootDocShells.length > 0) {
         const newRoot = rootDocShells[0];
         this._originalWindow = newRoot.DOMWindow;
         this._changeTopLevelDocument(this._originalWindow);
       } else {
         // If for some reason (typically during Firefox shutdown), the original
         // document is destroyed, and there is no other top level docshell,
-        // we detach the tab actor to unregister all listeners and prevent any
-        // exception
+        // we detach the actor to unregister all listeners and prevent any
+        // exception.
         this.exit();
       }
       return;
     }
 
-    // If the currently targeted context is destroyed,
-    // and we aren't on the top-level document,
-    // we have to switch to the top-level one.
+    // If the currently targeted browsing context is destroyed, and we aren't on
+    // the top-level document, we have to switch to the top-level one.
     if (webProgress.DOMWindow == this.window &&
         this.window != this._originalWindow) {
       this._changeTopLevelDocument(this._originalWindow);
     }
   },
 
   _isRootDocShell(docShell) {
     // Should report as root docshell:
@@ -876,27 +888,27 @@ const tabPrototype = {
     this.conn.removeActorPool(this._contextPool);
     this._contextPool = null;
     this.threadActor.exit();
     this.threadActor = null;
     this._sources = null;
   },
 
   /**
-   * Does the actual work of detaching from a tab.
+   * Does the actual work of detaching from a browsing context.
    *
-   * @returns false if the tab wasn't attached or true of detaching succeeds.
+   * @returns false if the actor wasn't attached or true of detaching succeeds.
    */
   _detach() {
     if (!this.attached) {
       return false;
     }
 
-    // Check for docShell availability, as it can be already gone
-    // during Firefox shutdown.
+    // Check for `docShell` availability, as it can be already gone during
+    // Firefox shutdown.
     if (this.docShell) {
       this._unwatchDocShell(this.docShell);
       this._restoreDocumentSettings();
     }
     if (this._progressListener) {
       this._progressListener.destroy();
       this._progressListener = null;
       this._originalWindow = null;
@@ -963,65 +975,65 @@ const tabPrototype = {
     if (!this._detach()) {
       return { error: "wrongState" };
     }
 
     return { type: "detached" };
   },
 
   /**
-   * Bring the tab's window to front.
+   * Bring the browsing context's window to front.
    */
   focus() {
     if (this.window) {
       this.window.focus();
     }
     return {};
   },
 
   /**
-   * Reload the page in this tab.
+   * Reload the page in this browsing context.
    */
   reload(request) {
     const force = request && request.options && request.options.force;
     // Wait a tick so that the response packet can be dispatched before the
     // subsequent navigation event packet.
     Services.tm.dispatchToMainThread(DevToolsUtils.makeInfallible(() => {
       // This won't work while the browser is shutting down and we don't really
       // care.
       if (Services.startup.shuttingDown) {
         return;
       }
       this.webNavigation.reload(force ?
         Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE :
         Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
-    }, "TabActor.prototype.reload's delayed body"));
+    }, "BrowsingContextTargetActor.prototype.reload's delayed body"));
     return {};
   },
 
   /**
-   * Navigate this tab to a new location
+   * Navigate this browsing context to a new location
    */
   navigateTo(request) {
     // Wait a tick so that the response packet can be dispatched before the
     // subsequent navigation event packet.
     Services.tm.dispatchToMainThread(DevToolsUtils.makeInfallible(() => {
       this.window.location = request.url;
-    }, "TabActor.prototype.navigateTo's delayed body"));
+    }, "BrowsingContextTargetActor.prototype.navigateTo's delayed body"));
     return {};
   },
 
   /**
    * Reconfigure options.
    */
   reconfigure(request) {
     const options = request.options || {};
 
     if (!this.docShell) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return {};
     }
     this._toggleDevToolsSettings(options);
 
     return {};
   },
 
   /**
@@ -1128,17 +1140,17 @@ const tabPrototype = {
     }
   },
 
   /**
    * Return JS allowed status.
    */
   _getJavascriptEnabled() {
     if (!this.docShell) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return null;
     }
 
     return this.docShell.allowJavascript;
   },
 
   /**
    * Disable or enable the service workers testing features.
@@ -1149,60 +1161,60 @@ const tabPrototype = {
     windowUtils.serviceWorkersTestingEnabled = enabled;
   },
 
   /**
    * Return cache allowed status.
    */
   _getCacheDisabled() {
     if (!this.docShell) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return null;
     }
 
     const disable = Ci.nsIRequest.LOAD_BYPASS_CACHE |
                   Ci.nsIRequest.INHIBIT_CACHING;
     return this.docShell.defaultLoadFlags === disable;
   },
 
   /**
    * Return service workers testing allowed status.
    */
   _getServiceWorkersTestingEnabled() {
     if (!this.docShell) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return null;
     }
 
     const windowUtils = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIDOMWindowUtils);
     return windowUtils.serviceWorkersTestingEnabled;
   },
 
   /**
    * Prepare to enter a nested event loop by disabling debuggee events.
    */
   preNest() {
     if (!this.window) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return;
     }
     const windowUtils = this.window
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils);
     windowUtils.suppressEventHandling(true);
     windowUtils.suspendTimeouts();
   },
 
   /**
    * Prepare to exit a nested event loop by enabling debuggee events.
    */
   postNest(nestData) {
     if (!this.window) {
-      // The tab is already closed.
+      // The browsing context is already closed.
       return;
     }
     const windowUtils = this.window
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIDOMWindowUtils);
     windowUtils.resumeTimeouts();
     windowUtils.suppressEventHandling(false);
   },
@@ -1232,19 +1244,19 @@ const tabPrototype = {
       });
     });
   },
 
   _setWindow(window) {
     const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIWebNavigation)
                          .QueryInterface(Ci.nsIDocShell);
-    // Here is the very important call where we switch the currently
-    // targeted context (it will indirectly update this.window and
-    // many other attributes defined from docShell).
+    // Here is the very important call where we switch the currently targeted
+    // browsing context (it will indirectly update this.window and many other
+    // attributes defined from docShell).
     Object.defineProperty(this, "docShell", {
       value: docShell,
       enumerable: true,
       configurable: true
     });
     this.emit("changed-toplevel-document");
     this.conn.send({
       from: this.actorID,
@@ -1298,52 +1310,51 @@ const tabPrototype = {
       window: window,
       isTopLevel: window == this.window,
       id: id || getWindowID(window),
       isFrozen: isFrozen
     });
   },
 
   /**
-   * Start notifying server and client about a new document
-   * being loaded in the currently targeted context.
+   * Start notifying server and client about a new document being loaded in the
+   * currently targeted browsing context.
    */
   _willNavigate(window, newURI, request, isFrameSwitching = false) {
     let isTopLevel = window == this.window;
     let reset = false;
 
     if (window == this._originalWindow && !isFrameSwitching) {
       // Clear the iframe list if the original top-level document changes.
       this._notifyDocShellDestroyAll();
 
-      // If the top level document changes and we are targeting
-      // an iframe, we need to reset to the upcoming new top level document.
-      // But for this will-navigate event, we will dispatch on the old window.
-      // (The inspector codebase expect to receive will-navigate for the
-      // currently displayed document in order to cleanup the markup view)
+      // If the top level document changes and we are targeting an iframe, we
+      // need to reset to the upcoming new top level document. But for this
+      // will-navigate event, we will dispatch on the old window. (The inspector
+      // codebase expect to receive will-navigate for the currently displayed
+      // document in order to cleanup the markup view)
       if (this.window != this._originalWindow) {
         reset = true;
         window = this.window;
         isTopLevel = true;
       }
     }
 
-    // will-navigate event needs to be dispatched synchronously,
-    // by calling the listeners in the order or registration.
-    // This event fires once navigation starts,
-    // (all pending user prompts are dealt with),
-    // but before the first request starts.
+    // will-navigate event needs to be dispatched synchronously, by calling the
+    // listeners in the order or registration. This event fires once navigation
+    // starts, (all pending user prompts are dealt with), but before the first
+    // request starts.
     this.emit("will-navigate", {
       window: window,
       isTopLevel: isTopLevel,
       newURI: newURI,
       request: request
     });
 
-    // We don't do anything for inner frames in TabActor.
+    // We don't do anything for inner frames here.
     // (we will only update thread actor on window-ready)
     if (!isTopLevel) {
       return;
     }
 
     // Proceed normally only if the debuggee is not paused.
     // TODO bug 997119: move that code to ThreadActor by listening to
     // will-navigate
@@ -1366,31 +1377,31 @@ const tabPrototype = {
 
     if (reset) {
       this._setWindow(this._originalWindow);
     }
   },
 
   /**
    * Notify server and client about a new document done loading in the current
-   * targeted context.
+   * targeted browsing context.
    */
   _navigate(window, isFrameSwitching = false) {
     const isTopLevel = window == this.window;
 
     // navigate event needs to be dispatched synchronously,
     // by calling the listeners in the order or registration.
     // This event is fired once the document is loaded,
     // after the load event, it's document ready-state is 'complete'.
     this.emit("navigate", {
       window: window,
       isTopLevel: isTopLevel
     });
 
-    // We don't do anything for inner frames in TabActor.
+    // We don't do anything for inner frames here.
     // (we will only update thread actor on window-ready)
     if (!isTopLevel) {
       return;
     }
 
     // TODO bug 997119: move that code to ThreadActor by listening to navigate
     const threadActor = this.threadActor;
     if (threadActor.state == "running") {
@@ -1459,30 +1470,31 @@ const tabPrototype = {
       if (this._tabActorPool.has(actor)) {
         this._tabActorPool.removeActor(actor);
       }
       delete this._extraActors[name];
     }
   },
 };
 
-exports.tabPrototype = tabPrototype;
-exports.TabActor = ActorClassWithSpec(tabSpec, tabPrototype);
+exports.browsingContextTargetPrototype = browsingContextTargetPrototype;
+exports.BrowsingContextTargetActor =
+  ActorClassWithSpec(browsingContextTargetSpec, browsingContextTargetPrototype);
 
 /**
  * The DebuggerProgressListener object is an nsIWebProgressListener which
- * handles onStateChange events for the inspected browser. If the user tries to
- * navigate away from a paused page, the listener makes sure that the debuggee
- * is resumed before the navigation begins.
+ * handles onStateChange events for the targeted browsing context. If the user
+ * tries to navigate away from a paused page, the listener makes sure that the
+ * debuggee is resumed before the navigation begins.
  *
- * @param TabActor aTabActor
- *        The tab actor associated with this listener.
+ * @param BrowsingContextTargetActor targetActor
+ *        The browsing context target actor associated with this listener.
  */
-function DebuggerProgressListener(tabActor) {
-  this._tabActor = tabActor;
+function DebuggerProgressListener(targetActor) {
+  this._targetActor = targetActor;
   this._onWindowCreated = this.onWindowCreated.bind(this);
   this._onWindowHidden = this.onWindowHidden.bind(this);
 
   // Watch for windows destroyed (global observer that will need filtering)
   Services.obs.addObserver(this, "inner-window-destroyed");
 
   // XXX: for now we maintain the list of windows we know about in this instance
   // so that we can discriminate windows we care about when observing
@@ -1518,19 +1530,19 @@ DebuggerProgressListener.prototype = {
                                     Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
                                     Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
 
     const handler = getDocShellChromeEventHandler(docShell);
     handler.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
     handler.addEventListener("pageshow", this._onWindowCreated, true);
     handler.addEventListener("pagehide", this._onWindowHidden, true);
 
-    // Dispatch the _windowReady event on the tabActor for pre-existing windows
+    // Dispatch the _windowReady event on the targetActor for pre-existing windows
     for (const win of this._getWindowsInDocShell(docShell)) {
-      this._tabActor._windowReady(win);
+      this._targetActor._windowReady(win);
       this._knownWindowIDs.set(getWindowID(win), win);
     }
   },
 
   unwatch(docShell) {
     const docShellWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIDOMWindow);
     if (!this._watchedDocShells.has(docShellWindow)) {
@@ -1560,17 +1572,17 @@ DebuggerProgressListener.prototype = {
   _getWindowsInDocShell(docShell) {
     return getChildDocShells(docShell).map(d => {
       return d.QueryInterface(Ci.nsIInterfaceRequestor)
               .getInterface(Ci.nsIDOMWindow);
     });
   },
 
   onWindowCreated: DevToolsUtils.makeInfallible(function(evt) {
-    if (!this._tabActor.attached) {
+    if (!this._targetActor.attached) {
       return;
     }
 
     // If we're in a frame swap (which occurs when toggling RDM, for example), then we can
     // ignore this event, as the window never really went anywhere for our purposes.
     if (evt.inFrameSwap) {
       return;
     }
@@ -1584,23 +1596,23 @@ DebuggerProgressListener.prototype = {
     // When a page does into the BFCache, a pagehide event is fired with persisted=true
     // but it doesn't necessarely mean persisted will be true for the pageshow
     // event fired when the page is reloaded from the BFCache (see bug 1378133)
     // So just check if we already know this window and accept any that isn't known yet
     if (this._knownWindowIDs.has(innerID)) {
       return;
     }
 
-    this._tabActor._windowReady(window);
+    this._targetActor._windowReady(window);
 
     this._knownWindowIDs.set(innerID, window);
   }, "DebuggerProgressListener.prototype.onWindowCreated"),
 
   onWindowHidden: DevToolsUtils.makeInfallible(function(evt) {
-    if (!this._tabActor.attached) {
+    if (!this._targetActor.attached) {
       return;
     }
 
     // If we're in a frame swap (which occurs when toggling RDM, for example), then we can
     // ignore this event, as the window isn't really going anywhere for our purposes.
     if (evt.inFrameSwap) {
       return;
     }
@@ -1609,60 +1621,60 @@ DebuggerProgressListener.prototype = {
     // was sent for a persisted window (persisted is set when the page is put
     // and frozen in the bfcache). If the page isn't persisted, the observer's
     // inner-window-destroyed event will handle it.
     if (!evt.persisted) {
       return;
     }
 
     const window = evt.target.defaultView;
-    this._tabActor._windowDestroyed(window, null, true);
+    this._targetActor._windowDestroyed(window, null, true);
     this._knownWindowIDs.delete(getWindowID(window));
   }, "DebuggerProgressListener.prototype.onWindowHidden"),
 
   observe: DevToolsUtils.makeInfallible(function(subject, topic) {
-    if (!this._tabActor.attached) {
+    if (!this._targetActor.attached) {
       return;
     }
 
     // Because this observer will be called for all inner-window-destroyed in
     // the application, we need to filter out events for windows we are not
     // watching
     const innerID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
     const window = this._knownWindowIDs.get(innerID);
     if (window) {
       this._knownWindowIDs.delete(innerID);
-      this._tabActor._windowDestroyed(window, innerID);
+      this._targetActor._windowDestroyed(window, innerID);
     }
   }, "DebuggerProgressListener.prototype.observe"),
 
   onStateChange:
   DevToolsUtils.makeInfallible(function(progress, request, flag, status) {
-    if (!this._tabActor.attached) {
+    if (!this._targetActor.attached) {
       return;
     }
 
     const isStart = flag & Ci.nsIWebProgressListener.STATE_START;
     const isStop = flag & Ci.nsIWebProgressListener.STATE_STOP;
     const isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
     const isWindow = flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
 
     // Catch any iframe location change
     if (isDocument && isStop) {
       // Watch document stop to ensure having the new iframe url.
       progress.QueryInterface(Ci.nsIDocShell);
-      this._tabActor._notifyDocShellsUpdate([progress]);
+      this._targetActor._notifyDocShellsUpdate([progress]);
     }
 
     const window = progress.DOMWindow;
     if (isDocument && isStart) {
       // One of the earliest events that tells us a new URI
       // is being loaded in this window.
       const newURI = request instanceof Ci.nsIChannel ? request.URI.spec : null;
-      this._tabActor._willNavigate(window, newURI, request);
+      this._targetActor._willNavigate(window, newURI, request);
     }
     if (isWindow && isStop) {
       // Don't dispatch "navigate" event just yet when there is a redirect to
       // about:neterror page.
       // Navigating to about:neterror will make `status` be something else than NS_OK.
       // But for some error like NS_BINDING_ABORTED we don't want to emit any `navigate`
       // event as the page load has been cancelled and the related page document is going
       // to be a dead wrapper.
@@ -1671,20 +1683,20 @@ DebuggerProgressListener.prototype = {
         // with LOAD_BACKGROUND flags and never dispatches load event.
         // That may be the same reason why there is no onStateChange event
         // for about:neterror loads.
         const handler = getDocShellChromeEventHandler(progress);
         const onLoad = evt => {
           // Ignore events from iframes
           if (evt.target === window.document) {
             handler.removeEventListener("DOMContentLoaded", onLoad, true);
-            this._tabActor._navigate(window);
+            this._targetActor._navigate(window);
           }
         };
         handler.addEventListener("DOMContentLoaded", onLoad, true);
       } else {
         // Somewhat equivalent of load event.
         // (window.document.readyState == complete)
-        this._tabActor._navigate(window);
+        this._targetActor._navigate(window);
       }
     }
   }, "DebuggerProgressListener.prototype.onStateChange")
 };
new file mode 100644
--- /dev/null
+++ b/devtools/server/actors/targets/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+    'browsing-context.js',
+)
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -55,17 +55,17 @@ loader.lazyRequireGetter(this, "EventEmi
 const ThreadActor = ActorClassWithSpec(threadSpec, {
   initialize: function(parent, global) {
     this._state = "detached";
     this._frameActors = [];
     this._parent = parent;
     this._dbg = null;
     this._gripDepth = 0;
     this._threadLifetimePool = null;
-    this._tabClosed = false;
+    this._parentClosed = false;
     this._scripts = null;
     this._pauseOnDOMEvents = null;
 
     this._options = {
       useSourceMaps: false,
       autoBlackBox: false
     };
 
@@ -387,20 +387,20 @@ const ThreadActor = ActorClassWithSpec(t
         return undefined;
       });
 
       this._pushThreadPause();
     } catch (e) {
       reportError(e, "Got an exception during TA__pauseAndRespond: ");
     }
 
-    // If the browser tab has been closed, terminate the debuggee script
+    // If the parent actor has been closed, terminate the debuggee script
     // instead of continuing. Executing JS after the content window is gone is
     // a bad idea.
-    return this._tabClosed ? null : undefined;
+    return this._parentClosed ? null : undefined;
   },
 
   _makeOnEnterFrame: function({ pauseAndRespond }) {
     return frame => {
       const generatedLocation = this.sources.getFrameLocation(frame);
       const { originalSourceActor } = this.unsafeSynchronize(
         this.sources.getOriginalLocation(generatedLocation)
       );
@@ -1593,17 +1593,17 @@ const ThreadActor = ActorClassWithSpec(t
    *        A Debugger.Object instance whose referent is the global object.
    */
   onNewScript: function(script, global) {
     this._addSource(script.source);
   },
 
   /**
    * A function called when there's a new source from a thread actor's sources.
-   * Emits `newSource` on the tab actor.
+   * Emits `newSource` on the target actor.
    *
    * @param {SourceActor} source
    */
   onNewSourceEvent: function(source) {
     const type = "newSource";
     this.conn.send({
       from: this._parent.actorID,
       type,
@@ -1616,17 +1616,17 @@ const ThreadActor = ActorClassWithSpec(t
       from: this.actorID,
       type,
       source: source.form()
     });
   },
 
   /**
    * A function called when there's an updated source from a thread actor' sources.
-   * Emits `updatedSource` on the tab actor.
+   * Emits `updatedSource` on the target actor.
    *
    * @param {SourceActor} source
    */
   onUpdatedSourceEvent: function(source) {
     this.conn.send({
       from: this._parent.actorID,
       type: "updatedSource",
       source: source.form()
--- a/devtools/server/actors/timeline.js
+++ b/devtools/server/actors/timeline.js
@@ -22,22 +22,22 @@ const { actorBridgeWithSpec } = require(
 const { Timeline } = require("devtools/server/performance/timeline");
 const { timelineSpec } = require("devtools/shared/specs/timeline");
 
 /**
  * The timeline actor pops and forwards timeline markers registered in docshells.
  */
 exports.TimelineActor = protocol.ActorClassWithSpec(timelineSpec, {
   /**
-   * Initializes this actor with the provided connection and tab actor.
+   * Initializes this actor with the provided connection and target actor.
    */
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
-    this.bridge = new Timeline(tabActor);
+    this.targetActor = targetActor;
+    this.bridge = new Timeline(targetActor);
 
     this._onTimelineDocLoading = this._onTimelineDocLoading.bind(this);
     this._onTimelineMarkers = this._onTimelineMarkers.bind(this);
     this._onTimelineTicks = this._onTimelineTicks.bind(this);
     this._onTimelineMemory = this._onTimelineMemory.bind(this);
     this._onTimelineFrames = this._onTimelineFrames.bind(this);
 
     this.bridge.on("doc-loading", this._onTimelineDocLoading);
@@ -53,17 +53,17 @@ exports.TimelineActor = protocol.ActorCl
   destroy: function() {
     this.bridge.off("doc-loading", this._onTimelineDocLoading);
     this.bridge.off("markers", this._onTimelineMarkers);
     this.bridge.off("ticks", this._onTimelineTicks);
     this.bridge.off("memory", this._onTimelineMemory);
     this.bridge.off("frames", this._onTimelineFrames);
     this.bridge.destroy();
     this.bridge = null;
-    this.tabActor = null;
+    this.targetActor = null;
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
    * Propagate events from the Timeline module over RDP if the event is defined here.
    */
   _onTimelineDocLoading: function(...args) {
     this.emit("doc-loading", ...args);
--- a/devtools/server/actors/utils/walker-search.js
+++ b/devtools/server/actors/utils/walker-search.js
@@ -241,17 +241,17 @@ WalkerSearch.prototype = {
 
         // For now, just do one result per node since the frontend
         // doesn't have a way to highlight each result individually
         // yet.
         break;
       }
     }
 
-    const documents = this.walker.tabActor.windows.map(win=>win.document);
+    const documents = this.walker.targetActor.windows.map(win=>win.document);
 
     // Sort the resulting nodes by order of appearance in the DOM
     resultList.sort((a, b) => {
       // Disconnected nodes won't get good results from compareDocumentPosition
       // so check the order of their document instead.
       if (a.node.ownerDocument != b.node.ownerDocument) {
         const indA = documents.indexOf(a.node.ownerDocument);
         const indB = documents.indexOf(b.node.ownerDocument);
--- a/devtools/server/actors/webaudio.js
+++ b/devtools/server/actors/webaudio.js
@@ -397,19 +397,19 @@ var AudioNodeActor = exports.AudioNodeAc
 });
 
 /**
  * The Web Audio Actor handles simple interaction with an BaseAudioContext
  * high-level methods. After instantiating this actor, you'll need to set it
  * up by calling setup().
  */
 exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
 
     this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
 
     // Store ChromeOnly ID (`nativeID` property on AudioNodeActor) mapped
     // to the associated actorID, so we don't have to expose `nativeID`
     // to the client in any way.
     this._nativeToActorID = new Map();
 
@@ -426,55 +426,55 @@ exports.WebAudioActor = protocol.ActorCl
    * Returns definition of all AudioNodes, such as AudioParams, and
    * flags.
    */
   getDefinition: function() {
     return AUDIO_NODE_DEFINITION;
   },
 
   /**
-   * Starts waiting for the current tab actor's document global to be
+   * Starts waiting for the current target actor's document global to be
    * created, in order to instrument the Canvas context and become
    * aware of everything the content does with Web Audio.
    *
    * See ContentObserver and WebAudioInstrumenter for more details.
    */
   setup: function({ reload }) {
     // Used to track when something is happening with the web audio API
     // the first time, to ultimately fire `start-context` event
     this._firstNodeCreated = false;
 
     // Clear out stored nativeIDs on reload as we do not want to track
     // AudioNodes that are no longer on this document.
     this._nativeToActorID.clear();
 
     if (this._initialized) {
       if (reload) {
-        this.tabActor.window.location.reload();
+        this.targetActor.window.location.reload();
       }
       return;
     }
 
     this._initialized = true;
 
-    this._callWatcher = new CallWatcherActor(this.conn, this.tabActor);
+    this._callWatcher = new CallWatcherActor(this.conn, this.targetActor);
     this._callWatcher.onCall = this._onContentFunctionCall;
     this._callWatcher.setup({
       tracedGlobals: AUDIO_GLOBALS,
       startRecording: true,
       performReload: reload,
       holdWeak: true,
       storeCalls: false
     });
     // Bind to `window-ready` so we can reenable recording on the
     // call watcher
-    this.tabActor.on("window-ready", this._onGlobalCreated);
+    this.targetActor.on("window-ready", this._onGlobalCreated);
     // Bind to the `window-destroyed` event so we can unbind events between
     // the global destruction and the `finalize` cleanup method on the actor.
-    this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
   },
 
   /**
    * Invoked whenever an instrumented function is called, like an
    * BaseAudioContext method or an AudioNode method.
    */
   _onContentFunctionCall: function(functionCall) {
     const { name } = functionCall.details;
@@ -557,19 +557,19 @@ exports.WebAudioActor = protocol.ActorCl
 
     try {
       Services.obs.removeObserver(this, "webaudio-node-demise");
     } catch (e) {
       // Maybe we've shutdown already and it's too late to remove the observer. So avoid
       // NS_ERROR_FAILURE errors with this silent try/catch.
     }
 
-    this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
-    this.tabActor.off("window-ready", this._onGlobalCreated);
-    this.tabActor = null;
+    this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.off("window-ready", this._onGlobalCreated);
+    this.targetActor = null;
     this._nativeToActorID = null;
     this._callWatcher.eraseRecording();
     this._callWatcher.finalize();
     this._callWatcher = null;
   },
 
   /**
    * Helper for constructing an AudioNodeActor, assigning to
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -259,17 +259,17 @@ WebConsoleActor.prototype =
     if (!this._progressListenerActive) {
       EventEmitter.on(this.parentActor, "will-navigate", this._onWillNavigate);
       this._progressListenerActive = true;
     }
   },
 
   /**
    * Flag used to track if we are listening for events from the progress
-   * listener of the tab actor. We use the progress listener to clear
+   * listener of the target actor. We use the progress listener to clear
    * this.evalWindow on page navigation.
    *
    * @private
    * @type boolean
    */
   _progressListenerActive: false,
 
   /**
--- a/devtools/server/actors/webextension-inspected-window.js
+++ b/devtools/server/actors/webextension-inspected-window.js
@@ -88,17 +88,17 @@ function logAccessDeniedWarning(window, 
   }
 
   error.initWithWindowID(msg, url, lineNumber, 0, 0, errorFlag, "webExtensions",
                          innerWindowId);
   Services.console.logMessage(error);
 }
 
 function CustomizedReload(params) {
-  this.docShell = params.tabActor.window
+  this.docShell = params.targetActor.window
                         .QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIDocShell);
   this.docShell.QueryInterface(Ci.nsIWebProgress);
 
   this.inspectedWindowEval = params.inspectedWindowEval;
   this.callerInfo = params.callerInfo;
 
   this.ignoreCache = params.ignoreCache;
@@ -258,19 +258,19 @@ CustomizedReload.prototype = {
 };
 
 var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
   webExtensionInspectedWindowSpec,
   {
     /**
      * Created the WebExtension InspectedWindow actor
      */
-    initialize(conn, tabActor) {
+    initialize(conn, targetActor) {
       protocol.Actor.prototype.initialize.call(this, conn);
-      this.tabActor = tabActor;
+      this.targetActor = targetActor;
     },
 
     destroy(conn) {
       protocol.Actor.prototype.destroy.call(this, conn);
 
       if (this.customizedReload) {
         this.customizedReload.stop(
           new Error("WebExtensionInspectedWindowActor destroyed")
@@ -284,26 +284,26 @@ var WebExtensionInspectedWindowActor = p
       }
     },
 
     get dbg() {
       if (this._dbg) {
         return this._dbg;
       }
 
-      this._dbg = this.tabActor.makeDebugger();
+      this._dbg = this.targetActor.makeDebugger();
       return this._dbg;
     },
 
     get window() {
-      return this.tabActor.window;
+      return this.targetActor.window;
     },
 
     get webNavigation() {
-      return this.tabActor.webNavigation;
+      return this.targetActor.webNavigation;
     },
 
     createEvalBindings(dbgWindow, options) {
       const bindings = Object.create(null);
 
       let selectedDOMNode;
 
       if (options.toolboxSelectedNodeActorID) {
@@ -395,17 +395,17 @@ var WebExtensionInspectedWindowActor = p
               "Reload already in progress. Ignored inspectedWindow.reload for " +
               `${callerInfo.url}:${callerInfo.lineNumber}`
             );
             return;
           }
 
           try {
             this.customizedReload = new CustomizedReload({
-              tabActor: this.tabActor,
+              targetActor: this.targetActor,
               inspectedWindowEval: this.eval.bind(this),
               callerInfo, injectedScript, userAgent, ignoreCache,
             });
 
             this.customizedReload.start()
                 .then(() => {
                   delete this.customizedReload;
                 })
@@ -438,18 +438,18 @@ var WebExtensionInspectedWindowActor = p
       // started.
       Services.tm.dispatchToMainThread(delayedReload);
 
       return {};
     },
 
     /**
      * Evaluate the provided javascript code in a target window (that is always the
-     * tabActor window when called through RDP protocol, or the passed customTargetWindow
-     * when called directly from the CustomizedReload instances).
+     * targetActor window when called through RDP protocol, or the passed
+     * customTargetWindow when called directly from the CustomizedReload instances).
      *
      * @param {webExtensionCallerInfo} callerInfo
      *   the addonId and the url (the addon base url or the url of the actual caller
      *   filename and lineNumber) used to log useful debugging information in the
      *   produced error logs and eval stack trace.
      *
      * @param {string} expression
      *   the javascript code to be evaluated in the target window
@@ -463,17 +463,17 @@ var WebExtensionInspectedWindowActor = p
      *   the eval call result will contain detailed informations (in the format usually
      *   expected for errors not raised in the evaluated javascript code).
      *
      * @param {DOMWindow|undefined} customTargetWindow
      *   Used in the CustomizedReload instances to evaluate the `injectedScript`
      *   javascript code in every sub-frame of the target window during the tab reload.
      *   NOTE: this parameter is not part of the RDP protocol exposed by this actor, when
      *   it is called over the remote debugging protocol the target window is always
-     *   `tabActor.window`.
+     *   `targetActor.window`.
      */
     eval(callerInfo, expression, options, customTargetWindow) {
       const window = customTargetWindow || this.window;
       options = options || {};
 
       const extensionPolicy = WebExtensionPolicy.getByID(callerInfo.addonId);
 
       if (!extensionPolicy) {
--- a/devtools/server/actors/webextension.js
+++ b/devtools/server/actors/webextension.js
@@ -6,48 +6,50 @@
 
 const { extend } = require("devtools/shared/extend");
 const { Ci, Cu, Cc } = require("chrome");
 const Services = require("Services");
 
 const { ChromeActor, chromePrototype } = require("./chrome");
 const makeDebugger = require("./utils/make-debugger");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
-const { tabSpec } = require("devtools/shared/specs/tab");
+const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
 
 loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/thread", true);
 loader.lazyRequireGetter(this, "ChromeUtils");
 const FALLBACK_DOC_MESSAGE = "Your addon does not have any document opened yet.";
 
 /**
- * Creates a TabActor for debugging all the contexts associated to a target WebExtensions
- * add-on running in a child extension process.
- * Most of the implementation is inherited from ChromeActor (which inherits most of its
- * implementation from TabActor).
+ * Creates a target actor for debugging all the contexts associated to a target
+ * WebExtensions add-on running in a child extension process. Most of the implementation
+ * is inherited from ChromeActor (which inherits most of its implementation from
+ * BrowsingContextTargetActor).
+ *
  * WebExtensionChildActor is created by a WebExtensionParentActor counterpart, when its
  * parent actor's `connect` method has been called (on the listAddons RDP package),
  * it runs in the same process that the extension is running into (which can be the main
  * process if the extension is running in non-oop mode, or the child extension process
  * if the extension is running in oop-mode).
  *
  * A WebExtensionChildActor contains all tab actors, like a regular ChromeActor
- * or TabActor.
+ * or BrowsingContextTargetActor.
  *
  * History lecture:
- * - The add-on actors used to not inherit TabActor because of the different way the
- * add-on APIs where exposed to the add-on itself, and for this reason the Addon Debugger
- * has only a sub-set of the feature available in the Tab or in the Browser Toolbox.
+ * - The add-on actors used to not inherit BrowsingContextTargetActor because of the
+ *   different way the add-on APIs where exposed to the add-on itself, and for this reason
+ *   the Addon Debugger has only a sub-set of the feature available in the Tab or in the
+ *   Browser Toolbox.
  * - In a WebExtensions add-on all the provided contexts (background, popups etc.),
- * besides the Content Scripts which run in the content process, hooked to an existent
- * tab, by creating a new WebExtensionActor which inherits from ChromeActor, we can
- * provide a full features Addon Toolbox (which is basically like a BrowserToolbox which
- * filters the visible sources and frames to the one that are related to the target
- * add-on).
+ *   besides the Content Scripts which run in the content process, hooked to an existent
+ *   tab, by creating a new WebExtensionActor which inherits from ChromeActor, we can
+ *   provide a full features Addon Toolbox (which is basically like a BrowserToolbox which
+ *   filters the visible sources and frames to the one that are related to the target
+ *   add-on).
  * - When the WebExtensions OOP mode has been introduced, this actor has been refactored
- * and moved from the main process to the new child extension process.
+ *   and moved from the main process to the new child extension process.
  *
  * @param {DebuggerServerConnection} conn
  *        The connection to the client.
  * @param {nsIMessageSender} chromeGlobal.
  *        The chromeGlobal where this actor has been injected by the
  *        DebuggerServer.connectToFrame method.
  * @param {string} prefix
  *        the custom RDP prefix to use.
@@ -71,17 +73,17 @@ webExtensionChildPrototype.initialize = 
     enumerable: true,
     configurable: true,
     get: () => {
       return this._chromeGlobal;
     }
   });
 
   // Bind the _allowSource helper to this, it is used in the
-  // TabActor to lazily create the TabSources instance.
+  // BrowsingContextTargetActor to lazily create the TabSources instance.
   this._allowSource = this._allowSource.bind(this);
   this._onParentExit = this._onParentExit.bind(this);
 
   this._chromeGlobal.addMessageListener("debug:webext_parent_exit", this._onParentExit);
 
   // Set the consoleAPIListener filtering options
   // (retrieved and used in the related webconsole child actor).
   this.consoleAPIListenerOptions = {
@@ -181,17 +183,17 @@ webExtensionChildPrototype._searchForExt
     if (window.document.nodePrincipal.addonId == this.id) {
       return window;
     }
   }
 
   return undefined;
 };
 
-// Customized ChromeActor/TabActor hooks.
+// Customized ChromeActor/BrowsingContextTargetActor hooks.
 
 webExtensionChildPrototype._onDocShellDestroy = function(docShell) {
   // Stop watching this docshell (the unwatch() method will check if we
   // started watching it before).
   this._unwatchDocShell(docShell);
 
   // Let the _onDocShellDestroy notify that the docShell has been destroyed.
   const webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -210,17 +212,17 @@ webExtensionChildPrototype._onDocShellDe
 webExtensionChildPrototype._onNewExtensionWindow = function(window) {
   if (!this.window || this.window === this.fallbackWindow) {
     this._changeTopLevelDocument(window);
   }
 };
 
 webExtensionChildPrototype._attach = function() {
   // NOTE: we need to be sure that `this.window` can return a
-  // window before calling the ChromeActor.onAttach, or the TabActor
+  // window before calling the ChromeActor.onAttach, or the BrowsingContextTargetActor
   // will not be subscribed to the child doc shell updates.
 
   if (!this.window || this.window.document.nodePrincipal.addonId !== this.id) {
     // Discovery an existent extension page to attach.
     const extensionWindow = this._searchForExtensionWindow();
 
     if (!extensionWindow) {
       this._createFallbackWindow();
@@ -390,9 +392,10 @@ webExtensionChildPrototype._shouldAddNew
 webExtensionChildPrototype._onParentExit = function(msg) {
   if (msg.json.actor !== this.actorID) {
     return;
   }
 
   this.exit();
 };
 
-exports.WebExtensionChildActor = ActorClassWithSpec(tabSpec, webExtensionChildPrototype);
+exports.WebExtensionChildActor =
+  ActorClassWithSpec(browsingContextTargetSpec, webExtensionChildPrototype);
--- a/devtools/server/actors/webgl.js
+++ b/devtools/server/actors/webgl.js
@@ -181,89 +181,89 @@ var ProgramActor = protocol.ActorClassWi
 });
 
 /**
  * The WebGL Actor handles simple interaction with a WebGL context via a few
  * high-level methods. After instantiating this actor, you'll need to set it
  * up by calling setup().
  */
 exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
-  initialize: function(conn, tabActor) {
+  initialize: function(conn, targetActor) {
     protocol.Actor.prototype.initialize.call(this, conn);
-    this.tabActor = tabActor;
+    this.targetActor = targetActor;
     this._onGlobalCreated = this._onGlobalCreated.bind(this);
     this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
     this._onProgramLinked = this._onProgramLinked.bind(this);
   },
   destroy: function(conn) {
     protocol.Actor.prototype.destroy.call(this, conn);
     this.finalize();
   },
 
   /**
-   * Starts waiting for the current tab actor's document global to be
+   * Starts waiting for the current target actor's document global to be
    * created, in order to instrument the Canvas context and become
    * aware of everything the content does WebGL-wise.
    *
    * See ContentObserver and WebGLInstrumenter for more details.
    */
   setup: function({ reload }) {
     if (this._initialized) {
       return;
     }
     this._initialized = true;
 
     this._programActorsCache = [];
     this._webglObserver = new WebGLObserver();
 
-    this.tabActor.on("window-ready", this._onGlobalCreated);
-    this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.on("window-ready", this._onGlobalCreated);
+    this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
     EventEmitter.on(this._webglObserver, "program-linked", this._onProgramLinked);
 
     if (reload) {
-      this.tabActor.window.location.reload();
+      this.targetActor.window.location.reload();
     }
   },
 
   /**
    * Stops listening for document global changes and puts this actor
    * to hibernation. This method is called automatically just before the
    * actor is destroyed.
    */
   finalize: function() {
     if (!this._initialized) {
       return;
     }
     this._initialized = false;
 
-    this.tabActor.off("window-ready", this._onGlobalCreated);
-    this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
+    this.targetActor.off("window-ready", this._onGlobalCreated);
+    this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
     EventEmitter.off(this._webglObserver, "program-linked", this._onProgramLinked);
 
     this._programActorsCache = null;
     this._contentObserver = null;
     this._webglObserver = null;
   },
 
   /**
-   * Gets an array of cached program actors for the current tab actor's window.
+   * Gets an array of cached program actors for the current target actor's window.
    * This is useful for dealing with bfcache, when no new programs are linked.
    */
   getPrograms: function() {
-    const id = ContentObserver.GetInnerWindowID(this.tabActor.window);
+    const id = ContentObserver.GetInnerWindowID(this.targetActor.window);
     return this._programActorsCache.filter(e => e.ownerWindow == id);
   },
 
   /**
-   * Waits for one frame via `requestAnimationFrame` on the tab actor's window.
+   * Waits for one frame via `requestAnimationFrame` on the target actor's window.
    * Used in tests.
    */
   waitForFrame: function() {
     const deferred = defer();
-    this.tabActor.window.requestAnimationFrame(deferred.resolve);
+    this.targetActor.window.requestAnimationFrame(deferred.resolve);
     return deferred.promise;
   },
 
   /**
    * Gets a pixel's RGBA value from a context specified by selector
    * and the coordinates of the pixel in question.
    * Currently only used in tests.
    *
@@ -272,22 +272,22 @@ exports.WebGLActor = protocol.ActorClass
    * @param Object position
    *        An object with an `x` and `y` property indicating coordinates of
    *        the pixel being inspected.
    * @return Object
    *        An object containing `r`, `g`, `b`, and `a` properties of the pixel.
    */
   getPixel: function({ selector, position }) {
     const { x, y } = position;
-    const canvas = this.tabActor.window.document.querySelector(selector);
+    const canvas = this.targetActor.window.document.querySelector(selector);
     const context = XPCNativeWrapper.unwrap(canvas.getContext("webgl"));
     const { proxy } = this._webglObserver.for(context);
     const height = canvas.height;
 
-    let buffer = new this.tabActor.window.Uint8Array(4);
+    let buffer = new this.targetActor.window.Uint8Array(4);
     buffer = XPCNativeWrapper.unwrap(buffer);
 
     proxy.readPixels(
       x, height - y - 1, 1, 1, context.RGBA, context.UNSIGNED_BYTE, buffer
     );
 
     return { r: buffer[0], g: buffer[1], b: buffer[2], a: buffer[3] };
   },
@@ -296,27 +296,27 @@ exports.WebGLActor = protocol.ActorClass
    * Gets an array of all cached program actors belonging to all windows.
    * This should only be used for tests.
    */
   _getAllPrograms: function() {
     return this._programActorsCache;
   },
 
   /**
-   * Invoked whenever the current tab actor's document global is created.
+   * Invoked whenever the current target actor's document global is created.
    */
   _onGlobalCreated: function({id, window, isTopLevel}) {
     if (isTopLevel) {
       WebGLInstrumenter.handle(window, this._webglObserver);
       this.emit("global-created", id);
     }
   },
 
   /**
-   * Invoked whenever the current tab actor's inner window is destroyed.
+   * Invoked whenever the current target actor's inner window is destroyed.
    */
   _onGlobalDestroyed: function({id, isTopLevel, isFrozen}) {
     if (isTopLevel && !isFrozen) {
       removeFromArray(this._programActorsCache, e => e.ownerWindow == id);
       this._webglObserver.unregisterContextsForWindow(id);
       this.emit("global-destroyed", id);
     }
   },
--- a/devtools/server/actors/window.js
+++ b/devtools/server/actors/window.js
@@ -1,77 +1,79 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { Ci } = require("chrome");
 const Services = require("Services");
-const { TabActor, tabPrototype } = require("./tab");
+const {
+  BrowsingContextTargetActor,
+  browsingContextTargetPrototype
+} = require("devtools/server/actors/targets/browsing-context");
 
 const { extend } = require("devtools/shared/extend");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
-const { tabSpec } = require("devtools/shared/specs/tab");
+const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
 
 /**
  * Creates a WindowActor for debugging a single window, like a browser window in Firefox,
  * but it can be used to reach any window in the process.  (Currently this is parent
  * process only because the root actor's `onGetWindow` doesn't try to cross process
  * boundaries.)  Both chrome and content windows are supported.
  *
- * Most of the implementation is inherited from TabActor.  WindowActor exposes all tab
- * actors via its form() request, like TabActor.
+ * Most of the implementation is inherited from BrowsingContextTargetActor. WindowActor
+ * exposes all tab actors via its form() request, like BrowsingContextTargetActor.
  *
  * You can request a specific window's actor via RootActor.getWindow().
  *
- * Caveat: Protocol.js expects only the prototype object, and does
- * not maintain the prototype chain when it constructs the
- * ActorClass. For this reason we are using `extend` to
- * maintain the properties of TabActor.prototype
+ * Caveat: Protocol.js expects only the prototype object, and does not maintain the
+ * prototype chain when it constructs the ActorClass. For this reason we are using
+ * `extend` to maintain the properties of BrowsingContextTargetActor.prototype
  *
  * @param connection DebuggerServerConnection
  *        The connection to the client.
  * @param window DOMWindow
  *        The window.
  */
 
-const windowPrototype = extend({}, tabPrototype);
+const windowPrototype = extend({}, browsingContextTargetPrototype);
 
 windowPrototype.initialize = function(connection, window) {
-  TabActor.prototype.initialize.call(this, connection);
+  BrowsingContextTargetActor.prototype.initialize.call(this, connection);
 
   const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell);
   Object.defineProperty(this, "docShell", {
     value: docShell,
     configurable: true
   });
 };
 
 // Bug 1266561: This setting is mysteriously named, we should split up the
 // functionality that is triggered by it.
 windowPrototype.isRootActor = true;
 
 windowPrototype.observe = function(subject, topic, data) {
-  TabActor.prototype.observe.call(this, subject, topic, data);
+  BrowsingContextTargetActor.prototype.observe.call(this, subject, topic, data);
   if (!this.attached) {
     return;
   }
   if (topic == "chrome-webnavigation-destroy") {
     this._onDocShellDestroy(subject);
   }
 };
 
 windowPrototype._attach = function() {
   if (this.attached) {
     return false;
   }
 
-  TabActor.prototype._attach.call(this);
+  BrowsingContextTargetActor.prototype._attach.call(this);
 
   // Listen for chrome docshells in addition to content docshells
   if (this.docShell.itemType == Ci.nsIDocShellTreeItem.typeChrome) {
     Services.obs.addObserver(this, "chrome-webnavigation-destroy");
   }
 
   return true;
 };
@@ -80,14 +82,14 @@ windowPrototype._detach = function() {
   if (!this.attached) {
     return false;
   }
 
   if (this.docShell.itemType == Ci.nsIDocShellTreeItem.typeChrome) {
     Services.obs.removeObserver(this, "chrome-webnavigation-destroy");
   }
 
-  TabActor.prototype._detach.call(this);
+  BrowsingContextTargetActor.prototype._detach.call(this);
 
   return true;
 };
 
-exports.WindowActor = ActorClassWithSpec(tabSpec, windowPrototype);
+exports.WindowActor = ActorClassWithSpec(browsingContextTargetSpec, windowPrototype);
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -969,22 +969,20 @@ var DebuggerServer = {
    * Start a DevTools server in a remote frame's process and add it as a child server for
    * an active connection.
    *
    * @param object connection
    *        The debugger server connection to use.
    * @param Element frame
    *        The frame element with remote content to connect to.
    * @param function [onDestroy]
-   *        Optional function to invoke when the child process closes
-   *        or the connection shuts down. (Need to forget about the
-   *        related TabActor)
+   *        Optional function to invoke when the child process closes or the connection
+   *        shuts down. (Need to forget about the related target actor.)
    * @return object
-   *         A promise object that is resolved once the connection is
-   *         established.
+   *         A promise object that is resolved once the connection is established.
    */
   connectToFrame(connection, frame, onDestroy, {addonId} = {}) {
     return new Promise(resolve => {
       // Get messageManager from XUL browser (which might be a specialized tunnel for RDM)
       // or else fallback to asking the frameLoader itself.
       let mm = frame.messageManager || frame.frameLoader.messageManager;
       mm.loadFrameScript("resource://devtools/server/startup/frame.js", false);
 
--- a/devtools/server/performance/framerate.js
+++ b/devtools/server/performance/framerate.js
@@ -1,42 +1,42 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 /**
- * A very simple utility for monitoring framerate. Takes a `tabActor`
+ * A very simple utility for monitoring framerate. Takes a `targetActor`
  * and monitors framerate over time. The actor wrapper around this
  * can be found at devtools/server/actors/framerate.js
  */
 class Framerate {
-  constructor(tabActor) {
-    this.tabActor = tabActor;
-    this._contentWin = tabActor.window;
+  constructor(targetActor) {
+    this.targetActor = targetActor;
+    this._contentWin = targetActor.window;
     this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
     this._onGlobalCreated = this._onGlobalCreated.bind(this);
-    this.tabActor.on("window-ready", this._onGlobalCreated);
+    this.targetActor.on("window-ready", this._onGlobalCreated);
   }
 
   destroy(conn) {
-    this.tabActor.off("window-ready", this._onGlobalCreated);
+    this.targetActor.off("window-ready", this._onGlobalCreated);
     this.stopRecording();
   }
 
   /**
    * Starts monitoring framerate, storing the frames per second.
    */
   startRecording() {
     if (this._recording) {
       return;
     }
     this._recording = true;
     this._ticks = [];
-    this._startTime = this.tabActor.docShell.now();
+    this._startTime = this.targetActor.docShell.now();
     this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
   }
 
   /**
    * Stops monitoring framerate, returning the recorded values.
    */
   stopRecording(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
     if (!this._recording) {
@@ -77,21 +77,21 @@ class Framerate {
   /**
    * Function invoked along with the refresh driver.
    */
   _onRefreshDriverTick() {
     if (!this._recording) {
       return;
     }
     this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
-    this._ticks.push(this.tabActor.docShell.now() - this._startTime);
+    this._ticks.push(this.targetActor.docShell.now() - this._startTime);
   }
 
   /**
-   * When the content window for the tab actor is created.
+   * When the content window for the target actor is created.
    */
   _onGlobalCreated(win) {
     if (this._recording) {
       this._contentWin.cancelAnimationFrame(this._rafID);
       this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
     }
   }
 }
--- a/devtools/server/performance/recorder.js
+++ b/devtools/server/performance/recorder.js
@@ -34,21 +34,21 @@ const DRAIN_ALLOCATIONS_TIMEOUT = 2000;
 
 /**
  * A connection to underlying actors (profiler, memory, framerate, etc.)
  * shared by all tools in a target.
  *
  * @param Target target
  *        The target owning this connection.
  */
-function PerformanceRecorder(conn, tabActor) {
+function PerformanceRecorder(conn, targetActor) {
   EventEmitter.decorate(this);
 
   this.conn = conn;
-  this.tabActor = tabActor;
+  this.targetActor = targetActor;
 
   this._pendingConsoleRecordings = [];
   this._recordings = [];
 
   this._onTimelineData = this._onTimelineData.bind(this);
   this._onProfilerEvent = this._onProfilerEvent.bind(this);
 }
 
@@ -95,19 +95,19 @@ PerformanceRecorder.prototype = {
     this._client = null;
   },
 
   /**
    * Initializes fronts and connects to the underlying actors using the facades
    * found in ./actors.js.
    */
   _connectComponents: function() {
-    this._profiler = new Profiler(this.tabActor);
-    this._memory = new Memory(this.tabActor);
-    this._timeline = new Timeline(this.tabActor);
+    this._profiler = new Profiler(this.targetActor);
+    this._memory = new Memory(this.targetActor);
+    this._timeline = new Timeline(this.targetActor);
     this._profiler.registerEventNotifications({ events: PROFILER_EVENTS });
   },
 
   /**
    * Registers listeners on events from the underlying
    * actors, so the connection can handle them.
    */
   _registerListeners: function() {
--- a/devtools/server/performance/timeline.js
+++ b/devtools/server/performance/timeline.js
@@ -32,60 +32,60 @@ loader.lazyRequireGetter(this, "EventEmi
 // How often do we pull markers from the docShells, and therefore, how often do
 // we send events to the front (knowing that when there are no markers in the
 // docShell, no event is sent). In milliseconds.
 const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200;
 
 /**
  * The timeline actor pops and forwards timeline markers registered in docshells.
  */
-function Timeline(tabActor) {
+function Timeline(targetActor) {
   EventEmitter.decorate(this);
 
-  this.tabActor = tabActor;
+  this.targetActor = targetActor;
 
   this._isRecording = false;
   this._stackFrames = null;
   this._memory = null;
   this._framerate = null;
 
   // Make sure to get markers from new windows as they become available
   this._onWindowReady = this._onWindowReady.bind(this);
   this._onGarbageCollection = this._onGarbageCollection.bind(this);
-  this.tabActor.on("window-ready", this._onWindowReady);
+  this.targetActor.on("window-ready", this._onWindowReady);
 }
 
 Timeline.prototype = {
   /**
    * Destroys this actor, stopping recording first.
    */
   destroy: function() {
     this.stop();
 
-    this.tabActor.off("window-ready", this._onWindowReady);
-    this.tabActor = null;
+    this.targetActor.off("window-ready", this._onWindowReady);
+    this.targetActor = null;
   },
 
   /**
-   * Get the list of docShells in the currently attached tabActor. Note that we
-   * always list the docShells included in the real root docShell, even if the
-   * tabActor was switched to a child frame. This is because for now, paint
-   * markers are only recorded at parent frame level so switching the timeline
-   * to a child frame would hide all paint markers.
+   * Get the list of docShells in the currently attached targetActor. Note that
+   * we always list the docShells included in the real root docShell, even if
+   * the targetActor was switched to a child frame. This is because for now,
+   * paint markers are only recorded at parent frame level so switching the
+   * timeline to a child frame would hide all paint markers.
    * See https://bugzilla.mozilla.org/show_bug.cgi?id=1050773#c14
    * @return {Array}
    */
   get docShells() {
     let originalDocShell;
     const docShells = [];
 
-    if (this.tabActor.isRootActor) {
-      originalDocShell = this.tabActor.docShell;
+    if (this.targetActor.isRootActor) {
+      originalDocShell = this.targetActor.docShell;
     } else {
-      originalDocShell = this.tabActor.originalDocShell;
+      originalDocShell = this.targetActor.originalDocShell;
     }
 
     if (!originalDocShell) {
       return docShells;
     }
 
     const docShellsEnum = originalDocShell.getDocShellEnumerator(
       Ci.nsIDocShellTreeItem.typeAll,
@@ -231,22 +231,22 @@ Timeline.prototype = {
 
     if (this._withMarkers || this._withDocLoadingEvents) {
       for (const docShell of docShells) {
         docShell.recordProfileTimelineMarkers = true;
       }
     }
 
     if (this._withTicks) {
-      this._framerate = new Framerate(this.tabActor);
+      this._framerate = new Framerate(this.targetActor);
       this._framerate.startRecording();
     }
 
     if (this._withMemory || this._withGCEvents) {
-      this._memory = new Memory(this.tabActor, this._stackFrames);
+      this._memory = new Memory(this.targetActor, this._stackFrames);
       this._memory.attach();
     }
 
     if (this._withGCEvents) {
       this._memory.on("garbage-collection", this._onGarbageCollection);
     }
 
     if (this._withFrames && this._withMarkers) {
@@ -305,17 +305,17 @@ Timeline.prototype = {
     this._withGCEvents = false;
 
     clearTimeout(this._dataPullTimeout);
 
     return endTime;
   },
 
   /**
-   * When a new window becomes available in the tabActor, start recording its
+   * When a new window becomes available in the targetActor, start recording its
    * markers if we were recording.
    */
   _onWindowReady: function({ window }) {
     if (this._isRecording) {
       const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIWebNavigation)
                            .QueryInterface(Ci.nsIDocShell);
       docShell.recordProfileTimelineMarkers = true;
--- a/devtools/server/tests/browser/browser_navigateEvents.js
+++ b/devtools/server/tests/browser/browser_navigateEvents.js
@@ -127,25 +127,25 @@ add_task(async function() {
 
   const { client, actorID } = await connectAndAttachTab();
   await ContentTask.spawn(browser, [actorID], async function(actorId) {
     const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
     const { DebuggerServer } = require("devtools/server/main");
     const EventEmitter = require("devtools/shared/event-emitter");
 
     // !Hack! Retrieve a server side object, the BrowserTabActor instance
-    const tabActor = DebuggerServer.searchAllConnectionsForActor(actorId);
+    const targetActor = DebuggerServer.searchAllConnectionsForActor(actorId);
     // In order to listen to internal will-navigate/navigate events
-    EventEmitter.on(tabActor, "will-navigate", function(data) {
+    EventEmitter.on(targetActor, "will-navigate", function(data) {
       sendSyncMessage("devtools-test:event", {
         event: "will-navigate",
         data: { newURI: data.newURI }
       });
     });
-    EventEmitter.on(tabActor, "navigate", function(data) {
+    EventEmitter.on(targetActor, "navigate", function(data) {
       sendSyncMessage("devtools-test:event", {
         event: "navigate",
         data: { readyState: content.document.readyState }
       });
     });
     // Forward DOMContentLoaded and load events
     addEventListener("DOMContentLoaded", function() {
       sendSyncMessage("devtools-test:event", {
--- a/devtools/server/tests/browser/head.js
+++ b/devtools/server/tests/browser/head.js
@@ -134,19 +134,20 @@ function getRootForm(client) {
 function waitUntilClientConnected(client) {
   return new Promise(resolve => {
     client.addOneTimeListener("connected", resolve);
   });
 }
 
 /**
  * Connect a debugger client.
+ *
  * @param {DebuggerClient}
- * @return {Promise} Resolves to the selected tabActor form when the client is
- * connected.
+ * @return {Promise} Resolves to the targetActor form for the selected tab when the client
+ *         is connected.
  */
 function connectDebuggerClient(client) {
   return client.connect()
     .then(() => client.listTabs())
     .then(tabs => {
       return tabs.tabs[tabs.selected];
     });
 }
@@ -185,30 +186,16 @@ function once(target, eventName, useCapt
  * windows.
  */
 function forceCollections() {
   Cu.forceGC();
   Cu.forceCC();
   Cu.forceShrinkingGC();
 }
 
-/**
- * Get a mock tabActor from a given window.
- * This is sometimes useful to test actors or classes that use the tabActor in
- * isolation.
- * @param {DOMWindow} win
- * @return {Object}
- */
-function getMockTabActor(win) {
-  return {
-    window: win,
-    isRootActor: true
-  };
-}
-
 registerCleanupFunction(function tearDown() {
   Services.cookies.removeAll();
 
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
--- a/devtools/server/tests/mochitest/chrome.ini
+++ b/devtools/server/tests/mochitest/chrome.ini
@@ -101,11 +101,11 @@ support-files =
 [test_styles-computed.html]
 [test_styles-layout.html]
 [test_styles-matched.html]
 [test_styles-modify.html]
 [test_styles-svg.html]
 [test_unsafeDereference.html]
 [test_webconsole-node-grip.html]
 [test_webextension-addon-debugging-connect.html]
-skip-if = !e10s # test is designed to work on e10s only
+disabled = true # Bug 1467313: broken, needs repair or removal
 [test_webextension-addon-debugging-reload.html]
-skip-if = !e10s # test is designed to work on e10s only
+disabled = true # Bug 1467313: broken, needs repair or removal
--- a/devtools/server/tests/mochitest/test_connectToFrame.html
+++ b/devtools/server/tests/mochitest/test_connectToFrame.html
@@ -77,17 +77,17 @@ function runTests() {
     // Fake a first connection to an iframe
     const transport = DebuggerServer.connectPipe();
     const conn = transport._serverConnection;
     const client = new DebuggerClient(transport);
     DebuggerServer.connectToFrame(conn, iframe).then(actor => {
       ok(actor.testActor, "Got the test actor");
 
       // Ensure sending at least one request to our actor,
-      // otherwise it won't be instanciated, nor be destroyed...
+      // otherwise it won't be instantiated, nor be destroyed...
       client.request({
         to: actor.testActor,
         type: "hello",
       }, function(response) {
         // Then close the client. That should end up cleaning our test actor
         client.close();
 
         // Ensure that our test actor got cleaned up;
--- a/devtools/server/tests/mochitest/test_inspector_getNodeFromActor.html
+++ b/devtools/server/tests/mochitest/test_inspector_getNodeFromActor.html
@@ -55,17 +55,17 @@ addTest(function() {
     is(rootDocNode, gWalker.rootNode, "The right node was returned");
     runNextTest();
   });
 });
 
 addTest(function() {
   info("Try to get a NodeFront from a valid actorID and valid complex path");
   gWalker.getNodeFromActor(gWalker.actorID,
-    ["tabActor", "window", "document", "body"]).then(bodyNode => {
+    ["targetActor", "window", "document", "body"]).then(bodyNode => {
       ok(bodyNode, "A node was returned");
       gWalker.querySelector(gWalker.rootNode, "body").then(node => {
         is(bodyNode, node, "The body node was returned");
         runNextTest();
       });
     });
 });
 
--- a/devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
+++ b/devtools/server/tests/mochitest/test_webextension-addon-debugging-connect.html
@@ -40,17 +40,17 @@ async function test_connect_addon(oopMod
   ok(addonActor, "The expected webextension addon actor has been found");
 
   // Connect to the target addon actor and wait for the updated list of frames.
   const waitFramesUpdated = waitForFramesUpdated({client});
   const addonTarget = await TargetFactory.forRemoteTab({
     form: addonActor,
     client,
     chrome: true,
-    isTabActor: true,
+    isBrowsingContext: true,
   });
   is(addonTarget.form.isOOP, oopMode,
      "Got the expected oop mode in the webextension actor form");
   const frames = await waitFramesUpdated;
   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");
--- a/devtools/server/tests/mochitest/webextension-helpers.js
+++ b/devtools/server/tests/mochitest/webextension-helpers.js
@@ -105,17 +105,17 @@ async function attachAddon(addonId) {
     client.close();
     throw new Error(`No WebExtension Actor found for ${addonId}`);
   }
 
   const addonTarget = await TargetFactory.forRemoteTab({
     form: addonActor,
     client,
     chrome: true,
-    isTabActor: true,
+    isBrowsingContext: true,
   });
 
   return addonTarget;
 }
 
 async function reloadAddon({client}, addonId) {
   const {addons} = await client.mainRoot.listAddons();
   const addonActor = addons.filter(actor => actor.id === addonId).pop();
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -419,18 +419,18 @@ function startTestDebuggerServer(title, 
 
 function finishClient(client) {
   client.close(function() {
     DebuggerServer.destroy();
     do_test_finished();
   });
 }
 
-// Create a server, connect to it and fetch tab actors for the parent process;
-// pass |callback| the debugger client and tab actor form with all actor IDs.
+// Create a server, connect to it and fetch target actors for the parent process;
+// pass |callback| the debugger client and target actor form with all actor IDs.
 function get_chrome_actors(callback) {
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
   DebuggerServer.allowChromeProcess = true;
 
   const client = new DebuggerClient(DebuggerServer.connectPipe());
   client.connect()
     .then(() => client.getProcess())
--- a/devtools/server/tests/unit/test_dbgactor.js
+++ b/devtools/server/tests/unit/test_dbgactor.js
@@ -30,21 +30,21 @@ function run_test() {
     });
   });
 
   gClient.connect();
 
   do_test_pending();
 }
 
-// Attach to |tabActor|, and check the response.
-function test_attach_tab(tabActor) {
-  gClient.request({ to: tabActor, type: "attach" }, function(response) {
+// Attach to |targetActor|, and check the response.
+function test_attach_tab(targetActor) {
+  gClient.request({ to: targetActor, type: "attach" }, function(response) {
     Assert.equal(false, "error" in response);
-    Assert.equal(response.from, tabActor);
+    Assert.equal(response.from, targetActor);
     Assert.equal(response.type, "tabAttached");
     Assert.ok(typeof response.threadActor === "string");
 
     test_attach_thread(response.threadActor);
   });
 }
 
 // Attach to |threadActor|, check the response, and resume it.
--- a/devtools/server/tests/unit/test_layout-reflows-observer.js
+++ b/devtools/server/tests/unit/test_layout-reflows-observer.js
@@ -16,38 +16,42 @@ const EventEmitter = require("devtools/s
 
 // Override set/clearTimeout on LayoutChangesObserver to avoid depending on
 // time in this unit test. This means that LayoutChangesObserver.eventLoopTimer
 // will be the timeout callback instead of the timeout itself, so test cases
 // will need to execute it to fake a timeout
 LayoutChangesObserver.prototype._setTimeout = cb => cb;
 LayoutChangesObserver.prototype._clearTimeout = function() {};
 
-// Mock the tabActor since we only really want to test the LayoutChangesObserver
+// Mock the targetActor since we only really want to test the LayoutChangesObserver
 // and don't want to depend on a window object, nor want to test protocol.js
-class MockTabActor extends EventEmitter {
+class MockTargetActor extends EventEmitter {
   constructor() {
     super();
-    this.window = new MockWindow();
+    this.docShell = new MockDocShell();
+    this.window = new MockWindow(this.docShell);
     this.windows = [this.window];
     this.attached = true;
   }
+
+  get chromeEventHandler() {
+    return this.docShell.chromeEventHandler;
+  }
 }
 
-function MockWindow() {}
+function MockWindow(docShell) {
+  this.docShell = docShell;
+}
 MockWindow.prototype = {
   QueryInterface: function() {
     const self = this;
     return {
       getInterface: function() {
         return {
           QueryInterface: function() {
-            if (!self.docShell) {
-              self.docShell = new MockDocShell();
-            }
             return self.docShell;
           }
         };
       }
     };
   },
   setTimeout: function(cb) {
     // Simply return the cb itself so that we can execute it in the test instead
@@ -94,201 +98,200 @@ function run_test() {
   destroyStopsObserving();
   stoppingAndStartingSeveralTimesWorksCorrectly();
   reflowsArentStackedWhenStopped();
   stackedReflowsAreResetOnStop();
 }
 
 function instancesOfObserversAreSharedBetweenWindows() {
   info("Checking that when requesting twice an instances of the observer " +
-    "for the same TabActor, the instance is shared");
+    "for the same BrowsingContextTargetActor, the instance is shared");
 
-  info("Checking 2 instances of the observer for the tabActor 1");
-  const tabActor1 = new MockTabActor();
-  const obs11 = getLayoutChangesObserver(tabActor1);
-  const obs12 = getLayoutChangesObserver(tabActor1);
+  info("Checking 2 instances of the observer for the targetActor 1");
+  const targetActor1 = new MockTargetActor();
+  const obs11 = getLayoutChangesObserver(targetActor1);
+  const obs12 = getLayoutChangesObserver(targetActor1);
   Assert.equal(obs11, obs12);
 
-  info("Checking 2 instances of the observer for the tabActor 2");
-  const tabActor2 = new MockTabActor();
-  const obs21 = getLayoutChangesObserver(tabActor2);
-  const obs22 = getLayoutChangesObserver(tabActor2);
+  info("Checking 2 instances of the observer for the targetActor 2");
+  const targetActor2 = new MockTargetActor();
+  const obs21 = getLayoutChangesObserver(targetActor2);
+  const obs22 = getLayoutChangesObserver(targetActor2);
   Assert.equal(obs21, obs22);
 
-  info("Checking that observers instances for 2 different tabActors are " +
+  info("Checking that observers instances for 2 different targetActors are " +
     "different");
   Assert.notEqual(obs11, obs21);
 
-  releaseLayoutChangesObserver(tabActor1);
-  releaseLayoutChangesObserver(tabActor1);
-  releaseLayoutChangesObserver(tabActor2);
-  releaseLayoutChangesObserver(tabActor2);
+  releaseLayoutChangesObserver(targetActor1);
+  releaseLayoutChangesObserver(targetActor1);
+  releaseLayoutChangesObserver(targetActor2);
+  releaseLayoutChangesObserver(targetActor2);
 }
 
 function eventsAreBatched() {
   info("Checking that reflow events are batched and only sent when the " +
     "timeout expires");
 
-  // Note that in this test, we mock the TabActor and its window property, so we
-  // also mock the setTimeout/clearTimeout mechanism and just call the callback
-  // manually
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  // Note that in this test, we mock the target actor and its window property, so we also
+  // mock the setTimeout/clearTimeout mechanism and just call the callback manually
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
 
   const reflowsEvents = [];
   const onReflows = reflows => reflowsEvents.push(reflows);
   observer.on("reflows", onReflows);
 
   const resizeEvents = [];
   const onResize = () => resizeEvents.push("resize");
   observer.on("resize", onResize);
 
   info("Fake one reflow event");
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
   info("Checking that no batched reflow event has been emitted");
   Assert.equal(reflowsEvents.length, 0);
 
   info("Fake another reflow event");
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
   info("Checking that still no batched reflow event has been emitted");
   Assert.equal(reflowsEvents.length, 0);
 
   info("Fake a few of resize events too");
-  tabActor.window.docShell.mockResize();
-  tabActor.window.docShell.mockResize();
-  tabActor.window.docShell.mockResize();
+  targetActor.window.docShell.mockResize();
+  targetActor.window.docShell.mockResize();
+  targetActor.window.docShell.mockResize();
   info("Checking that still no batched resize event has been emitted");
   Assert.equal(resizeEvents.length, 0);
 
   info("Faking timeout expiration and checking that events are sent");
   observer.eventLoopTimer();
   Assert.equal(reflowsEvents.length, 1);
   Assert.equal(reflowsEvents[0].length, 2);
   Assert.equal(resizeEvents.length, 1);
 
   observer.off("reflows", onReflows);
   observer.off("resize", onResize);
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function noEventsAreSentWhenThereAreNoReflowsAndLoopTimeouts() {
   info("Checking that if no reflows were detected and the event batching " +
   "loop expires, then no reflows event is sent");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
 
   const reflowsEvents = [];
   const onReflows = (reflows) => reflowsEvents.push(reflows);
   observer.on("reflows", onReflows);
 
   info("Faking timeout expiration and checking for reflows");
   observer.eventLoopTimer();
   Assert.equal(reflowsEvents.length, 0);
 
   observer.off("reflows", onReflows);
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function observerIsAlreadyStarted() {
   info("Checking that the observer is already started when getting it");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
   Assert.ok(observer.isObserving);
 
   observer.stop();
   Assert.ok(!observer.isObserving);
 
   observer.start();
   Assert.ok(observer.isObserving);
 
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function destroyStopsObserving() {
   info("Checking that the destroying the observer stops it");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
   Assert.ok(observer.isObserving);
 
   observer.destroy();
   Assert.ok(!observer.isObserving);
 
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function stoppingAndStartingSeveralTimesWorksCorrectly() {
   info("Checking that the stopping and starting several times the observer" +
     " works correctly");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
 
   Assert.ok(observer.isObserving);
   observer.start();
   observer.start();
   observer.start();
   Assert.ok(observer.isObserving);
 
   observer.stop();
   Assert.ok(!observer.isObserving);
 
   observer.stop();
   observer.stop();
   Assert.ok(!observer.isObserving);
 
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function reflowsArentStackedWhenStopped() {
   info("Checking that when stopped, reflows aren't stacked in the observer");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
 
   info("Stoping the observer");
   observer.stop();
 
   info("Faking reflows");
-  tabActor.window.docShell.observer.reflow();
-  tabActor.window.docShell.observer.reflow();
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
 
   info("Checking that reflows aren't recorded");
   Assert.equal(observer.reflows.length, 0);
 
   info("Starting the observer and faking more reflows");
   observer.start();
-  tabActor.window.docShell.observer.reflow();
-  tabActor.window.docShell.observer.reflow();
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
 
   info("Checking that reflows are recorded");
   Assert.equal(observer.reflows.length, 3);
 
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
 
 function stackedReflowsAreResetOnStop() {
   info("Checking that stacked reflows are reset on stop");
 
-  const tabActor = new MockTabActor();
-  const observer = getLayoutChangesObserver(tabActor);
+  const targetActor = new MockTargetActor();
+  const observer = getLayoutChangesObserver(targetActor);
 
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
   Assert.equal(observer.reflows.length, 1);
 
   observer.stop();
   Assert.equal(observer.reflows.length, 0);
 
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
   Assert.equal(observer.reflows.length, 0);
 
   observer.start();
   Assert.equal(observer.reflows.length, 0);
 
-  tabActor.window.docShell.observer.reflow();
+  targetActor.window.docShell.observer.reflow();
   Assert.equal(observer.reflows.length, 1);
 
-  releaseLayoutChangesObserver(tabActor);
+  releaseLayoutChangesObserver(targetActor);
 }
--- a/devtools/server/tests/unit/test_promises_actor_attach.js
+++ b/devtools/server/tests/unit/test_promises_actor_attach.js
@@ -9,17 +9,17 @@
  */
 
 const { PromisesFront } = require("devtools/shared/fronts/promises");
 
 add_task(async function() {
   const client = await startTestDebuggerServer("promises-actor-test");
   const chromeActors = await getChromeActors(client);
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testAttach(client, chromeActors);
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-actor-test");
   ok(targetTab, "Found our target tab.");
 
   const [ tabResponse ] = await attachTab(client, targetTab);
--- a/devtools/server/tests/unit/test_promises_actor_exist.js
+++ b/devtools/server/tests/unit/test_promises_actor_exist.js
@@ -10,22 +10,22 @@
 
 add_task(async function() {
   const client = await startTestDebuggerServer("promises-actor-test");
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-actor-test");
   Assert.ok(targetTab, "Found our target tab.");
 
-  // Attach to the TabActor and check the response
+  // Attach to the BrowsingContextTargetActor and check the response
   await new Promise(resolve => {
     client.request({ to: targetTab.actor, type: "attach" }, response => {
       Assert.ok(!("error" in response), "Expect no error in response.");
       Assert.equal(response.from, targetTab.actor,
-        "Expect the target TabActor in response form field.");
+        "Expect the target BrowsingContextTargetActor in response form field.");
       Assert.equal(response.type, "tabAttached",
         "Expect tabAttached in the response type.");
       Assert.ok(typeof response.promisesActor === "string",
         "Should have a tab context PromisesActor.");
       resolve();
     });
   });
 
--- a/devtools/server/tests/unit/test_promises_actor_list_promises.js
+++ b/devtools/server/tests/unit/test_promises_actor_list_promises.js
@@ -10,17 +10,17 @@
 
 const { PromisesFront } = require("devtools/shared/fronts/promises");
 const SECRET = "MyLittleSecret";
 
 add_task(async function() {
   const client = await startTestDebuggerServer("promises-actor-test");
   const chromeActors = await getChromeActors(client);
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testListPromises(client, chromeActors, v =>
     new Promise(resolve => resolve(v)));
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-actor-test");
   ok(targetTab, "Found our target tab.");
 
--- a/devtools/server/tests/unit/test_promises_actor_onnewpromise.js
+++ b/devtools/server/tests/unit/test_promises_actor_onnewpromise.js
@@ -13,17 +13,17 @@ const { PromisesFront } = require("devto
 var EventEmitter = require("devtools/shared/event-emitter");
 
 add_task(async function() {
   const client = await startTestDebuggerServer("promises-actor-test");
   const chromeActors = await getChromeActors(client);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise");
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testNewPromisesEvent(client, chromeActors,
     v => new Promise(resolve => resolve(v)));
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-actor-test");
   ok(targetTab, "Found our target tab.");
 
--- a/devtools/server/tests/unit/test_promises_actor_onpromisesettled.js
+++ b/devtools/server/tests/unit/test_promises_actor_onpromisesettled.js
@@ -15,17 +15,17 @@ const { PromisesFront } = require("devto
 var EventEmitter = require("devtools/shared/event-emitter");
 
 add_task(async function() {
   const client = await startTestDebuggerServer("promises-actor-test");
   const chromeActors = await getChromeActors(client);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise");
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testPromisesSettled(client, chromeActors,
     v => new Promise(resolve => resolve(v)),
     v => new Promise((resolve, reject) => reject(v)));
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-actor-test");
   ok(targetTab, "Found our target tab.");
--- a/devtools/server/tests/unit/test_promises_object_creationtimestamp.js
+++ b/devtools/server/tests/unit/test_promises_object_creationtimestamp.js
@@ -22,17 +22,17 @@ add_task(async function() {
     Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
   });
 
   const client = await startTestDebuggerServer("promises-object-test");
   const chromeActors = await getChromeActors(client);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testPromiseCreationTimestamp(client, chromeActors, v => {
     return new Promise(resolve => resolve(v));
   });
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "promises-object-test");
   ok(targetTab, "Found our target tab.");
--- a/devtools/server/tests/unit/test_promises_object_timetosettle-01.js
+++ b/devtools/server/tests/unit/test_promises_object_timetosettle-01.js
@@ -13,17 +13,17 @@ const { PromisesFront } = require("devto
 var EventEmitter = require("devtools/shared/event-emitter");
 
 add_task(async function() {
   const client = await startTestDebuggerServer("test-promises-timetosettle");
   const chromeActors = await getChromeActors(client);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testGetTimeToSettle(client, chromeActors, () => {
     const p = new Promise(() => {});
     p.name = "p";
     const q = p.then();
     q.name = "q";
 
     return p;
--- a/devtools/server/tests/unit/test_promises_object_timetosettle-02.js
+++ b/devtools/server/tests/unit/test_promises_object_timetosettle-02.js
@@ -15,17 +15,17 @@ var EventEmitter = require("devtools/sha
 
 add_task(async function() {
   const client = await startTestDebuggerServer("test-promises-timetosettle");
   const chromeActors = await getChromeActors(client);
   await attachTab(client, chromeActors);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
 
-  // We have to attach the chrome TabActor before playing with the PromiseActor
+  // We have to attach the chrome target actor before playing with the PromiseActor
   await attachTab(client, chromeActors);
   await testGetTimeToSettle(client, chromeActors,
     v => new Promise(resolve => setTimeout(() => resolve(v), 100)));
 
   const response = await listTabs(client);
   const targetTab = findTab(response.tabs, "test-promises-timetosettle");
   ok(targetTab, "Found our target tab.");
   await attachTab(client, targetTab);
--- a/devtools/server/tests/unit/test_register_actor.js
+++ b/devtools/server/tests/unit/test_register_actor.js
@@ -46,57 +46,57 @@ function test_deprecated_api() {
   check_actors(true);
 
   run_next_test();
 }
 
 // Bug 988237: Test the new lazy actor loading
 function test_lazy_api() {
   let isActorLoaded = false;
-  let isActorInstanciated = false;
+  let isActorInstantiated = false;
   function onActorEvent(subject, topic, data) {
     if (data == "loaded") {
       isActorLoaded = true;
     } else if (data == "instantiated") {
-      isActorInstanciated = true;
+      isActorInstantiated = true;
     }
   }
   Services.obs.addObserver(onActorEvent, "actor");
   DebuggerServer.registerModule("xpcshell-test/registertestactors-03", {
     prefix: "lazy",
     constructor: "LazyActor",
     type: { global: true, tab: true }
   });
   // The actor is immediatly registered, but not loaded
   Assert.ok(DebuggerServer.tabActorFactories.hasOwnProperty("lazyActor"));
   Assert.ok(DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
   Assert.ok(!isActorLoaded);
-  Assert.ok(!isActorInstanciated);
+  Assert.ok(!isActorInstantiated);
 
   const client = new DebuggerClient(DebuggerServer.connectPipe());
   client.connect().then(function onConnect() {
     client.listTabs().then(onListTabs);
   });
   function onListTabs(response) {
     // On listTabs, the actor is still not loaded,
     // but we can see its name in the list of available actors
     Assert.ok(!isActorLoaded);
-    Assert.ok(!isActorInstanciated);
+    Assert.ok(!isActorInstantiated);
     Assert.ok("lazyActor" in response);
 
     const {LazyFront} = require("xpcshell-test/registertestactors-03");
     const front = LazyFront(client, response);
     front.hello().then(onRequest);
   }
   function onRequest(response) {
     Assert.equal(response, "world");
 
     // Finally, the actor is loaded on the first request being made to it
     Assert.ok(isActorLoaded);
-    Assert.ok(isActorInstanciated);
+    Assert.ok(isActorInstantiated);
 
     Services.obs.removeObserver(onActorEvent, "actor");
     client.close().then(() => run_next_test());
   }
 }
 
 function cleanup() {
   DebuggerServer.destroy();
--- a/devtools/shared/client/debugger-client.js
+++ b/devtools/shared/client/debugger-client.js
@@ -322,38 +322,38 @@ DebuggerClient.prototype = {
     return this.mainRoot.listAddons(onResponse);
   },
 
   getTab: function(filter) {
     return this.mainRoot.getTab(filter);
   },
 
   /**
-   * Attach to a tab actor.
+   * Attach to a tab's target actor.
    *
-   * @param string tabActor
-   *        The actor ID for the tab to attach.
+   * @param string targetActor
+   *        The target actor ID for the tab to attach.
    * @param function onResponse
    *        Called with the response packet and a TabClient
    *        (which will be undefined on error).
    */
-  attachTab: function(tabActor, onResponse = noop) {
-    if (this._clients.has(tabActor)) {
-      const cachedTab = this._clients.get(tabActor);
+  attachTab: function(targetActor, onResponse = noop) {
+    if (this._clients.has(targetActor)) {
+      const cachedTab = this._clients.get(targetActor);
       const cachedResponse = {
         cacheDisabled: cachedTab.cacheDisabled,
         javascriptEnabled: cachedTab.javascriptEnabled,
         traits: cachedTab.traits,
       };
       DevToolsUtils.executeSoon(() => onResponse(cachedResponse, cachedTab));
       return promise.resolve([cachedResponse, cachedTab]);
     }
 
     const packet = {
-      to: tabActor,
+      to: targetActor,
       type: "attach"
     };
     return this.request(packet).then(response => {
       let tabClient;
       if (!response.error) {
         tabClient = new TabClient(this, response);
         this.registerClient(tabClient);
       }
--- a/devtools/shared/client/property-iterator-client.js
+++ b/devtools/shared/client/property-iterator-client.js
@@ -12,17 +12,17 @@ const {arg, DebuggerClient} = require("d
  * Note that the properties can be sorted in the backend,
  * this is controled while creating the PropertyIteratorClient
  * from ObjectClient.enumProperties.
  *
  * @param client DebuggerClient
  *        The debugger client parent.
  * @param grip Object
  *        A PropertyIteratorActor grip returned by the protocol via
- *        TabActor.enumProperties request.
+ *        BrowsingContextTargetActor.enumProperties request.
  */
 function PropertyIteratorClient(client, grip) {
   this._grip = grip;
   this._client = client;
   this.request = this._client.request;
 }
 
 PropertyIteratorClient.prototype = {
--- a/devtools/shared/client/root-client.js
+++ b/devtools/shared/client/root-client.js
@@ -188,17 +188,17 @@ RootClient.prototype = {
           result.other.push(worker);
       }
     });
 
     return result;
   },
 
   /**
-   * Fetch the TabActor for the currently selected tab, or for a specific
+   * Fetch the target actor for the currently selected tab, or for a specific
    * tab given as first parameter.
    *
    * @param [optional] object filter
    *        A dictionary object with following optional attributes:
    *         - outerWindowID: used to match tabs in parent process
    *         - tabId: used to match tabs in child processes
    *         - tab: a reference to xul:tab element
    *        If nothing is specified, returns the actor for the currently
--- a/devtools/shared/client/symbol-iterator-client.js
+++ b/devtools/shared/client/symbol-iterator-client.js
@@ -9,17 +9,17 @@ const {arg, DebuggerClient} = require("d
 /**
  * A SymbolIteratorClient provides a way to access to symbols
  * of an object efficiently, slice by slice.
  *
  * @param client DebuggerClient
  *        The debugger client parent.
  * @param grip Object
  *        A SymbolIteratorActor grip returned by the protocol via
- *        TabActor.enumSymbols request.
+ *        BrowsingContextTargetActor.enumSymbols request.
  */
 function SymbolIteratorClient(client, grip) {
   this._grip = grip;
   this._client = client;
   this.request = this._client.request;
 }
 
 SymbolIteratorClient.prototype = {
--- a/devtools/shared/content-observer.js
+++ b/devtools/shared/content-observer.js
@@ -8,18 +8,18 @@ const Services = require("Services");
 
 const EventEmitter = require("devtools/shared/event-emitter");
 
 /**
  * Handles adding an observer for the creation of content document globals,
  * event sent immediately after a web content document window has been set up,
  * but before any script code has been executed.
  */
-function ContentObserver(tabActor) {
-  this._contentWindow = tabActor.window;
+function ContentObserver(targetActor) {
+  this._contentWindow = targetActor.window;
   this._onContentGlobalCreated = this._onContentGlobalCreated.bind(this);
   this._onInnerWindowDestroyed = this._onInnerWindowDestroyed.bind(this);
   this.startListening();
 }
 
 module.exports.ContentObserver = ContentObserver;
 
 ContentObserver.prototype = {
--- a/devtools/shared/protocol.js
+++ b/devtools/shared/protocol.js
@@ -319,17 +319,17 @@ types.addActorType = function(name) {
       }
 
       // Reading a response on the client side, check for an
       // existing front on the connection, and create the front
       // if it isn't found.
       const actorID = typeof (v) === "string" ? v : v.actor;
       let front = ctx.conn.getActor(actorID);
       if (!front) {
-        // If front isn't instanciated yet, create one.
+        // If front isn't instantiated yet, create one.
 
         // Try lazy loading front if not already loaded.
         // The front module will synchronously call `FrontClassWithSpec` and
         // augment `type` with the `frontClass` attribute.
         if (!type.frontClass) {
           lazyLoadFront(name);
         }
 
@@ -1244,17 +1244,17 @@ exports.ActorClassWithSpec = ActorClassW
  * @constructor
  */
 var Front = function(conn = null, form = null, detail = null, context = null) {
   Pool.call(this, conn);
   this._requests = [];
 
   // protocol.js no longer uses this data in the constructor, only external
   // uses do.  External usage of manually-constructed fronts will be
-  // drastically reduced if we convert the root and tab actors to
+  // drastically reduced if we convert the root and target actors to
   // protocol.js, in which case this can probably go away.
   if (form) {
     this.actorID = form.actor;
     form = types.getType(this.typeName).formType(detail).read(form, this, detail);
     this.form(form, detail, context);
   }
 };
 
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -210,18 +210,18 @@ const Types = exports.__TypesForTests = 
     front: null,
   },
   {
     types: ["symbolIterator"],
     spec: "devtools/shared/specs/symbol-iterator",
     front: null,
   },
   {
-    types: ["tab"],
-    spec: "devtools/shared/specs/tab",
+    types: ["browsingContextTarget"],
+    spec: "devtools/shared/specs/targets/browsing-context",
     front: null,
   },
   {
     types: ["timeline"],
     spec: "devtools/shared/specs/timeline",
     front: "devtools/shared/fronts/timeline",
   },
   {
--- a/devtools/shared/specs/moz.build
+++ b/devtools/shared/specs/moz.build
@@ -1,14 +1,18 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+DIRS += [
+    'targets',
+]
+
 DevToolsModules(
     'accessibility.js',
     'actor-registry.js',
     'addons.js',
     'animation.js',
     'breakpoint.js',
     'call-watcher.js',
     'canvas.js',
@@ -38,17 +42,16 @@ DevToolsModules(
     'script.js',
     'source.js',
     'storage.js',
     'string.js',
     'styles.js',
     'stylesheets.js',
     'symbol-iterator.js',
     'symbol.js',
-    'tab.js',
     'timeline.js',
     'webaudio.js',
     'webconsole.js',
     'webextension-inspected-window.js',
     'webextension-parent.js',
     'webgl.js',
     'worker.js'
 )
rename from devtools/shared/specs/tab.js
rename to devtools/shared/specs/targets/browsing-context.js
--- a/devtools/shared/specs/tab.js
+++ b/devtools/shared/specs/targets/browsing-context.js
@@ -1,115 +1,115 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const {types, generateActorSpec, RetVal, Option} = require("devtools/shared/protocol");
 
-types.addDictType("tab.attach", {
+types.addDictType("browsingContextTarget.attach", {
   type: "string",
   threadActor: "number",
   cacheDisabled: "boolean",
   javascriptEnabled: "boolean",
   traits: "json"
 });
 
-types.addDictType("tab.detach", {
+types.addDictType("browsingContextTarget.detach", {
   error: "nullable:string",
   type: "nullable:string"
 });
 
-types.addDictType("tab.switchtoframe", {
+types.addDictType("browsingContextTarget.switchtoframe", {
   error: "nullable:string",
   message: "nullable:string"
 });
 
-types.addDictType("tab.listframes", {
-  frames: "array:tab.window"
+types.addDictType("browsingContextTarget.listframes", {
+  frames: "array:browsingContextTarget.window"
 });
 
-types.addDictType("tab.window", {
+types.addDictType("browsingContextTarget.window", {
   id: "string",
   parentID: "nullable:string",
   url: "string",
   title: "string"
 });
 
-types.addDictType("tab.workers", {
+types.addDictType("browsingContextTarget.workers", {
   error: "nullable:string"
 });
 
-types.addDictType("tab.reload", {
+types.addDictType("browsingContextTarget.reload", {
   force: "boolean"
 });
 
-types.addDictType("tab.reconfigure", {
+types.addDictType("browsingContextTarget.reconfigure", {
   javascriptEnabled: "nullable:boolean",
   cacheDisabled: "nullable:boolean",
   serviceWorkersTestingEnabled: "nullable:boolean",
   performReload: "nullable:boolean"
 });
 
-const tabSpec = generateActorSpec({
-  typeName: "tab",
+const browsingContextTargetSpec = generateActorSpec({
+  typeName: "browsingContextTarget",
 
   methods: {
     attach: {
       request: {},
-      response: RetVal("tab.attach")
+      response: RetVal("browsingContextTarget.attach")
     },
     detach: {
       request: {},
-      response: RetVal("tab.detach")
+      response: RetVal("browsingContextTarget.detach")
     },
     ensureCSSErrorReportingEnabled: {
       request: {},
       response: {}
     },
     focus: {
       request: {},
       response: {}
     },
     reload: {
       request: {
-        options: Option(0, "tab.reload"),
+        options: Option(0, "browsingContextTarget.reload"),
       },
       response: {}
     },
     navigateTo: {
       request: {
         url: Option(0, "string"),
       },
       response: {}
     },
     reconfigure: {
       request: {
-        options: Option(0, "tab.reconfigure")
+        options: Option(0, "browsingContextTarget.reconfigure")
       },
       response: {}
     },
     switchToFrame: {
       request: {
         windowId: Option(0, "string")
       },
-      response: RetVal("tab.switchtoframe")
+      response: RetVal("browsingContextTarget.switchtoframe")
     },
     listFrames: {
       request: {},
-      response: RetVal("tab.listframes")
+      response: RetVal("browsingContextTarget.listframes")
     },
     listWorkers: {
       request: {},
-      response: RetVal("tab.workers")
+      response: RetVal("browsingContextTarget.workers")
     },
     logInPage: {
       request: {
         text: Option(0, "string"),
         category: Option(0, "string"),
         flags: Option(0, "string")
       },
       response: {}
     }
   }
 });
 
-exports.tabSpec = tabSpec;
+exports.browsingContextTargetSpec = browsingContextTargetSpec;
new file mode 100644
--- /dev/null
+++ b/devtools/shared/specs/targets/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+    'browsing-context.js',
+)
--- a/devtools/shared/tests/unit/test_protocol_index.js
+++ b/devtools/shared/tests/unit/test_protocol_index.js
@@ -24,28 +24,28 @@ function test_index_is_alphabetically_so
     lastSpec = spec;
   }
   ok(true, "Specs index is alphabetically sorted");
 }
 
 function test_specs() {
   for (const type of Types) {
     for (const typeName of type.types) {
-      ok(getType(typeName), `${typeName} spec is defined`);
+      ok(!!getType(typeName), `${typeName} spec is defined`);
     }
   }
   ok(true, "Specs are all accessible");
 }
 
 function test_fronts() {
   for (const item of Types) {
     if (!item.front) {
       continue;
     }
     for (const typeName of item.types) {
       lazyLoadFront(typeName);
       const type = getType(typeName);
-      ok(type, `Front for ${typeName} has a spec`);
+      ok(!!type, `Front for ${typeName} has a spec`);
       ok(type.frontClass, `${typeName} has a front correctly defined`);
     }
   }
   ok(true, "Front are all accessible");
 }
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -1732,17 +1732,17 @@ NetworkMonitor.prototype = {
  * log the network requests for this child process.
  *
  * The main process creates NetworkEventActorProxy instances per request. These
  * send the data to this object using the nsIMessageManager. Here we proxy the
  * data to the WebConsoleActor or to a NetworkEventActor.
  *
  * @constructor
  * @param number outerWindowID
- *        The outerWindowID of the TabActor's main window.
+ *        The outerWindowID of the target actor's main window.
  * @param nsIMessageManager messageManager
  *        The nsIMessageManager to use to communicate with the parent process.
  * @param object DebuggerServerConnection
  *        The RDP connection to the client.
  * @param object owner
  *        The WebConsoleActor that is listening for the network requests.
  */
 function NetworkMonitorChild(outerWindowID, messageManager, conn, owner) {