Bug 1350646: Part 10 - Remove SDK tabs/windows modules. r?Mossop draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 05 Aug 2017 22:02:47 -0700
changeset 641190 788a1233cb6df1cbfd252e203b9e844cfa018675
parent 641189 94d0e896615122c79610be399c5cc05a4d47b339
child 641191 3cd6689918813d18a676c692d8ceb85a849225af
push id72469
push usermaglione.k@gmail.com
push dateSun, 06 Aug 2017 07:23:41 +0000
reviewersMossop
bugs1350646
milestone57.0a1
Bug 1350646: Part 10 - Remove SDK tabs/windows modules. r?Mossop MozReview-Commit-ID: 4VlwKUNXo8O
addon-sdk/moz.build
addon-sdk/source/lib/framescript/FrameScriptManager.jsm
addon-sdk/source/lib/framescript/content.jsm
addon-sdk/source/lib/framescript/manager.js
addon-sdk/source/lib/framescript/util.js
addon-sdk/source/lib/sdk/content/content-worker.js
addon-sdk/source/lib/sdk/content/content.js
addon-sdk/source/lib/sdk/content/sandbox.js
addon-sdk/source/lib/sdk/content/sandbox/events.js
addon-sdk/source/lib/sdk/content/tab-events.js
addon-sdk/source/lib/sdk/content/worker-child.js
addon-sdk/source/lib/sdk/content/worker.js
addon-sdk/source/lib/sdk/deprecated/sync-worker.js
addon-sdk/source/lib/sdk/deprecated/unit-test.js
addon-sdk/source/lib/sdk/loader/sandbox.js
addon-sdk/source/lib/sdk/remote/child.js
addon-sdk/source/lib/sdk/remote/core.js
addon-sdk/source/lib/sdk/remote/parent.js
addon-sdk/source/lib/sdk/remote/utils.js
addon-sdk/source/lib/sdk/selection.js
addon-sdk/source/lib/sdk/tab/events.js
addon-sdk/source/lib/sdk/tabs.js
addon-sdk/source/lib/sdk/tabs/common.js
addon-sdk/source/lib/sdk/tabs/events.js
addon-sdk/source/lib/sdk/tabs/helpers.js
addon-sdk/source/lib/sdk/tabs/namespace.js
addon-sdk/source/lib/sdk/tabs/observer.js
addon-sdk/source/lib/sdk/tabs/tab-fennec.js
addon-sdk/source/lib/sdk/tabs/tab-firefox.js
addon-sdk/source/lib/sdk/tabs/tab.js
addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
addon-sdk/source/lib/sdk/tabs/utils.js
addon-sdk/source/lib/sdk/tabs/worker.js
addon-sdk/source/lib/sdk/test/utils.js
addon-sdk/source/lib/sdk/window/browser.js
addon-sdk/source/lib/sdk/window/events.js
addon-sdk/source/lib/sdk/window/helpers.js
addon-sdk/source/lib/sdk/window/namespace.js
addon-sdk/source/lib/sdk/windows.js
addon-sdk/source/lib/sdk/windows/fennec.js
addon-sdk/source/lib/sdk/windows/firefox.js
addon-sdk/source/lib/sdk/windows/observer.js
addon-sdk/source/lib/sdk/windows/tabs-fennec.js
addon-sdk/source/lib/sdk/worker/utils.js
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -16,47 +16,36 @@ EXTRA_JS_MODULES.sdk += [
     'source/app-extension/bootstrap.js',
 ]
 
 EXTRA_JS_MODULES.sdk.system += [
     'source/modules/system/Startup.js',
 ]
 
 modules = [
-    'framescript/FrameScriptManager.jsm',
-    'framescript/content.jsm',
-    'framescript/manager.js',
-    'framescript/util.js',
     'index.js',
     'jetpack-id/index.js',
     'method/core.js',
     'method/test/browser.js',
     'method/test/common.js',
     'mozilla-toolkit-versioning/index.js',
     'mozilla-toolkit-versioning/lib/utils.js',
     'node/os.js',
     'sdk/addon/installer.js',
     'sdk/addon/window.js',
     'sdk/base64.js',
     'sdk/browser/events.js',
     'sdk/clipboard.js',
     'sdk/console/plain-text.js',
     'sdk/console/traceback.js',
-    'sdk/content/content-worker.js',
-    'sdk/content/content.js',
     'sdk/content/events.js',
     'sdk/content/loader.js',
     'sdk/content/mod.js',
-    'sdk/content/sandbox.js',
-    'sdk/content/sandbox/events.js',
-    'sdk/content/tab-events.js',
     'sdk/content/thumbnail.js',
     'sdk/content/utils.js',
-    'sdk/content/worker-child.js',
-    'sdk/content/worker.js',
     'sdk/core/disposable.js',
     'sdk/core/heritage.js',
     'sdk/core/namespace.js',
     'sdk/core/observer.js',
     'sdk/core/promise.js',
     'sdk/core/reference.js',
     'sdk/deprecated/api-utils.js',
     'sdk/deprecated/events/assembler.js',
@@ -97,50 +86,32 @@ modules = [
     'sdk/passwords/utils.js',
     'sdk/platform/xpcom.js',
     'sdk/preferences/event-target.js',
     'sdk/preferences/service.js',
     'sdk/preferences/utils.js',
     'sdk/private-browsing.js',
     'sdk/private-browsing/utils.js',
     'sdk/querystring.js',
-    'sdk/remote/child.js',
-    'sdk/remote/core.js',
-    'sdk/remote/parent.js',
-    'sdk/remote/utils.js',
     'sdk/request.js',
-    'sdk/selection.js',
     'sdk/self.js',
     'sdk/simple-prefs.js',
     'sdk/simple-storage.js',
     'sdk/stylesheet/style.js',
     'sdk/stylesheet/utils.js',
     'sdk/system.js',
     'sdk/system/environment.js',
     'sdk/system/events-shimmed.js',
     'sdk/system/events.js',
     'sdk/system/globals.js',
     'sdk/system/process.js',
     'sdk/system/runtime.js',
     'sdk/system/unload.js',
     'sdk/system/xul-app.js',
     'sdk/system/xul-app.jsm',
-    'sdk/tab/events.js',
-    'sdk/tabs.js',
-    'sdk/tabs/common.js',
-    'sdk/tabs/events.js',
-    'sdk/tabs/helpers.js',
-    'sdk/tabs/namespace.js',
-    'sdk/tabs/observer.js',
-    'sdk/tabs/tab-fennec.js',
-    'sdk/tabs/tab-firefox.js',
-    'sdk/tabs/tab.js',
-    'sdk/tabs/tabs-firefox.js',
-    'sdk/tabs/utils.js',
-    'sdk/tabs/worker.js',
     'sdk/test.js',
     'sdk/test/assert.js',
     'sdk/test/harness.js',
     'sdk/test/httpd.js',
     'sdk/test/loader.js',
     'sdk/test/memory.js',
     'sdk/test/options.js',
     'sdk/test/runner.js',
@@ -154,27 +125,17 @@ modules = [
     'sdk/util/contract.js',
     'sdk/util/deprecate.js',
     'sdk/util/dispatcher.js',
     'sdk/util/list.js',
     'sdk/util/object.js',
     'sdk/util/sequence.js',
     'sdk/util/uuid.js',
     'sdk/view/core.js',
-    'sdk/window/browser.js',
-    'sdk/window/events.js',
-    'sdk/window/helpers.js',
-    'sdk/window/namespace.js',
     'sdk/window/utils.js',
-    'sdk/windows.js',
-    'sdk/windows/fennec.js',
-    'sdk/windows/firefox.js',
-    'sdk/windows/observer.js',
-    'sdk/windows/tabs-fennec.js',
-    'sdk/worker/utils.js',
     'sdk/zip/utils.js',
     'test.js',
     'toolkit/loader.js',
     'toolkit/require.js',
 ]
 
 commonjs = EXTRA_JS_MODULES.commonjs
 
deleted file mode 100644
--- a/addon-sdk/source/lib/framescript/FrameScriptManager.jsm
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 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 globalMM = Components.classes["@mozilla.org/globalmessagemanager;1"].
-                 getService(Components.interfaces.nsIMessageListenerManager);
-
-// Load frame scripts from the same dir as this module.
-// Since this JSM will be loaded using require(), PATH will be
-// overridden while running tests, just like any other module.
-const PATH = __URI__.replace('framescript/FrameScriptManager.jsm', '');
-
-// Builds a unique loader ID for this runtime. We prefix with the SDK path so
-// overriden versions of the SDK don't conflict
-var LOADER_ID = 0;
-this.getNewLoaderID = () => {
-  return PATH + ":" + LOADER_ID++;
-}
-
-const frame_script = function(contentFrame, PATH) {
-  let { registerContentFrame } = Components.utils.import(PATH + 'framescript/content.jsm', {});
-  registerContentFrame(contentFrame);
-}
-globalMM.loadFrameScript("data:,(" + frame_script.toString() + ")(this, " + JSON.stringify(PATH) + ");", true);
-
-this.EXPORTED_SYMBOLS = ['getNewLoaderID'];
deleted file mode 100644
--- a/addon-sdk/source/lib/framescript/content.jsm
+++ /dev/null
@@ -1,94 +0,0 @@
-/* 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 { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-const { Services } = Cu.import('resource://gre/modules/Services.jsm');
-
-const cpmm = Cc['@mozilla.org/childprocessmessagemanager;1'].
-             getService(Ci.nsISyncMessageSender);
-
-this.EXPORTED_SYMBOLS = ["registerContentFrame"];
-
-// This may be an overriden version of the SDK so use the PATH as a key for the
-// initial messages before we have a loaderID.
-const PATH = __URI__.replace('framescript/content.jsm', '');
-
-const { Loader } = Cu.import(PATH + 'toolkit/loader.js', {});
-
-// one Loader instance per addon (per @loader/options to be precise)
-var addons = new Map();
-
-// Tell the parent that a new process is ready
-cpmm.sendAsyncMessage('sdk/remote/process/start', {
-  modulePath: PATH
-});
-
-// Load a child process module loader with the given loader options
-cpmm.addMessageListener('sdk/remote/process/load', ({ data: { modulePath, loaderID, options, reason } }) => {
-  if (modulePath != PATH)
-    return;
-
-  // During startup races can mean we get a second load message
-  if (addons.has(loaderID))
-    return;
-
-  options.waiveInterposition = true;
-
-  let loader = Loader.Loader(options);
-  let addon = {
-    loader,
-    require: Loader.Require(loader, { id: 'LoaderHelper' }),
-  }
-  addons.set(loaderID, addon);
-
-  cpmm.sendAsyncMessage('sdk/remote/process/attach', {
-    loaderID,
-    processID: Services.appinfo.processID,
-    isRemote: Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
-  });
-
-  addon.child = addon.require('sdk/remote/child');
-
-  for (let contentFrame of frames.values())
-    addon.child.registerContentFrame(contentFrame);
-});
-
-// Unload a child process loader
-cpmm.addMessageListener('sdk/remote/process/unload', ({ data: { loaderID, reason } }) => {
-  if (!addons.has(loaderID))
-    return;
-
-  let addon = addons.get(loaderID);
-  Loader.unload(addon.loader, reason);
-
-  // We want to drop the reference to the loader but never allow creating a new
-  // loader with the same ID
-  addons.set(loaderID, {});
-})
-
-
-var frames = new Set();
-
-this.registerContentFrame = contentFrame => {
-  contentFrame.addEventListener("unload", () => {
-    unregisterContentFrame(contentFrame);
-  });
-
-  frames.add(contentFrame);
-
-  for (let addon of addons.values()) {
-    if ("child" in addon)
-      addon.child.registerContentFrame(contentFrame);
-  }
-};
-
-function unregisterContentFrame(contentFrame) {
-  frames.delete(contentFrame);
-
-  for (let addon of addons.values()) {
-    if ("child" in addon)
-      addon.child.unregisterContentFrame(contentFrame);
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/framescript/manager.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const mime = "application/javascript";
-const requireURI = module.uri.replace("framescript/manager.js",
-                                      "toolkit/require.js");
-
-const requireLoadURI = `data:${mime},this["Components"].utils.import("${requireURI}")`
-
-// Loads module with given `id` into given `messageManager` via shared module loader. If `init`
-// string is passed, will call module export with that name and pass frame script environment
-// of the `messageManager` into it. Since module will load only once per process (which is
-// once for chrome proces & second for content process) it is useful to have an init function
-// to setup event listeners on each content frame.
-const loadModule = (messageManager, id, allowDelayed, init) => {
-  const moduleLoadURI = `${requireLoadURI}.require("${id}")`
-  const uri = init ? `${moduleLoadURI}.${init}(this)` : moduleLoadURI;
-  messageManager.loadFrameScript(uri, allowDelayed);
-};
-exports.loadModule = loadModule;
deleted file mode 100644
--- a/addon-sdk/source/lib/framescript/util.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-
-const { Ci } = require("chrome");
-
-const windowToMessageManager = window =>
-  window.
-    QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDocShell).
-    sameTypeRootTreeItem.
-    QueryInterface(Ci.nsIDocShell).
-    QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIContentFrameMessageManager);
-exports.windowToMessageManager = windowToMessageManager;
-
-const nodeToMessageManager = node =>
-  windowToMessageManager(node.ownerGlobal);
-exports.nodeToMessageManager = nodeToMessageManager;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/content-worker.js
+++ /dev/null
@@ -1,305 +0,0 @@
-/* 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/. */
-
-Object.freeze({
-  // TODO: Bug 727854 Use same implementation than common JS modules,
-  // i.e. EventEmitter module
-
-  /**
-   * Create an EventEmitter instance.
-   */
-  createEventEmitter: function createEventEmitter(emit) {
-    let listeners = Object.create(null);
-    let eventEmitter = Object.freeze({
-      emit: emit,
-      on: function on(name, callback) {
-        if (typeof callback !== "function")
-          return this;
-        if (!(name in listeners))
-          listeners[name] = [];
-        listeners[name].push(callback);
-        return this;
-      },
-      once: function once(name, callback) {
-        eventEmitter.on(name, function onceCallback() {
-          eventEmitter.removeListener(name, onceCallback);
-          callback.apply(callback, arguments);
-        });
-      },
-      removeListener: function removeListener(name, callback) {
-        if (!(name in listeners))
-          return;
-        let index = listeners[name].indexOf(callback);
-        if (index == -1)
-          return;
-        listeners[name].splice(index, 1);
-      }
-    });
-    function onEvent(name) {
-      if (!(name in listeners))
-        return [];
-      let args = Array.slice(arguments, 1);
-      let results = [];
-      for (let callback of listeners[name]) {
-        results.push(callback.apply(null, args));
-      }
-      return results;
-    }
-    return {
-      eventEmitter: eventEmitter,
-      emit: onEvent
-    };
-  },
-
-  /**
-   * Create an EventEmitter instance to communicate with chrome module
-   * by passing only strings between compartments.
-   * This function expects `emitToChrome` function, that allows to send
-   * events to the chrome module. It returns the EventEmitter as `pipe`
-   * attribute, and, `onChromeEvent` a function that allows chrome module
-   * to send event into the EventEmitter.
-   *
-   *                  pipe.emit --> emitToChrome
-   *              onChromeEvent --> callback registered through pipe.on
-   */
-  createPipe: function createPipe(emitToChrome) {
-    let ContentWorker = this;
-    function onEvent(type, ...args) {
-      // JSON.stringify is buggy with cross-sandbox values,
-      // it may return "{}" on functions. Use a replacer to match them correctly.
-      let replacer = (k, v) =>
-        typeof(v) === "function"
-          ? (type === "console" ? Function.toString.call(v) : void(0))
-          : v;
-
-      let str = JSON.stringify([type, ...args], replacer);
-      emitToChrome(str);
-    }
-
-    let { eventEmitter, emit } =
-      ContentWorker.createEventEmitter(onEvent);
-
-    return {
-      pipe: eventEmitter,
-      onChromeEvent: function onChromeEvent(array) {
-        // We either receive a stringified array, or a real array.
-        // We still allow to pass an array of objects, in WorkerSandbox.emitSync
-        // in order to allow sending DOM node reference between content script
-        // and modules (only used for context-menu API)
-        let args = typeof array == "string" ? JSON.parse(array) : array;
-        return emit.apply(null, args);
-      }
-    };
-  },
-
-  injectConsole: function injectConsole(exports, pipe) {
-    exports.console = Object.freeze({
-      log: pipe.emit.bind(null, "console", "log"),
-      info: pipe.emit.bind(null, "console", "info"),
-      warn: pipe.emit.bind(null, "console", "warn"),
-      error: pipe.emit.bind(null, "console", "error"),
-      debug: pipe.emit.bind(null, "console", "debug"),
-      exception: pipe.emit.bind(null, "console", "exception"),
-      trace: pipe.emit.bind(null, "console", "trace"),
-      time: pipe.emit.bind(null, "console", "time"),
-      timeEnd: pipe.emit.bind(null, "console", "timeEnd")
-    });
-  },
-
-  injectTimers: function injectTimers(exports, chromeAPI, pipe, console) {
-    // wrapped functions from `'timer'` module.
-    // Wrapper adds `try catch` blocks to the callbacks in order to
-    // emit `error` event if exception is thrown in
-    // the Worker global scope.
-    // @see http://www.w3.org/TR/workers/#workerutils
-
-    // List of all living timeouts/intervals
-    let _timers = Object.create(null);
-
-    // Keep a reference to original timeout functions
-    let {
-      setTimeout: chromeSetTimeout,
-      setInterval: chromeSetInterval,
-      clearTimeout: chromeClearTimeout,
-      clearInterval: chromeClearInterval
-    } = chromeAPI.timers;
-
-    function registerTimer(timer) {
-      let registerMethod = null;
-      if (timer.kind == "timeout")
-        registerMethod = chromeSetTimeout;
-      else if (timer.kind == "interval")
-        registerMethod = chromeSetInterval;
-      else
-        throw new Error("Unknown timer kind: " + timer.kind);
-
-      if (typeof timer.fun == 'string') {
-        let code = timer.fun;
-        timer.fun = () => chromeAPI.sandbox.evaluate(exports, code);
-      } else if (typeof timer.fun != 'function') {
-        throw new Error('Unsupported callback type' + typeof timer.fun);
-      }
-
-      let id = registerMethod(onFire, timer.delay);
-      function onFire() {
-        try {
-          if (timer.kind == "timeout")
-            delete _timers[id];
-          timer.fun.apply(null, timer.args);
-        } catch(e) {
-          console.exception(e);
-          let wrapper = {
-            instanceOfError: instanceOf(e, Error),
-            value: e,
-          };
-          if (wrapper.instanceOfError) {
-            wrapper.value = {
-              message: e.message,
-              fileName: e.fileName,
-              lineNumber: e.lineNumber,
-              stack: e.stack,
-              name: e.name,
-            };
-          }
-          pipe.emit('error', wrapper);
-        }
-      }
-      _timers[id] = timer;
-      return id;
-    }
-
-    // copied from sdk/lang/type.js since modules are not available here
-    function instanceOf(value, Type) {
-      var isConstructorNameSame;
-      var isConstructorSourceSame;
-
-      // If `instanceof` returned `true` we know result right away.
-      var isInstanceOf = value instanceof Type;
-
-      // If `instanceof` returned `false` we do ducktype check since `Type` may be
-      // from a different sandbox. If a constructor of the `value` or a constructor
-      // of the value's prototype has same name and source we assume that it's an
-      // instance of the Type.
-      if (!isInstanceOf && value) {
-        isConstructorNameSame = value.constructor.name === Type.name;
-        isConstructorSourceSame = String(value.constructor) == String(Type);
-        isInstanceOf = (isConstructorNameSame && isConstructorSourceSame) ||
-                        instanceOf(Object.getPrototypeOf(value), Type);
-      }
-      return isInstanceOf;
-    }
-
-    function unregisterTimer(id) {
-      if (!(id in _timers))
-        return;
-      let { kind } = _timers[id];
-      delete _timers[id];
-      if (kind == "timeout")
-        chromeClearTimeout(id);
-      else if (kind == "interval")
-        chromeClearInterval(id);
-      else
-        throw new Error("Unknown timer kind: " + kind);
-    }
-
-    function disableAllTimers() {
-      Object.keys(_timers).forEach(unregisterTimer);
-    }
-
-    exports.setTimeout = function ContentScriptSetTimeout(callback, delay) {
-      return registerTimer({
-        kind: "timeout",
-        fun: callback,
-        delay: delay,
-        args: Array.slice(arguments, 2)
-      });
-    };
-    exports.clearTimeout = function ContentScriptClearTimeout(id) {
-      unregisterTimer(id);
-    };
-
-    exports.setInterval = function ContentScriptSetInterval(callback, delay) {
-      return registerTimer({
-        kind: "interval",
-        fun: callback,
-        delay: delay,
-        args: Array.slice(arguments, 2)
-      });
-    };
-    exports.clearInterval = function ContentScriptClearInterval(id) {
-      unregisterTimer(id);
-    };
-
-    // On page-hide, save a list of all existing timers before disabling them,
-    // in order to be able to restore them on page-show.
-    // These events are fired when the page goes in/out of bfcache.
-    // https://developer.mozilla.org/En/Working_with_BFCache
-    let frozenTimers = [];
-    pipe.on("pageshow", function onPageShow() {
-      frozenTimers.forEach(registerTimer);
-    });
-    pipe.on("pagehide", function onPageHide() {
-      frozenTimers = [];
-      for (let id in _timers)
-        frozenTimers.push(_timers[id]);
-      disableAllTimers();
-      // Some other pagehide listeners may register some timers that won't be
-      // frozen as this particular pagehide listener is called first.
-      // So freeze these timers on next cycle.
-      chromeSetTimeout(function () {
-        for (let id in _timers)
-          frozenTimers.push(_timers[id]);
-        disableAllTimers();
-      }, 0);
-    });
-
-    // Unregister all timers when the page is destroyed
-    // (i.e. when it is removed from bfcache)
-    pipe.on("detach", function clearTimeouts() {
-      disableAllTimers();
-      _timers = {};
-      frozenTimers = [];
-    });
-  },
-
-  injectMessageAPI: function injectMessageAPI(exports, pipe, console) {
-
-    let ContentWorker = this;
-    let { eventEmitter: port, emit : portEmit } =
-      ContentWorker.createEventEmitter(pipe.emit.bind(null, "event"));
-    pipe.on("event", portEmit);
-
-    let self = {
-      port: port,
-      postMessage: pipe.emit.bind(null, "message"),
-      on: pipe.on.bind(null),
-      once: pipe.once.bind(null),
-      removeListener: pipe.removeListener.bind(null),
-    };
-    Object.defineProperty(exports, "self", {
-      value: self
-    });
-  },
-
-  injectOptions: function (exports, options) {
-    Object.defineProperty( exports.self, "options", { value: JSON.parse( options ) });
-  },
-
-  inject: function (exports, chromeAPI, emitToChrome, options) {
-    let ContentWorker = this;
-    let { pipe, onChromeEvent } =
-      ContentWorker.createPipe(emitToChrome);
-
-    ContentWorker.injectConsole(exports, pipe);
-    ContentWorker.injectTimers(exports, chromeAPI, pipe, exports.console);
-    ContentWorker.injectMessageAPI(exports, pipe, exports.console);
-    if ( options !== undefined ) {
-      ContentWorker.injectOptions(exports, options);
-    }
-
-    Object.freeze( exports.self );
-
-    return onChromeEvent;
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/content.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const { deprecateUsage } = require('../util/deprecate');
-
-Object.defineProperty(exports, "Worker", {
-  get: function() {
-    deprecateUsage('`sdk/content/content` is deprecated. Please use `sdk/content/worker` directly.');
-    return require('./worker').Worker;
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ /dev/null
@@ -1,426 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-const { Class } = require('../core/heritage');
-const { EventTarget } = require('../event/target');
-lazyRequire(this, '../event/core', "on", "off", "emit");
-lazyRequire(this, './sandbox/events', "events");
-lazyRequire(this, './utils', "requiresAddonGlobal");
-lazyRequire(this, '../lang/functional', {"delay": "async"});
-const { Ci, Cu, Cc } = require('chrome');
-lazyRequireModule(this, "../timers", "timer");
-lazyRequire(this, '../url', "URL");
-lazyRequire(this, '../loader/sandbox', "sandbox", "evaluate", "load");
-lazyRequire(this, '../util/object', "merge");
-lazyRequire(this, '../tabs/utils', "getTabForContentWindowNoShim");
-lazyRequire(this, '../window/utils', "getInnerId");
-lazyRequire(this, '../console/plain-text', "PlainTextConsole");
-
-lazyRequire(this, '../self', "data");
-lazyRequire(this, '../remote/core', "isChildLoader");
-
-// WeakMap of sandboxes so we can access private values
-const sandboxes = new WeakMap();
-
-/* Trick the linker in order to ensure shipping these files in the XPI.
-  require('./content-worker.js');
-  Then, retrieve URL of these files in the XPI:
-*/
-var prefix = module.uri.split('sandbox.js')[0];
-const CONTENT_WORKER_URL = prefix + 'content-worker.js';
-const metadata = require('@loader/options').metadata;
-
-// Fetch additional list of domains to authorize access to for each content
-// script. It is stored in manifest `metadata` field which contains
-// package.json data. This list is originaly defined by authors in
-// `permissions` attribute of their package.json addon file.
-const permissions = (metadata && metadata['permissions']) || {};
-const EXPANDED_PRINCIPALS = permissions['cross-domain-content'] || [];
-
-const waiveSecurityMembrane = !!permissions['unsafe-content-script'];
-
-const nsIScriptSecurityManager = Ci.nsIScriptSecurityManager;
-const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
-  getService(Ci.nsIScriptSecurityManager);
-
-const JS_VERSION = '1.8';
-
-// Tests whether this window is loaded in a tab
-function isWindowInTab(window) {
-  if (isChildLoader) {
-    let { frames } = require('../remote/child');
-    let frame = frames.getFrameForWindow(window.top);
-    return frame && frame.isTab;
-  }
-  else {
-    // The deprecated sync worker API still does everything in the main process
-    return getTabForContentWindowNoShim(window);
-  }
-}
-
-const WorkerSandbox = Class({
-  implements: [ EventTarget ],
-
-  /**
-   * Emit a message to the worker content sandbox
-   */
-  emit: function emit(type, ...args) {
-    // JSON.stringify is buggy with cross-sandbox values,
-    // it may return "{}" on functions. Use a replacer to match them correctly.
-    let replacer = (k, v) =>
-      typeof(v) === "function"
-        ? (type === "console" ? Function.toString.call(v) : void(0))
-        : v;
-
-    // Ensure having an asynchronous behavior
-    async(() =>
-      emitToContent(this, JSON.stringify([type, ...args], replacer))
-    );
-  },
-
-  /**
-   * Synchronous version of `emit`.
-   * /!\ Should only be used when it is strictly mandatory /!\
-   *     Doesn't ensure passing only JSON values.
-   *     Mainly used by context-menu in order to avoid breaking it.
-   */
-  emitSync: function emitSync(...args) {
-    // because the arguments could be also non JSONable values,
-    // we need to ensure the array instance is created from
-    // the content's sandbox
-    return emitToContent(this, new modelFor(this).sandbox.Array(...args));
-  },
-
-  /**
-   * Configures sandbox and loads content scripts into it.
-   * @param {Worker} worker
-   *    content worker
-   */
-  initialize: function WorkerSandbox(worker, window) {
-    let model = {};
-    sandboxes.set(this, model);
-    model.worker = worker;
-    // We receive a wrapped window, that may be an xraywrapper if it's content
-    let proto = window;
-
-    // TODO necessary?
-    // Ensure that `emit` has always the right `this`
-    this.emit = this.emit.bind(this);
-    this.emitSync = this.emitSync.bind(this);
-
-    // Use expanded principal for content-script if the content is a
-    // regular web content for better isolation.
-    // (This behavior can be turned off for now with the unsafe-content-script
-    // flag to give addon developers time for making the necessary changes)
-    // But prevent it when the Worker isn't used for a content script but for
-    // injecting `addon` object into a Panel scope, for example.
-    // That's because:
-    // 1/ It is useless to use multiple domains as the worker is only used
-    // to communicate with the addon,
-    // 2/ By using it it would prevent the document to have access to any JS
-    // value of the worker. As JS values coming from multiple domain principals
-    // can't be accessed by 'mono-principals' (principal with only one domain).
-    // Even if this principal is for a domain that is specified in the multiple
-    // domain principal.
-    let principals = window;
-    let wantGlobalProperties = [];
-    let isSystemPrincipal = secMan.isSystemPrincipal(
-      window.document.nodePrincipal);
-    if (!isSystemPrincipal && !requiresAddonGlobal(worker)) {
-      if (EXPANDED_PRINCIPALS.length > 0) {
-        // We have to replace XHR constructor of the content document
-        // with a custom cross origin one, automagically added by platform code:
-        delete proto.XMLHttpRequest;
-        wantGlobalProperties.push('XMLHttpRequest');
-      }
-      if (!waiveSecurityMembrane)
-        principals = EXPANDED_PRINCIPALS.concat(window);
-    }
-
-    // Create the sandbox and bind it to window in order for content scripts to
-    // have access to all standard globals (window, document, ...)
-    let content = sandbox(principals, {
-      sandboxPrototype: proto,
-      wantXrays: !requiresAddonGlobal(worker),
-      wantGlobalProperties: wantGlobalProperties,
-      wantExportHelpers: true,
-      sameZoneAs: window,
-      metadata: {
-        SDKContentScript: true,
-        'inner-window-id': getInnerId(window)
-      }
-    });
-    model.sandbox = content;
-
-    // We have to ensure that window.top and window.parent are the exact same
-    // object than window object, i.e. the sandbox global object. But not
-    // always, in case of iframes, top and parent are another window object.
-    let top = window.top === window ? content : content.top;
-    let parent = window.parent === window ? content : content.parent;
-    merge(content, {
-      // We need 'this === window === top' to be true in toplevel scope:
-      get window() {
-        return content;
-      },
-      get top() {
-        return top;
-      },
-      get parent() {
-        return parent;
-      }
-    });
-
-    // Use the Greasemonkey naming convention to provide access to the
-    // unwrapped window object so the content script can access document
-    // JavaScript values.
-    // NOTE: this functionality is experimental and may change or go away
-    // at any time!
-    //
-    // Note that because waivers aren't propagated between origins, we
-    // need the unsafeWindow getter to live in the sandbox.
-    var unsafeWindowGetter =
-      new content.Function('return window.wrappedJSObject || window;');
-    Object.defineProperty(content, 'unsafeWindow', {get: unsafeWindowGetter});
-
-    // Load trusted code that will inject content script API.
-    let ContentWorker = load(content, CONTENT_WORKER_URL);
-
-    // prepare a clean `self.options`
-    let options = 'contentScriptOptions' in worker ?
-      JSON.stringify(worker.contentScriptOptions) :
-      undefined;
-
-    // Then call `inject` method and communicate with this script
-    // by trading two methods that allow to send events to the other side:
-    //   - `onEvent` called by content script
-    //   - `result.emitToContent` called by addon script
-    let onEvent = Cu.exportFunction(onContentEvent.bind(null, this), ContentWorker);
-    let chromeAPI = createChromeAPI(ContentWorker);
-    let result = Cu.waiveXrays(ContentWorker).inject(content, chromeAPI, onEvent, options);
-
-    // Merge `emitToContent` into our private model of the
-    // WorkerSandbox so we can communicate with content script
-    model.emitToContent = result;
-
-    let console = new PlainTextConsole(null, getInnerId(window));
-
-    // Handle messages send by this script:
-    setListeners(this, console);
-
-    // Inject `addon` global into target document if document is trusted,
-    // `addon` in document is equivalent to `self` in content script.
-    if (requiresAddonGlobal(worker)) {
-      Object.defineProperty(getUnsafeWindow(window), 'addon', {
-          value: content.self,
-          configurable: true
-        }
-      );
-    }
-
-    // Inject our `console` into target document if worker doesn't have a tab
-    // (e.g Panel, PageWorker).
-    // `worker.tab` can't be used because bug 804935.
-    if (!isWindowInTab(window)) {
-      let win = getUnsafeWindow(window);
-
-      // export our chrome console to content window, as described here:
-      // https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
-      let con = Cu.createObjectIn(win);
-
-      let genPropDesc = function genPropDesc(fun) {
-        return { enumerable: true, configurable: true, writable: true,
-          value: console[fun] };
-      }
-
-      const properties = {
-        log: genPropDesc('log'),
-        info: genPropDesc('info'),
-        warn: genPropDesc('warn'),
-        error: genPropDesc('error'),
-        debug: genPropDesc('debug'),
-        trace: genPropDesc('trace'),
-        dir: genPropDesc('dir'),
-        group: genPropDesc('group'),
-        groupCollapsed: genPropDesc('groupCollapsed'),
-        groupEnd: genPropDesc('groupEnd'),
-        time: genPropDesc('time'),
-        timeEnd: genPropDesc('timeEnd'),
-        profile: genPropDesc('profile'),
-        profileEnd: genPropDesc('profileEnd'),
-        exception: genPropDesc('exception'),
-        assert: genPropDesc('assert'),
-        count: genPropDesc('count'),
-        table: genPropDesc('table'),
-        clear: genPropDesc('clear'),
-        dirxml: genPropDesc('dirxml'),
-        timeStamp: genPropDesc('timeStamp'),
-      };
-
-      Object.defineProperties(con, properties);
-      Cu.makeObjectPropsNormal(con);
-
-      win.console = con;
-    };
-
-    emit(events, "content-script-before-inserted", {
-      window: window,
-      worker: worker
-    });
-
-    // The order of `contentScriptFile` and `contentScript` evaluation is
-    // intentional, so programs can load libraries like jQuery from script URLs
-    // and use them in scripts.
-    let contentScriptFile = ('contentScriptFile' in worker)
-          ? worker.contentScriptFile
-          : null,
-        contentScript = ('contentScript' in worker)
-          ? worker.contentScript
-          : null;
-
-    if (contentScriptFile)
-      importScripts.apply(null, [this].concat(contentScriptFile));
-
-    if (contentScript) {
-      evaluateIn(
-        this,
-        Array.isArray(contentScript) ? contentScript.join(';\n') : contentScript
-      );
-    }
-  },
-  destroy: function destroy(reason) {
-    if (typeof reason != 'string')
-      reason = '';
-    this.emitSync('event', 'detach', reason);
-    let model = modelFor(this);
-    model.sandbox = null
-    model.worker = null;
-  },
-
-});
-
-exports.WorkerSandbox = WorkerSandbox;
-
-/**
- * Imports scripts to the sandbox by reading files under urls and
- * evaluating its source. If exception occurs during evaluation
- * `'error'` event is emitted on the worker.
- * This is actually an analog to the `importScript` method in web
- * workers but in our case it's not exposed even though content
- * scripts may be able to do it synchronously since IO operation
- * takes place in the UI process.
- */
-function importScripts (workerSandbox, ...urls) {
-  let { worker, sandbox } = modelFor(workerSandbox);
-  for (let i in urls) {
-    let contentScriptFile = data.url(urls[i]);
-
-    try {
-      let uri = URL(contentScriptFile);
-      if (uri.scheme === 'resource')
-        load(sandbox, String(uri));
-      else
-        throw Error('Unsupported `contentScriptFile` url: ' + String(uri));
-    }
-    catch(e) {
-      emit(worker, 'error', e);
-    }
-  }
-}
-
-function setListeners (workerSandbox, console) {
-  let { worker } = modelFor(workerSandbox);
-  // console.xxx calls
-  workerSandbox.on('console', function consoleListener (kind, ...args) {
-    console[kind].apply(console, args);
-  });
-
-  // self.postMessage calls
-  workerSandbox.on('message', function postMessage(data) {
-    // destroyed?
-    if (worker)
-      emit(worker, 'message', data);
-  });
-
-  // self.port.emit calls
-  workerSandbox.on('event', function portEmit (...eventArgs) {
-    // If not destroyed, emit event information to worker
-    // `eventArgs` has the event name as first element,
-    // and remaining elements are additional arguments to pass
-    if (worker)
-      emit.apply(null, [worker.port].concat(eventArgs));
-  });
-
-  // unwrap, recreate and propagate async Errors thrown from content-script
-  workerSandbox.on('error', function onError({instanceOfError, value}) {
-    if (worker) {
-      let error = value;
-      if (instanceOfError) {
-        error = new Error(value.message, value.fileName, value.lineNumber);
-        error.stack = value.stack;
-        error.name = value.name;
-      }
-      emit(worker, 'error', error);
-    }
-  });
-}
-
-/**
- * Evaluates code in the sandbox.
- * @param {String} code
- *    JavaScript source to evaluate.
- * @param {String} [filename='javascript:' + code]
- *    Name of the file
- */
-function evaluateIn (workerSandbox, code, filename) {
-  let { worker, sandbox } = modelFor(workerSandbox);
-  try {
-    evaluate(sandbox, code, filename || 'javascript:' + code);
-  }
-  catch(e) {
-    emit(worker, 'error', e);
-  }
-}
-
-/**
- * Method called by the worker sandbox when it needs to send a message
- */
-function onContentEvent (workerSandbox, args) {
-  // As `emit`, we ensure having an asynchronous behavior
-  async(function () {
-    // We emit event to chrome/addon listeners
-    emit.apply(null, [workerSandbox].concat(JSON.parse(args)));
-  });
-}
-
-
-function modelFor (workerSandbox) {
-  return sandboxes.get(workerSandbox);
-}
-
-function getUnsafeWindow (win) {
-  return win.wrappedJSObject || win;
-}
-
-function emitToContent (workerSandbox, args) {
-  return modelFor(workerSandbox).emitToContent(args);
-}
-
-function createChromeAPI (scope) {
-  return Cu.cloneInto({
-    timers: {
-      setTimeout: timer.setTimeout.bind(timer),
-      setInterval: timer.setInterval.bind(timer),
-      clearTimeout: timer.clearTimeout.bind(timer),
-      clearInterval: timer.clearInterval.bind(timer),
-    },
-    sandbox: {
-      evaluate: evaluate,
-    },
-  }, scope, {cloneFunctions: true});
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/sandbox/events.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const events = {};
-exports.events = events;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/tab-events.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* 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 system = require('sdk/system/events');
-const { frames } = require('sdk/remote/child');
-const { WorkerChild } = require('sdk/content/worker-child');
-
-// map observer topics to tab event names
-const EVENTS = {
-  'content-document-global-created': 'create',
-  'chrome-document-global-created': 'create',
-  'content-document-interactive': 'ready',
-  'chrome-document-interactive': 'ready',
-  'content-document-loaded': 'load',
-  'chrome-document-loaded': 'load',
-// 'content-page-shown': 'pageshow', // bug 1024105
-}
-
-function topicListener({ subject, type }) {
-  // NOTE detect the window from the subject:
-  // - on *-global-created the subject is the window
-  // - in the other cases it is the document object
-  let window = subject instanceof Ci.nsIDOMWindow ? subject : subject.defaultView;
-  if (!window){
-    return;
-  }
-  let frame = frames.getFrameForWindow(window);
-  if (frame) {
-    let readyState = frame.content.document.readyState;
-    frame.port.emit('sdk/tab/event', EVENTS[type], { readyState });
-  }
-}
-
-for (let topic in EVENTS)
-  system.on(topic, topicListener, true);
-
-// bug 1024105 - content-page-shown notification doesn't pass persisted param
-function eventListener({target, type, persisted}) {
-  let frame = this;
-  if (target === frame.content.document) {
-    frame.port.emit('sdk/tab/event', type, persisted);
-  }
-}
-frames.addEventListener('pageshow', eventListener, true);
-
-frames.port.on('sdk/tab/attach', (frame, options) => {
-  options.window = frame.content;
-  new WorkerChild(options);
-});
-
-// Forward the existent frames's readyState.
-for (let frame of frames) {
-  let readyState = frame.content.document.readyState;
-  frame.port.emit('sdk/tab/event', 'init', { readyState });
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/worker-child.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/* 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';
-
-lazyRequire(this, '../util/object', 'merge');
-const { Class } = require('../core/heritage');
-lazyRequire(this, '../event/core', 'emit');
-const { EventTarget } = require('../event/target');
-lazyRequire(this, '../window/utils', 'getInnerId');
-lazyRequire(this, '../lang/type', 'instanceOf', 'isObject');
-lazyRequireModule(this, '../system/events', 'system');
-const { when } = require('../system/unload');
-lazyRequire(this, './sandbox', 'WorkerSandbox');
-const { Ci } = require('chrome');
-const { process, frames } = require('../remote/child');
-
-const EVENTS = {
-  'chrome-page-shown': 'pageshow',
-  'content-page-shown': 'pageshow',
-  'chrome-page-hidden': 'pagehide',
-  'content-page-hidden': 'pagehide',
-  'inner-window-destroyed': 'detach',
-}
-
-// The parent Worker must have been created (or an async message sent to spawn
-// its creation) before creating the WorkerChild or messages from the content
-// script to the parent will get lost.
-const WorkerChild = Class({
-  implements: [EventTarget],
-
-  initialize(options) {
-    merge(this, options);
-    keepAlive.set(this.id, this);
-
-    this.windowId = getInnerId(this.window);
-    if (this.contentScriptOptions)
-      this.contentScriptOptions = JSON.parse(this.contentScriptOptions);
-
-    this.port = EventTarget();
-    this.port.on('*', this.send.bind(this, 'event'));
-    this.on('*', this.send.bind(this));
-
-    this.observe = this.observe.bind(this);
-
-    for (let topic in EVENTS)
-      system.on(topic, this.observe);
-
-    this.receive = this.receive.bind(this);
-    process.port.on('sdk/worker/message', this.receive);
-
-    this.sandbox = WorkerSandbox(this, this.window);
-
-    // If the document has an unexpected readyState, its worker-child instance is initialized
-    // as frozen until one of the known readyState is reached.
-    let initialDocumentReadyState = this.window.document.readyState;
-    this.frozen = [
-      "loading", "interactive", "complete"
-    ].includes(initialDocumentReadyState) ? false : true;
-
-    if (this.frozen) {
-      console.warn("SDK worker-child started as frozen on unexpected initial document.readyState", {
-        initialDocumentReadyState, windowLocation: this.window.location.href,
-      });
-    }
-
-    this.frozenMessages = [];
-    this.on('pageshow', () => {
-      this.frozen = false;
-      this.frozenMessages.forEach(args => this.sandbox.emit(...args));
-      this.frozenMessages = [];
-    });
-    this.on('pagehide', () => {
-      this.frozen = true;
-    });
-  },
-
-  // messages
-  receive(process, id, args) {
-    if (id !== this.id)
-      return;
-    args = JSON.parse(args);
-
-    if (this.frozen)
-      this.frozenMessages.push(args);
-    else
-      this.sandbox.emit(...args);
-
-    if (args[0] === 'detach')
-      this.destroy(args[1]);
-  },
-
-  send(...args) {
-    process.port.emit('sdk/worker/event', this.id, JSON.stringify(args, exceptions));
-  },
-
-  // notifications
-  observe({ type, subject }) {
-    if (!this.sandbox)
-      return;
-
-    if (subject.defaultView && getInnerId(subject.defaultView) === this.windowId) {
-      this.sandbox.emitSync(EVENTS[type]);
-      emit(this, EVENTS[type]);
-    }
-
-    if (type === 'inner-window-destroyed' &&
-        subject.QueryInterface(Ci.nsISupportsPRUint64).data === this.windowId) {
-      this.destroy();
-    }
-  },
-
-  get frame() {
-    return frames.getFrameForWindow(this.window.top);
-  },
-
-  // detach/destroy: unload and release the sandbox
-  destroy(reason) {
-    if (!this.sandbox)
-      return;
-
-    for (let topic in EVENTS)
-      system.off(topic, this.observe);
-    process.port.off('sdk/worker/message', this.receive);
-
-    this.sandbox.destroy(reason);
-    this.sandbox = null;
-    keepAlive.delete(this.id);
-
-    this.send('detach');
-  }
-})
-exports.WorkerChild = WorkerChild;
-
-// Error instances JSON poorly
-function exceptions(key, value) {
-  if (!isObject(value) || !instanceOf(value, Error))
-    return value;
-  let _errorType = value.constructor.name;
-  let { message, fileName, lineNumber, stack, name } = value;
-  return { _errorType, message, fileName, lineNumber, stack, name };
-}
-
-// workers for windows in this tab
-var keepAlive = new Map();
-
-process.port.on('sdk/worker/create', (process, options, cpows) => {
-  options.window = cpows.window;
-  let worker = new WorkerChild(options);
-
-  let frame = frames.getFrameForWindow(options.window.top);
-  frame.port.emit('sdk/worker/connect', options.id, options.window.location.href);
-});
-
-when(reason => {
-  for (let worker of keepAlive.values())
-    worker.destroy(reason);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/worker.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-lazyRequire(this, '../event/core', "emit");
-const { omit, merge } = require('../util/object');
-const { Class } = require('../core/heritage');
-const { method } = require('../lang/functional');
-lazyRequire(this, '../window/utils', "getInnerId");
-const { EventTarget } = require('../event/target');
-lazyRequire(this, '../private-browsing/utils', "isPrivate");
-lazyRequire(this, '../tabs/utils', "getTabForBrowser", "getTabForContentWindowNoShim", "getBrowserForTab");
-lazyRequire(this, './utils', "attach", "connect", "detach", "destroy", "makeChildOptions");
-const { ensure } = require('../system/unload');
-lazyRequire(this, '../system/events', {"on": "observe"});
-const { Ci, Cu } = require('chrome');
-lazyRequire(this, 'sdk/model/core', {"modelFor": "tabFor"});
-const { remoteRequire, processes, frames } = require('../remote/parent');
-remoteRequire('sdk/content/worker-child');
-
-const workers = new WeakMap();
-var modelFor = (worker) => workers.get(worker);
-
-const ERR_DESTROYED = "Couldn't find the worker to receive this message. " +
-  "The script may not be initialized yet, or may already have been unloaded.";
-
-// a handle for communication between content script and addon code
-const Worker = Class({
-  implements: [EventTarget],
-
-  initialize(options = {}) {
-    ensure(this, 'detach');
-
-    let model = {
-      attached: false,
-      destroyed: false,
-      earlyEvents: [],        // fired before worker was attached
-      frozen: true,           // document is not yet active
-      options,
-    };
-    workers.set(this, model);
-
-    this.on('detach', this.detach);
-    EventTarget.prototype.initialize.call(this, options);
-
-    this.receive = this.receive.bind(this);
-
-    this.port = EventTarget();
-    this.port.emit = this.send.bind(this, 'event');
-    this.postMessage = this.send.bind(this, 'message');
-
-    if ('window' in options) {
-      let window = options.window;
-      delete options.window;
-      attach(this, window);
-    }
-  },
-
-  // messages
-  receive(process, id, args) {
-    let model = modelFor(this);
-    if (id !== model.id || !model.attached)
-      return;
-    args = JSON.parse(args);
-    if (model.destroyed && args[0] != 'detach')
-      return;
-
-    if (args[0] === 'event')
-      emit(this.port, ...args.slice(1))
-    else
-      emit(this, ...args);
-  },
-
-  send(...args) {
-    let model = modelFor(this);
-    if (model.destroyed && args[0] !== 'detach')
-      throw new Error(ERR_DESTROYED);
-
-    if (!model.attached) {
-      model.earlyEvents.push(args);
-      return;
-    }
-
-    processes.port.emit('sdk/worker/message', model.id, JSON.stringify(args));
-  },
-
-  // properties
-  get url() {
-    let { url } = modelFor(this);
-    return url;
-  },
-
-  get contentURL() {
-    return this.url;
-  },
-
-  get tab() {
-    require('sdk/tabs');
-    let { frame } = modelFor(this);
-    if (!frame)
-      return null;
-    let rawTab = getTabForBrowser(frame.frameElement);
-    return rawTab && tabFor(rawTab);
-  },
-
-  toString: () => '[object Worker]',
-
-  detach: method(detach),
-  destroy: method(destroy),
-})
-exports.Worker = Worker;
-
-attach.define(Worker, function(worker, window) {
-  let model = modelFor(worker);
-  if (model.attached)
-    detach(worker);
-
-  let childOptions = makeChildOptions(model.options);
-  processes.port.emitCPOW('sdk/worker/create', [childOptions], { window });
-
-  let listener = (frame, id, url) => {
-    if (id != childOptions.id)
-      return;
-    frames.port.off('sdk/worker/connect', listener);
-    connect(worker, frame, { id, url });
-  };
-  frames.port.on('sdk/worker/connect', listener);
-});
-
-connect.define(Worker, function(worker, frame, { id, url }) {
-  let model = modelFor(worker);
-  if (model.attached)
-    detach(worker);
-
-  model.id = id;
-  model.frame = frame;
-  model.url = url;
-
-  // Messages from content -> chrome come through the process message manager
-  // since that lives longer than the frame message manager
-  processes.port.on('sdk/worker/event', worker.receive);
-
-  model.attached = true;
-  model.destroyed = false;
-  model.frozen = false;
-
-  model.earlyEvents.forEach(args => worker.send(...args));
-  model.earlyEvents = [];
-  emit(worker, 'attach');
-});
-
-// unload and release the child worker, release window reference
-detach.define(Worker, function(worker) {
-  let model = modelFor(worker);
-  if (!model.attached)
-    return;
-
-  processes.port.off('sdk/worker/event', worker.receive);
-  model.attached = false;
-  model.destroyed = true;
-  emit(worker, 'detach');
-});
-
-isPrivate.define(Worker, ({ tab }) => isPrivate(tab));
-
-// Something in the parent side has destroyed the worker, tell the child to
-// detach, the child will respond when it has detached
-destroy.define(Worker, function(worker, reason) {
-  let model = modelFor(worker);
-  model.destroyed = true;
-  if (!model.attached)
-    return;
-
-  worker.send('detach', reason);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/sync-worker.js
+++ /dev/null
@@ -1,288 +0,0 @@
-/* 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/. */
-
-/**
- *
- * `deprecated/sync-worker` was previously `content/worker`, that was
- * incompatible with e10s. we are in the process of switching to the new
- * asynchronous `Worker`, which behaves slightly differently in some edge
- * cases, so we are keeping this one around for a short period.
- * try to switch to the new one as soon as possible..
- *
- */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Class } = require('../core/heritage');
-const { EventTarget } = require('../event/target');
-const { on, off, emit, setListeners } = require('../event/core');
-const {
-  attach, detach, destroy
-} = require('../content/utils');
-const { method } = require('../lang/functional');
-const { Ci, Cu, Cc } = require('chrome');
-const unload = require('../system/unload');
-const events = require('../system/events');
-const { getInnerId } = require("../window/utils");
-const { WorkerSandbox } = require('../content/sandbox');
-const { isPrivate } = require('../private-browsing/utils');
-
-// A weak map of workers to hold private attributes that
-// should not be exposed
-const workers = new WeakMap();
-
-var modelFor = (worker) => workers.get(worker);
-
-const ERR_DESTROYED =
-  "Couldn't find the worker to receive this message. " +
-  "The script may not be initialized yet, or may already have been unloaded.";
-
-const ERR_FROZEN = "The page is currently hidden and can no longer be used " +
-                   "until it is visible again.";
-
-/**
- * Message-passing facility for communication between code running
- * in the content and add-on process.
- * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker
- */
-const Worker = Class({
-  implements: [EventTarget],
-  initialize: function WorkerConstructor (options) {
-    // Save model in weak map to not expose properties
-    let model = createModel();
-    workers.set(this, model);
-
-    options = options || {};
-
-    if ('contentScriptFile' in options)
-      this.contentScriptFile = options.contentScriptFile;
-    if ('contentScriptOptions' in options)
-      this.contentScriptOptions = options.contentScriptOptions;
-    if ('contentScript' in options)
-      this.contentScript = options.contentScript;
-    if ('injectInDocument' in options)
-      this.injectInDocument = !!options.injectInDocument;
-
-    setListeners(this, options);
-
-    unload.ensure(this, "destroy");
-
-    // Ensure that worker.port is initialized for contentWorker to be able
-    // to send events during worker initialization.
-    this.port = createPort(this);
-
-    model.documentUnload = documentUnload.bind(this);
-    model.pageShow = pageShow.bind(this);
-    model.pageHide = pageHide.bind(this);
-
-    if ('window' in options)
-      attach(this, options.window);
-  },
-
-  /**
-   * Sends a message to the worker's global scope. Method takes single
-   * argument, which represents data to be sent to the worker. The data may
-   * be any primitive type value or `JSON`. Call of this method asynchronously
-   * emits `message` event with data value in the global scope of this
-   * worker.
-   *
-   * `message` event listeners can be set either by calling
-   * `self.on` with a first argument string `"message"` or by
-   * implementing `onMessage` function in the global scope of this worker.
-   * @param {Number|String|JSON} data
-   */
-  postMessage: function (...data) {
-    let model = modelFor(this);
-    let args = ['message'].concat(data);
-    if (!model.inited) {
-      model.earlyEvents.push(args);
-      return;
-    }
-    processMessage.apply(null, [this].concat(args));
-  },
-
-  get url () {
-    let model = modelFor(this);
-    // model.window will be null after detach
-    return model.window ? model.window.document.location.href : null;
-  },
-
-  get contentURL () {
-    let model = modelFor(this);
-    return model.window ? model.window.document.URL : null;
-  },
-
-  // Implemented to provide some of the previous features of exposing sandbox
-  // so that Worker can be extended
-  getSandbox: function () {
-    return modelFor(this).contentWorker;
-  },
-
-  toString: function () { return '[object Worker]'; },
-  attach: method(attach),
-  detach: method(detach),
-  destroy: method(destroy)
-});
-exports.Worker = Worker;
-
-attach.define(Worker, function (worker, window) {
-  let model = modelFor(worker);
-  model.window = window;
-  // Track document unload to destroy this worker.
-  // We can't watch for unload event on page's window object as it
-  // prevents bfcache from working:
-  // https://developer.mozilla.org/En/Working_with_BFCache
-  model.windowID = getInnerId(model.window);
-  events.on("inner-window-destroyed", model.documentUnload);
-
-  // will set model.contentWorker pointing to the private API:
-  model.contentWorker = WorkerSandbox(worker, model.window);
-
-  // Listen to pagehide event in order to freeze the content script
-  // while the document is frozen in bfcache:
-  model.window.addEventListener("pageshow", model.pageShow, true);
-  model.window.addEventListener("pagehide", model.pageHide, true);
-
-  // Mainly enable worker.port.emit to send event to the content worker
-  model.inited = true;
-  model.frozen = false;
-
-  // Fire off `attach` event
-  emit(worker, 'attach', window);
-
-  // Process all events and messages that were fired before the
-  // worker was initialized.
-  model.earlyEvents.forEach(args => processMessage.apply(null, [worker].concat(args)));
-});
-
-/**
- * Remove all internal references to the attached document
- * Tells _port to unload itself and removes all the references from itself.
- */
-detach.define(Worker, function (worker, reason) {
-  let model = modelFor(worker);
-
-  // maybe unloaded before content side is created
-  if (model.contentWorker) {
-    model.contentWorker.destroy(reason);
-  }
-
-  model.contentWorker = null;
-  if (model.window) {
-    model.window.removeEventListener("pageshow", model.pageShow, true);
-    model.window.removeEventListener("pagehide", model.pageHide, true);
-  }
-  model.window = null;
-  // This method may be called multiple times,
-  // avoid dispatching `detach` event more than once
-  if (model.windowID) {
-    model.windowID = null;
-    events.off("inner-window-destroyed", model.documentUnload);
-    model.earlyEvents.length = 0;
-    emit(worker, 'detach');
-  }
-  model.inited = false;
-});
-
-isPrivate.define(Worker, ({ tab }) => isPrivate(tab));
-
-/**
- * Tells content worker to unload itself and
- * removes all the references from itself.
- */
-destroy.define(Worker, function (worker, reason) {
-  detach(worker, reason);
-  modelFor(worker).inited = true;
-  // Specifying no type or listener removes all listeners
-  // from target
-  off(worker);
-  off(worker.port);
-});
-
-/**
- * Events fired by workers
- */
-function documentUnload ({ subject, data }) {
-  let model = modelFor(this);
-  let innerWinID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-  if (innerWinID != model.windowID) return false;
-  detach(this);
-  return true;
-}
-
-function pageShow () {
-  let model = modelFor(this);
-  model.contentWorker.emitSync('pageshow');
-  emit(this, 'pageshow');
-  model.frozen = false;
-}
-
-function pageHide () {
-  let model = modelFor(this);
-  model.contentWorker.emitSync('pagehide');
-  emit(this, 'pagehide');
-  model.frozen = true;
-}
-
-/**
- * Fired from postMessage and emitEventToContent, or from the earlyMessage
- * queue when fired before the content is loaded. Sends arguments to
- * contentWorker if able
- */
-
-function processMessage (worker, ...args) {
-  let model = modelFor(worker) || {};
-  if (!model.contentWorker)
-    throw new Error(ERR_DESTROYED);
-  if (model.frozen)
-    throw new Error(ERR_FROZEN);
-  model.contentWorker.emit.apply(null, args);
-}
-
-function createModel () {
-  return {
-    // List of messages fired before worker is initialized
-    earlyEvents: [],
-    // Is worker connected to the content worker sandbox ?
-    inited: false,
-    // Is worker being frozen? i.e related document is frozen in bfcache.
-    // Content script should not be reachable if frozen.
-    frozen: true,
-    /**
-     * Reference to the content side of the worker.
-     * @type {WorkerGlobalScope}
-     */
-    contentWorker: null,
-    /**
-     * Reference to the window that is accessible from
-     * the content scripts.
-     * @type {Object}
-     */
-    window: null
-  };
-}
-
-function createPort (worker) {
-  let port = EventTarget();
-  port.emit = emitEventToContent.bind(null, worker);
-  return port;
-}
-
-/**
- * Emit a custom event to the content script,
- * i.e. emit this event on `self.port`
- */
-function emitEventToContent (worker, ...eventArgs) {
-  let model = modelFor(worker);
-  let args = ['event'].concat(eventArgs);
-  if (!model.inited) {
-    model.earlyEvents.push(args);
-    return;
-  }
-  processMessage.apply(null, [worker].concat(args));
-}
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test.js
@@ -29,25 +29,23 @@ const findAndRunTests = function findAnd
       stopOnError: options.stopOnError,
       onDone: options.onDone
     });
   });
 };
 exports.findAndRunTests = findAndRunTests;
 
 var runnerWindows = new WeakMap();
-var runnerTabs = new WeakMap();
 
 const TestRunner = function TestRunner(options) {
   options = options || {};
 
   // remember the id's for the open window and tab
   let window = getMostRecentBrowserWindow();
   runnerWindows.set(this, getInnerId(window));
-  runnerTabs.set(this, getTabId(getSelectedTab(window)));
 
   this.fs = options.fs;
   this.console = options.console || console;
   this.passed = 0;
   this.failed = 0;
   this.testRunSummary = [];
   this.expectFailNesting = 0;
   this.done = TestRunner.prototype.done.bind(this);
@@ -325,41 +323,28 @@ TestRunner.prototype = {
     });
 
     PromiseDebugging.flushUncaughtErrors();
     PromiseDebugging.removeUncaughtErrorObserver(this._uncaughtErrorObserver);
 
 
     return all(winPromises).then(() => {
       let browserWins = wins.filter(isBrowser);
-      let tabs = browserWins.reduce((tabs, window) => tabs.concat(getTabs(window)), []);
-      let newTabID = getTabId(getSelectedTab(wins[0]));
-      let oldTabID = runnerTabs.get(this);
-      let hasMoreTabsOpen = browserWins.length && tabs.length != 1;
       let failure = false;
 
       if (wins.length != 1 || getInnerId(wins[0]) !== runnerWindows.get(this)) {
         failure = true;
         this.fail("Should not be any unexpected windows open");
       }
-      else if (hasMoreTabsOpen) {
-        failure = true;
-        this.fail("Should not be any unexpected tabs open");
-      }
-      else if (oldTabID != newTabID) {
-        failure = true;
-        runnerTabs.set(this, newTabID);
-        this.fail("Should not be any new tabs left open, old id: " + oldTabID + " new id: " + newTabID);
-      }
 
       if (failure) {
         console.log("Windows open:");
         for (let win of wins) {
           if (isBrowser(win)) {
-            tabs = getTabs(win);
+            tabs = [];
             console.log(win.location + " - " + tabs.map(getURI).join(", "));
           }
           else {
             console.log(win.location);
           }
         }
       }
 
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/loader/sandbox.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cc, Ci, CC, Cu } = require('chrome');
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const self = require('sdk/self');
-const { getTabId } = require('../tabs/utils');
-const { getInnerId } = require('../window/utils');
-
-/**
- * Make a new sandbox that inherits given `source`'s principals. Source can be
- * URI string, DOMWindow or `null` for system principals.
- */
-function sandbox(target, options) {
-  options = options || {};
-  options.metadata = options.metadata ? options.metadata : {};
-  options.metadata.addonID = options.metadata.addonID ?
-    options.metadata.addonID : self.id;
-
-  let sandbox = Cu.Sandbox(target || systemPrincipal, options);
-  Cu.setSandboxMetadata(sandbox, options.metadata);
-  return sandbox;
-}
-exports.sandbox = sandbox;
-
-/**
- * Evaluates given `source` in a given `sandbox` and returns result.
- */
-function evaluate(sandbox, code, uri, line, version) {
-  return Cu.evalInSandbox(code, sandbox, version || '1.8', uri || '', line || 1);
-}
-exports.evaluate = evaluate;
-
-/**
- * Evaluates code under the given `uri` in the given `sandbox`.
- *
- * @param {String} uri
- *    The URL pointing to the script to load.
- *    It must be a local chrome:, resource:, file: or data: URL.
- */
-function load(sandbox, uri) {
-  if (uri.indexOf('data:') === 0) {
-    let source = uri.substr(uri.indexOf(',') + 1);
-
-    return evaluate(sandbox, decodeURIComponent(source), '1.8', uri, 0);
-  } else {
-    return scriptLoader.loadSubScriptWithOptions(uri, {target: sandbox,
-                                                       charset: 'UTF-8',
-                                                       wantReturnValue: true});
-  }
-}
-exports.load = load;
-
-/**
- * Forces the given `sandbox` to be freed immediately.
- */
-exports.nuke = Cu.nukeSandbox
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/remote/child.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/* 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 { isChildLoader } = require('./core');
-if (!isChildLoader)
-  throw new Error("Cannot load sdk/remote/child in a main process loader.");
-
-const { Ci, Cc, Cu } = require('chrome');
-const runtime = require('../system/runtime');
-const { Class } = require('../core/heritage');
-const { Namespace } = require('../core/namespace');
-const { omit } = require('../util/object');
-const { when } = require('../system/unload');
-const { EventTarget } = require('../event/target');
-const { emit } = require('../event/core');
-const { Disposable } = require('../core/disposable');
-const { EventParent } = require('./utils');
-const { addListItem, removeListItem } = require('../util/list');
-
-const loaderID = require('@loader/options').loaderID;
-
-const MAIN_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-
-const mm = Cc['@mozilla.org/childprocessmessagemanager;1'].
-           getService(Ci.nsISyncMessageSender);
-
-const ns = Namespace();
-
-const process = {
-  port: new EventTarget(),
-  get id() {
-    return runtime.processID;
-  },
-  get isRemote() {
-    return runtime.processType != MAIN_PROCESS;
-  }
-};
-exports.process = process;
-
-function definePort(obj, name) {
-  obj.port.emit = (event, ...args) => {
-    let manager = ns(obj).messageManager;
-    if (!manager)
-      return;
-
-    manager.sendAsyncMessage(name, { loaderID, event, args });
-  };
-}
-
-function messageReceived({ data, objects }) {
-  // Ignore messages from other loaders
-  if (data.loaderID != loaderID)
-    return;
-
-  let keys = Object.keys(objects);
-  if (keys.length) {
-    // If any objects are CPOWs then ignore this message. We don't want child
-    // processes interracting with CPOWs
-    if (!keys.every(name => !Cu.isCrossProcessWrapper(objects[name])))
-      return;
-
-    data.args.push(objects);
-  }
-
-  emit(this.port, data.event, this, ...data.args);
-}
-
-ns(process).messageManager = mm;
-definePort(process, 'sdk/remote/process/message');
-let processMessageReceived = messageReceived.bind(process);
-mm.addMessageListener('sdk/remote/process/message', processMessageReceived);
-
-when(() => {
-  mm.removeMessageListener('sdk/remote/process/message', processMessageReceived);
-  frames = null;
-});
-
-process.port.on('sdk/remote/require', (process, uri) => {
-  require(uri);
-});
-
-function listenerEquals(a, b) {
-  for (let prop of ["type", "callback", "isCapturing"]) {
-    if (a[prop] != b[prop])
-      return false;
-  }
-  return true;
-}
-
-function listenerFor(type, callback, isCapturing = false) {
-  return {
-    type,
-    callback,
-    isCapturing,
-    registeredCallback: undefined,
-    get args() {
-      return [
-        this.type,
-        this.registeredCallback ? this.registeredCallback : this.callback,
-        this.isCapturing
-      ];
-    }
-  };
-}
-
-function removeListenerFromArray(array, listener) {
-  let index = array.findIndex(l => listenerEquals(l, listener));
-  if (index < 0)
-    return;
-  array.splice(index, 1);
-}
-
-function getListenerFromArray(array, listener) {
-  return array.find(l => listenerEquals(l, listener));
-}
-
-function arrayContainsListener(array, listener) {
-  return !!getListenerFromArray(array, listener);
-}
-
-function makeFrameEventListener(frame, callback) {
-  return callback.bind(frame);
-}
-
-var FRAME_ID = 0;
-var tabMap = new Map();
-
-const Frame = Class({
-  implements: [ Disposable ],
-  extends: EventTarget,
-  setup: function(contentFrame) {
-    // This ID should be unique for this loader across all processes
-    let priv = ns(this);
-
-    priv.id = runtime.processID + ":" + FRAME_ID++;
-
-    priv.contentFrame = contentFrame;
-    priv.messageManager = contentFrame;
-    priv.domListeners = [];
-
-    tabMap.set(contentFrame.docShell, this);
-
-    priv.messageReceived = messageReceived.bind(this);
-    priv.messageManager.addMessageListener('sdk/remote/frame/message', priv.messageReceived);
-
-    this.port = new EventTarget();
-    definePort(this, 'sdk/remote/frame/message');
-
-    priv.messageManager.sendAsyncMessage('sdk/remote/frame/attach', {
-      loaderID,
-      frameID: priv.id,
-      processID: runtime.processID
-    });
-
-    frames.attachItem(this);
-  },
-
-  dispose: function() {
-    let priv = ns(this);
-
-    emit(this, 'detach', this);
-
-    for (let listener of priv.domListeners)
-      priv.contentFrame.removeEventListener(...listener.args);
-
-    priv.messageManager.removeMessageListener('sdk/remote/frame/message', priv.messageReceived);
-    tabMap.delete(priv.contentFrame.docShell);
-    priv.contentFrame = null;
-  },
-
-  get content() {
-    return ns(this).contentFrame.content;
-  },
-
-  get isTab() {
-    let docShell = ns(this).contentFrame.docShell;
-    if (process.isRemote) {
-      // We don't want to roundtrip to the main process to get this property.
-      // This hack relies on the host app having defined webBrowserChrome only
-      // in frames that are part of the tabs. Since only Firefox has remote
-      // processes right now and does this this works.
-      let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                             .getInterface(Ci.nsITabChild);
-      return !!tabchild.webBrowserChrome;
-    }
-    else {
-      // This is running in the main process so we can break out to the browser
-      // And check we can find a tab for the browser element directly.
-      let browser = docShell.chromeEventHandler;
-      let tab = require('../tabs/utils').getTabForBrowser(browser);
-      return !!tab;
-    }
-  },
-
-  addEventListener: function(...args) {
-    let priv = ns(this);
-
-    let listener = listenerFor(...args);
-    if (arrayContainsListener(priv.domListeners, listener))
-      return;
-
-    listener.registeredCallback = makeFrameEventListener(this, listener.callback);
-
-    priv.domListeners.push(listener);
-    priv.contentFrame.addEventListener(...listener.args);
-  },
-
-  removeEventListener: function(...args) {
-    let priv = ns(this);
-
-    let listener = getListenerFromArray(priv.domListeners, listenerFor(...args));
-    if (!listener)
-      return;
-
-    removeListenerFromArray(priv.domListeners, listener);
-    priv.contentFrame.removeEventListener(...listener.args);
-  }
-});
-
-const FrameList = Class({
-  implements: [ EventParent, Disposable ],
-  extends: EventTarget,
-  setup: function() {
-    EventParent.prototype.initialize.call(this);
-
-    this.port = new EventTarget();
-    ns(this).domListeners = [];
-
-    this.on('attach', frame => {
-      for (let listener of ns(this).domListeners)
-        frame.addEventListener(...listener.args);
-    });
-  },
-
-  dispose: function() {
-    // The only case where we get destroyed is when the loader is unloaded in
-    // which case each frame will clean up its own event listeners.
-    ns(this).domListeners = null;
-  },
-
-  getFrameForWindow: function(window) {
-    let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDocShell);
-
-    return tabMap.get(docShell) || null;
-  },
-
-  addEventListener: function(...args) {
-    let listener = listenerFor(...args);
-    if (arrayContainsListener(ns(this).domListeners, listener))
-      return;
-
-    ns(this).domListeners.push(listener);
-    for (let frame of this)
-      frame.addEventListener(...listener.args);
-  },
-
-  removeEventListener: function(...args) {
-    let listener = listenerFor(...args);
-    if (!arrayContainsListener(ns(this).domListeners, listener))
-      return;
-
-    removeListenerFromArray(ns(this).domListeners, listener);
-    for (let frame of this)
-      frame.removeEventListener(...listener.args);
-  }
-});
-var frames = exports.frames = new FrameList();
-
-function registerContentFrame(contentFrame) {
-  let frame = new Frame(contentFrame);
-}
-exports.registerContentFrame = registerContentFrame;
-
-function unregisterContentFrame(contentFrame) {
-  let frame = tabMap.get(contentFrame.docShell);
-  if (!frame)
-    return;
-
-  frame.destroy();
-}
-exports.unregisterContentFrame = unregisterContentFrame;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/remote/core.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* 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 options = require("@loader/options");
-
-exports.isChildLoader = options.childLoader;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/remote/parent.js
+++ /dev/null
@@ -1,334 +0,0 @@
-/* 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 { isChildLoader } = require('./core');
-if (isChildLoader)
-  throw new Error("Cannot load sdk/remote/parent in a child loader.");
-
-const { Cu, Ci, Cc } = require('chrome');
-const runtime = require('../system/runtime');
-
-const MAIN_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-
-if (runtime.processType != MAIN_PROCESS) {
-  throw new Error('Cannot use sdk/remote/parent in a child process.');
-}
-
-const { Class } = require('../core/heritage');
-const { Namespace } = require('../core/namespace');
-const { Disposable } = require('../core/disposable');
-const { omit } = require('../util/object');
-const { when } = require('../system/unload');
-const { EventTarget } = require('../event/target');
-const { emit } = require('../event/core');
-const system = require('../system/events');
-const { EventParent } = require('./utils');
-const options = require('@loader/options');
-const loaderModule = require('toolkit/loader');
-
-lazyRequire(this, '../tabs/utils', "getTabForBrowser");
-
-const appInfo = Cc["@mozilla.org/xre/app-info;1"].
-                getService(Ci.nsIXULRuntime);
-
-exports.useRemoteProcesses = appInfo.browserTabsRemoteAutostart;
-
-// Chose the right function for resolving relative a module id
-var moduleResolve;
-if (options.isNative) {
-  moduleResolve = (id, requirer) => loaderModule.nodeResolve(id, requirer, { rootURI: options.rootURI });
-}
-else {
-  moduleResolve = loaderModule.resolve;
-}
-
-// Load the scripts in the child processes
-var { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm');
-var PATH = options.paths[''];
-
-const childOptions = omit(options, ['modules', 'globals', 'resolve', 'load']);
-childOptions.modules = {};
-// @l10n/data is just JSON data and can be safely sent across to the child loader
-try {
-  childOptions.modules["@l10n/data"] = require("@l10n/data");
-}
-catch (e) {
-  // There may be no l10n data
-}
-const loaderID = getNewLoaderID();
-childOptions.loaderID = loaderID;
-childOptions.childLoader = true;
-
-const ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'].
-             getService(Ci.nsIMessageBroadcaster);
-const gmm = Cc['@mozilla.org/globalmessagemanager;1'].
-            getService(Ci.nsIMessageBroadcaster);
-
-const ns = Namespace();
-
-var processMap = new Map();
-
-function definePort(obj, name) {
-  obj.port.emitCPOW = (event, args, cpows = {}) => {
-    let manager = ns(obj).messageManager;
-    if (!manager)
-      return;
-
-    let method = manager instanceof Ci.nsIMessageBroadcaster ?
-                 "broadcastAsyncMessage" : "sendAsyncMessage";
-
-    manager[method](name, { loaderID, event, args }, cpows);
-  };
-
-  obj.port.emit = (event, ...args) => obj.port.emitCPOW(event, args);
-}
-
-function messageReceived({ target, data }) {
-  // Ignore messages from other loaders
-  if (data.loaderID != loaderID)
-    return;
-
-  emit(this.port, data.event, this, ...data.args);
-}
-
-// Process represents a gecko process that can load webpages. Each process
-// contains a number of Frames. This class is used to send and receive messages
-// from a single process.
-const Process = Class({
-  implements: [ Disposable ],
-  extends: EventTarget,
-  setup: function(id, messageManager, isRemote) {
-    ns(this).id = id;
-    ns(this).isRemote = isRemote;
-    ns(this).messageManager = messageManager;
-    ns(this).messageReceived = messageReceived.bind(this);
-    this.destroy = this.destroy.bind(this);
-    ns(this).messageManager.addMessageListener('sdk/remote/process/message', ns(this).messageReceived);
-    ns(this).messageManager.addMessageListener('child-process-shutdown', this.destroy);
-
-    this.port = new EventTarget();
-    definePort(this, 'sdk/remote/process/message');
-
-    // Load any remote modules
-    for (let module of remoteModules.values())
-      this.port.emit('sdk/remote/require', module);
-
-    processMap.set(ns(this).id, this);
-    processes.attachItem(this);
-  },
-
-  dispose: function() {
-    emit(this, 'detach', this);
-    processMap.delete(ns(this).id);
-    ns(this).messageManager.removeMessageListener('sdk/remote/process/message', ns(this).messageReceived);
-    ns(this).messageManager.removeMessageListener('child-process-shutdown', this.destroy);
-    ns(this).messageManager = null;
-  },
-
-  // Returns true if this process is a child process
-  get isRemote() {
-    return ns(this).isRemote;
-  }
-});
-
-// Processes gives an API for enumerating an sending and receiving messages from
-// all processes as well as detecting when a new process starts.
-const Processes = Class({
-  implements: [ EventParent ],
-  extends: EventTarget,
-  initialize: function() {
-    EventParent.prototype.initialize.call(this);
-    ns(this).messageManager = ppmm;
-
-    this.port = new EventTarget();
-    definePort(this, 'sdk/remote/process/message');
-  },
-
-  getById: function(id) {
-    return processMap.get(id);
-  }
-});
-var processes = exports.processes = new Processes();
-
-var frameMap = new Map();
-
-function setFrameProcess(frame, process) {
-  ns(frame).process = process;
-  frames.attachItem(frame);
-}
-
-// Frames display webpages in a process. In the main process every Frame is
-// linked with a <browser> or <iframe> element. 
-const Frame = Class({
-  implements: [ Disposable ],
-  extends: EventTarget,
-  setup: function(id, node) {
-    ns(this).id = id;
-    ns(this).node = node;
-
-    let frameLoader = node.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
-    ns(this).messageManager = frameLoader.messageManager;
-
-    ns(this).messageReceived = messageReceived.bind(this);
-    ns(this).messageManager.addMessageListener('sdk/remote/frame/message', ns(this).messageReceived);
-
-    this.port = new EventTarget();
-    definePort(this, 'sdk/remote/frame/message');
-
-    frameMap.set(ns(this).messageManager, this);
-  },
-
-  dispose: function() {
-    emit(this, 'detach', this);
-    ns(this).messageManager.removeMessageListener('sdk/remote/frame/message', ns(this).messageReceived);
-
-    frameMap.delete(ns(this).messageManager);
-    ns(this).messageManager = null;
-  },
-
-  // Returns the browser or iframe element this frame displays in
-  get frameElement() {
-    return ns(this).node;
-  },
-
-  // Returns the process that this frame loads in
-  get process() {
-    return ns(this).process;
-  },
-
-  // Returns true if this frame is a tab in a main browser window
-  get isTab() {
-    let tab = getTabForBrowser(ns(this).node);
-    return !!tab;
-  }
-});
-
-function managerDisconnected({ subject: manager }) {
-  let frame = frameMap.get(manager);
-  if (frame)
-    frame.destroy();
-}
-system.on('message-manager-disconnect', managerDisconnected);
-
-// Provides an API for enumerating and sending and receiving messages from all
-// Frames
-const FrameList = Class({
-  implements: [ EventParent ],
-  extends: EventTarget,
-  initialize: function() {
-    EventParent.prototype.initialize.call(this);
-    ns(this).messageManager = gmm;
-
-    this.port = new EventTarget();
-    definePort(this, 'sdk/remote/frame/message');
-  },
-
-  // Returns the frame for a browser element
-  getFrameForBrowser: function(browser) {
-    for (let frame of this) {
-      if (frame.frameElement == browser)
-        return frame;
-    }
-    return null;
-  },
-});
-var frames = exports.frames = new FrameList();
-
-// Create the module loader in any existing processes
-ppmm.broadcastAsyncMessage('sdk/remote/process/load', {
-  modulePath: PATH,
-  loaderID,
-  options: childOptions,
-  reason: "broadcast"
-});
-
-// A loader has started in a remote process
-function processLoaderStarted({ target, data }) {
-  if (data.loaderID != loaderID)
-    return;
-
-  if (processMap.has(data.processID)) {
-    console.error("Saw the same process load the same loader twice. This is a bug in the SDK.");
-    return;
-  }
-
-  let process = new Process(data.processID, target, data.isRemote);
-
-  if (pendingFrames.has(data.processID)) {
-    for (let frame of pendingFrames.get(data.processID))
-      setFrameProcess(frame, process);
-    pendingFrames.delete(data.processID);
-  }
-}
-
-// A new process has started
-function processStarted({ target, data: { modulePath } }) {
-  if (modulePath != PATH)
-    return;
-
-  // Have it load a loader if it hasn't already
-  target.sendAsyncMessage('sdk/remote/process/load', {
-    modulePath,
-    loaderID,
-    options: childOptions,
-    reason: "response"
-  });
-}
-
-var pendingFrames = new Map();
-
-// A new frame has been created in the remote process
-function frameAttached({ target, data }) {
-  if (data.loaderID != loaderID)
-    return;
-
-  let frame = new Frame(data.frameID, target);
-
-  let process = processMap.get(data.processID);
-  if (process) {
-    setFrameProcess(frame, process);
-    return;
-  }
-
-  // In some cases frame messages can arrive earlier than process messages
-  // causing us to see a new frame appear before its process. In this case
-  // cache the frame data until we see the process. See bug 1131375.
-  if (!pendingFrames.has(data.processID))
-    pendingFrames.set(data.processID, [frame]);
-  else
-    pendingFrames.get(data.processID).push(frame);
-}
-
-// Wait for new processes and frames
-ppmm.addMessageListener('sdk/remote/process/attach', processLoaderStarted);
-ppmm.addMessageListener('sdk/remote/process/start', processStarted);
-gmm.addMessageListener('sdk/remote/frame/attach', frameAttached);
-
-when(reason => {
-  ppmm.removeMessageListener('sdk/remote/process/attach', processLoaderStarted);
-  ppmm.removeMessageListener('sdk/remote/process/start', processStarted);
-  gmm.removeMessageListener('sdk/remote/frame/attach', frameAttached);
-
-  ppmm.broadcastAsyncMessage('sdk/remote/process/unload', { loaderID, reason });
-});
-
-var remoteModules = new Set();
-
-// Ensures a module is loaded in every child process. It is safe to send 
-// messages to this module immediately after calling this.
-// Pass a module to resolve the id relatively.
-function remoteRequire(id, module = null) {
-  // Resolve relative to calling module if passed
-  if (module)
-    id = moduleResolve(id, module.id);
-
-  // Don't reload the same module
-  if (remoteModules.has(id))
-    return;
-
-  remoteModules.add(id);
-  processes.port.emit('sdk/remote/require', id);
-}
-exports.remoteRequire = remoteRequire;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/remote/utils.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { List, addListItem, removeListItem } = require('../util/list');
-lazyRequire(this, '../event/core', 'emit');
-lazyRequire(this, '../event/utils', 'pipe');
-
-// A helper class that maintains a list of EventTargets. Any events emitted
-// to an EventTarget are also emitted by the EventParent. Likewise for an
-// EventTarget's port property.
-const EventParent = Class({
-  implements: [ List ],
-
-  attachItem: function(item) {
-    addListItem(this, item);
-
-    pipe(item.port, this.port);
-    pipe(item, this);
-
-    item.once('detach', () => {
-      removeListItem(this, item);
-    })
-
-    emit(this, 'attach', item);
-  },
-
-  // Calls listener for every object already in the list and every object
-  // subsequently added to the list.
-  forEvery: function(listener) {
-    for (let item of this)
-      listener(item);
-
-    this.on('attach', listener);
-  }
-});
-exports.EventParent = EventParent;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/selection.js
+++ /dev/null
@@ -1,469 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "stable",
-  "engines": {
-    "Firefox": "*",
-    "SeaMonkey": "*"
-  }
-};
-
-const { Ci, Cc } = require("chrome");
-lazyRequire(this, "./timers", "setTimeout");
-lazyRequire(this, "./event/core", "emit", "off");
-const { Class, obscure } = require("./core/heritage");
-const { EventTarget } = require("./event/target");
-const { ns } = require("./core/namespace");
-const { when: unload } = require("./system/unload");
-lazyRequire(this, './private-browsing/utils', "ignoreWindow");
-lazyRequire(this, './tabs/utils', "getTabs", "getTabForContentWindow", "getAllTabContentWindows");
-lazyRequireModule(this, "./window/utils", "winUtils");
-const events = require("./system/events");
-
-// The selection types
-const HTML = 0x01,
-      TEXT = 0x02,
-      DOM  = 0x03; // internal use only
-
-// A more developer-friendly message than the caught exception when is not
-// possible change a selection.
-const ERR_CANNOT_CHANGE_SELECTION =
-  "It isn't possible to change the selection, as there isn't currently a selection";
-
-const selections = ns();
-
-const Selection = Class({
-  /**
-   * Creates an object from which a selection can be set, get, etc. Each
-   * object has an associated with a range number. Range numbers are the
-   * 0-indexed counter of selection ranges as explained at
-   * https://developer.mozilla.org/en/DOM/Selection.
-   *
-   * @param rangeNumber
-   *        The zero-based range index into the selection
-   */
-  initialize: function initialize(rangeNumber) {
-    // In order to hide the private `rangeNumber` argument from API consumers
-    // while still enabling Selection getters/setters to access it, we define
-    // it as non enumerable, non configurable property. While consumers still
-    // may discover it they won't be able to do any harm which is good enough
-    // in this case.
-    Object.defineProperties(this, {
-      rangeNumber: {
-        enumerable: false,
-        configurable: false,
-        value: rangeNumber
-      }
-    });
-  },
-  get text() { return getSelection(TEXT, this.rangeNumber); },
-  set text(value) { setSelection(TEXT, value, this.rangeNumber); },
-  get html() { return getSelection(HTML, this.rangeNumber); },
-  set html(value) { setSelection(HTML, value, this.rangeNumber); },
-  get isContiguous() {
-
-    // If there are multiple non empty ranges, the selection is definitely
-    // discontiguous. It returns `false` also if there are no valid selection.
-    let count = 0;
-    for (let sel in selectionIterator)
-      if (++count > 1)
-        break;
-
-    return count === 1;
-  }
-});
-
-const selectionListener = {
-  notifySelectionChanged: function (document, selection, reason) {
-    if (!["SELECTALL", "KEYPRESS", "MOUSEUP"].some(type => reason &
-      Ci.nsISelectionListener[type + "_REASON"]) || selection.toString() == "")
-        return;
-
-    this.onSelect();
-  },
-
-  onSelect: function() {
-    emit(module.exports, "select");
-  }
-}
-
-/**
- * Defines iterators so that discontiguous selections can be iterated.
- * Empty selections are skipped - see `safeGetRange` for further details.
- *
- * If discontiguous selections are in a text field, only the first one
- * is returned because the text field selection APIs doesn't support
- * multiple selections.
- */
-function* forOfIterator() {
-  let selection = getSelection(DOM);
-  let count = 0;
-
-  if (selection)
-    count = selection.rangeCount || (getElementWithSelection() ? 1 : 0);
-
-  for (let i = 0; i < count; i++) {
-    let sel = Selection(i);
-
-    if (sel.text)
-      yield Selection(i);
-  }
-}
-
-const selectionIteratorOptions = {
-  __iterator__: function() {
-      for (let item of this)
-          yield item;
-  }
-}
-selectionIteratorOptions[Symbol.iterator] = forOfIterator;
-const selectionIterator = obscure(selectionIteratorOptions);
-
-/**
- * Returns the most recent focused window.
- * if private browsing window is most recent and not supported,
- * then ignore it and return `null`, because the focused window
- * can't be targeted.
- */
-function getFocusedWindow() {
-  let window = winUtils.getFocusedWindow();
-
-  return ignoreWindow(window) ? null : window;
-}
-
-/**
- * Returns the focused element in the most recent focused window
- * if private browsing window is most recent and not supported,
- * then ignore it and return `null`, because the focused element
- * can't be targeted.
- */
-function getFocusedElement() {
-  let element = winUtils.getFocusedElement();
-
-  if (!element || ignoreWindow(element.ownerGlobal))
-    return null;
-
-  return element;
-}
-
-/**
- * Returns the current selection from most recent content window. Depending on
- * the specified |type|, the value returned can be a string of text, stringified
- * HTML, or a DOM selection object as described at
- * https://developer.mozilla.org/en/DOM/Selection.
- *
- * @param type
- *        Specifies the return type of the selection. Valid values are the one
- *        of the constants HTML, TEXT, or DOM.
- *
- * @param rangeNumber
- *        Specifies the zero-based range index of the returned selection.
- */
-function getSelection(type, rangeNumber) {
-  let window, selection;
-  try {
-    window = getFocusedWindow();
-    selection = window.getSelection();
-  }
-  catch (e) {
-    return null;
-  }
-
-  // Get the selected content as the specified type
-  if (type == DOM) {
-    return selection;
-  }
-  else if (type == TEXT) {
-    let range = safeGetRange(selection, rangeNumber);
-
-    if (range)
-      return range.toString();
-
-    let node = getElementWithSelection();
-
-    if (!node)
-      return null;
-
-    return node.value.substring(node.selectionStart, node.selectionEnd);
-  }
-  else if (type == HTML) {
-    let range = safeGetRange(selection, rangeNumber);
-    // Another way, but this includes the xmlns attribute for all elements in
-    // Gecko 1.9.2+ :
-    // return Cc["@mozilla.org/xmlextras/xmlserializer;1"].
-    //   createInstance(Ci.nsIDOMSerializer).serializeToSTring(range.
-    //     cloneContents());
-    if (!range)
-      return null;
-
-    let node = window.document.createElement("span");
-    node.appendChild(range.cloneContents());
-    return node.innerHTML;
-  }
-
-  throw new Error("Type " + type + " is unrecognized.");
-}
-
-/**
- * Sets the current selection of the most recent content document by changing
- * the existing selected text/HTML range to the specified value.
- *
- * @param val
- *        The value for the new selection
- *
- * @param rangeNumber
- *        The zero-based range index of the selection to be set
- *
- */
-function setSelection(type, val, rangeNumber) {
-  // Make sure we have a window context & that there is a current selection.
-  // Selection cannot be set unless there is an existing selection.
-  let window, selection;
-
-  try {
-    window = getFocusedWindow();
-    selection = window.getSelection();
-  }
-  catch (e) {
-    throw new Error(ERR_CANNOT_CHANGE_SELECTION);
-  }
-
-  let range = safeGetRange(selection, rangeNumber);
-
-  if (range) {
-    let fragment;
-
-    if (type === HTML)
-      fragment = range.createContextualFragment(val);
-    else {
-      fragment = range.createContextualFragment("");
-      fragment.textContent = val;
-    }
-
-    range.deleteContents();
-    range.insertNode(fragment);
-  }
-  else {
-    let node = getElementWithSelection();
-
-    if (!node)
-      throw new Error(ERR_CANNOT_CHANGE_SELECTION);
-
-    let { value, selectionStart, selectionEnd } = node;
-
-    let newSelectionEnd = selectionStart + val.length;
-
-    node.value = value.substring(0, selectionStart) +
-                  val +
-                  value.substring(selectionEnd, value.length);
-
-    node.setSelectionRange(selectionStart, newSelectionEnd);
-  }
-}
-
-/**
- * Returns the specified range in a selection without throwing an exception.
- *
- * @param selection
- *        A selection object as described at
- *         https://developer.mozilla.org/en/DOM/Selection
- *
- * @param [rangeNumber]
- *        Specifies the zero-based range index of the returned selection.
- *        If it's not provided the function will return the first non empty
- *        range, if any.
- */
-function safeGetRange(selection, rangeNumber) {
-  try {
-    let { rangeCount } = selection;
-    let range = null;
-
-    if (typeof rangeNumber === "undefined")
-      rangeNumber = 0;
-    else
-      rangeCount = rangeNumber + 1;
-
-    for (; rangeNumber < rangeCount; rangeNumber++ ) {
-      range = selection.getRangeAt(rangeNumber);
-
-      if (range && range.toString())
-        break;
-
-      range = null;
-    }
-
-    return range;
-  }
-  catch (e) {
-    return null;
-  }
-}
-
-/**
- * Returns a reference of the DOM's active element for the window given, if it
- * supports the text field selection API and has a text selected.
- *
- * Note:
- *   we need this method because window.getSelection doesn't return a selection
- *   for text selected in a form field (see bug 85686)
- */
-function getElementWithSelection() {
-  let element = getFocusedElement();
-
-  if (!element)
-    return null;
-
-  try {
-    // Accessing selectionStart and selectionEnd on e.g. a button
-    // results in an exception thrown as per the HTML5 spec.  See
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#textFieldSelection
-
-    let { value, selectionStart, selectionEnd } = element;
-
-    let hasSelection = typeof value === "string" &&
-                      !isNaN(selectionStart) &&
-                      !isNaN(selectionEnd) &&
-                      selectionStart !== selectionEnd;
-
-    return hasSelection ? element : null;
-  }
-  catch (err) {
-    return null;
-  }
-
-}
-
-/**
- * Adds the Selection Listener to the content's window given
- */
-function addSelectionListener(window) {
-  let selection = window.getSelection();
-
-  // Don't add the selection's listener more than once to the same window,
-  // if the selection object is the same
-  if ("selection" in selections(window) && selections(window).selection === selection)
-    return;
-
-  // We ensure that the current selection is an instance of
-  // `nsISelectionPrivate` before working on it, in case is `null`.
-  //
-  // If it's `null` it's likely too early to add the listener, and we demand
-  // that operation to `document-shown` - it can easily happens for frames
-  if (selection instanceof Ci.nsISelectionPrivate)
-    selection.addSelectionListener(selectionListener);
-
-  // nsISelectionListener implementation seems not fire a notification if
-  // a selection is in a text field, therefore we need to add a listener to
-  // window.onselect, that is fired only for text fields.
-  // For consistency, we add it only when the nsISelectionListener is added.
-  //
-  // https://developer.mozilla.org/en/DOM/window.onselect
-  window.addEventListener("select", selectionListener.onSelect, true);
-
-  selections(window).selection = selection;
-};
-
-/**
- * Removes the Selection Listener to the content's window given
- */
-function removeSelectionListener(window) {
-  // Don't remove the selection's listener to a window that wasn't handled.
-  if (!("selection" in selections(window)))
-    return;
-
-  let selection = window.getSelection();
-  let isSameSelection = selection === selections(window).selection;
-
-  // Before remove the listener, we ensure that the current selection is an
-  // instance of `nsISelectionPrivate` (it could be `null`), and that is still
-  // the selection we managed for this window (it could be detached).
-  if (selection instanceof Ci.nsISelectionPrivate && isSameSelection)
-    selection.removeSelectionListener(selectionListener);
-
-  window.removeEventListener("select", selectionListener.onSelect, true);
-
-  delete selections(window).selection;
-};
-
-function onContent(event) {
-  let window = event.subject.defaultView;
-
-  // We are not interested in documents without valid defaultView (e.g. XML)
-  // that aren't in a tab (e.g. Panel); or in private windows
-   if (window && getTabForContentWindow(window) && !ignoreWindow(window)) {
-    addSelectionListener(window);
-  }
-}
-
-// Adds Selection listener to new documents
-// Note that strong reference is needed for documents that are loading slowly or
-// where the server didn't close the connection (e.g. "comet").
-events.on("document-element-inserted", onContent, true);
-
-// Adds Selection listeners to existing documents
-getAllTabContentWindows().forEach(addSelectionListener);
-
-// When a document is not visible anymore the selection object is detached, and
-// a new selection object is created when it becomes visible again.
-// That makes the previous selection's listeners added previously totally
-// useless – the listeners are not notified anymore.
-// To fix that we're listening for `document-shown` event in order to add
-// the listeners to the new selection object created.
-//
-// See bug 665386 for further details.
-
-function onShown(event) {
-  let window = event.subject.defaultView;
-
-  // We are not interested in documents without valid defaultView.
-  // For example XML documents don't have windows and we don't yet support them.
-  if (!window)
-    return;
-
-  // We want to handle only the windows where we added selection's listeners
-  if ("selection" in selections(window)) {
-    let currentSelection = window.getSelection();
-    let { selection } = selections(window);
-
-    // If the current selection for the window given is different from the one
-    // stored in the namespace, we need to add the listeners again, and replace
-    // the previous selection in our list with the new one.
-    //
-    // Notice that we don't have to remove the listeners from the old selection,
-    // because is detached. An attempt to remove the listener, will raise an
-    // error (see http://mxr.mozilla.org/mozilla-central/source/layout/generic/nsSelection.cpp#5343 )
-    //
-    // We ensure that the current selection is an instance of
-    // `nsISelectionPrivate` before working on it, in case is `null`.
-    if (currentSelection instanceof Ci.nsISelectionPrivate &&
-      currentSelection !== selection) {
-
-      window.addEventListener("select", selectionListener.onSelect, true);
-      currentSelection.addSelectionListener(selectionListener);
-      selections(window).selection = currentSelection;
-    }
-  }
-}
-
-events.on("document-shown", onShown, true);
-
-// Removes Selection listeners when the add-on is unloaded
-unload(function(){
-  getAllTabContentWindows().forEach(removeSelectionListener);
-
-  events.off("document-element-inserted", onContent);
-  events.off("document-shown", onShown);
-
-  off(exports);
-});
-
-const selection = Class({
-  extends: EventTarget,
-  implements: [ Selection, selectionIterator ]
-})();
-
-module.exports = selection;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tab/events.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* 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";
-
-// This module provides temporary shim until Bug 843901 is shipped.
-// It basically registers tab event listeners on all windows that get
-// opened and forwards them through observer notifications.
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Ci } = require("chrome");
-const { windows, isInteractive } = require("../window/utils");
-const { events } = require("../browser/events");
-const { open } = require("../event/dom");
-const { filter, map, merge, expand } = require("../event/utils");
-const isFennec = require("sdk/system/xul-app").is("Fennec");
-
-// Module provides event stream (in nodejs style) that emits data events
-// for all the tab events that happen in running firefox. At the moment
-// it does it by registering listeners on all browser windows and then
-// forwarding events when they occur to a stream. This will become obsolete
-// once Bug 843901 is fixed, and we'll just leverage observer notifications.
-
-// Set of tab events that this module going to aggregate and expose.
-const TYPES = ["TabOpen","TabClose","TabSelect","TabMove","TabPinned",
-               "TabUnpinned"];
-
-// Utility function that given a browser `window` returns stream of above
-// defined tab events for all tabs on the given window.
-function tabEventsFor(window) {
-  // Map supported event types to a streams of those events on the given
-  // `window` and than merge these streams into single form stream off
-  // all events.
-  let channels = TYPES.map(type => open(window, type));
-  return merge(channels);
-}
-
-// Create our event channels.  We do this in a separate function to
-// minimize the chance of leaking intermediate objects on the global.
-function makeEvents() {
-  // Filter DOMContentLoaded events from all the browser events.
-  var readyEvents = filter(events, e => e.type === "DOMContentLoaded");
-  // Map DOMContentLoaded events to it's target browser windows.
-  var futureWindows = map(readyEvents, e => e.target);
-  // Expand all browsers that will become interactive to supported tab events
-  // on these windows. Result will be a tab events from all tabs of all windows
-  // that will become interactive.
-  var eventsFromFuture = expand(futureWindows, tabEventsFor);
-
-  // Above covers only windows that will become interactive in a future, but some
-  // windows may already be interactive so we pick those and expand to supported
-  // tab events for them too.
-  var interactiveWindows = windows("navigator:browser", { includePrivate: true }).
-                           filter(isInteractive);
-  var eventsFromInteractive = merge(interactiveWindows.map(tabEventsFor));
-
-
-  // Finally merge stream of tab events from future windows and current windows
-  // to cover all tab events on all windows that will open.
-  return merge([eventsFromInteractive, eventsFromFuture]);
-}
-
-// Map events to Fennec format if necessary
-exports.events = map(makeEvents(), function (event) {
-  return !isFennec ? event : {
-    type: event.type,
-    target: event.target.ownerGlobal.BrowserApp
-            .getTabForBrowser(event.target)
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-if (require("./system/xul-app").is("Fennec")) {
-  module.exports = require("./windows/tabs-fennec").tabs;
-}
-else {
-  module.exports = require("./tabs/tabs-firefox");
-}
-
-const tabs = module.exports;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/common.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 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 { validateOptions } = require("../deprecated/api-utils");
-const { data } = require("../self");
-
-function Options(options) {
-  if ('string' === typeof options)
-    options = { url: options };
-
-  return validateOptions(options, {
-    url: {
-      is: ["string"],
-      map: (v) => v ? data.url(v) : v
-    },
-    inBackground: {
-      map: Boolean,
-      is: ["undefined", "boolean"]
-    },
-    isPinned: { is: ["undefined", "boolean"] },
-    isPrivate: { is: ["undefined", "boolean"] },
-    inNewWindow: { is: ["undefined", "boolean"] },
-    onOpen: { is: ["undefined", "function"] },
-    onClose: { is: ["undefined", "function"] },
-    onReady: { is: ["undefined", "function"] },
-    onLoad: { is: ["undefined", "function"] },
-    onPageShow: { is: ["undefined", "function"] },
-    onActivate: { is: ["undefined", "function"] },
-    onDeactivate: { is: ["undefined", "function"] }
-  });
-}
-exports.Options = Options;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/events.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const ON_PREFIX = "on";
-const TAB_PREFIX = "Tab";
-
-const EVENTS = {
-  ready: "DOMContentLoaded",
-  load: "load", // Used for non-HTML content
-  pageshow: "pageshow", // Used for cached content
-  open: "TabOpen",
-  close: "TabClose",
-  activate: "TabSelect",
-  deactivate: null,
-  pinned: "TabPinned",
-  unpinned: "TabUnpinned"
-}
-exports.EVENTS = EVENTS;
-
-Object.keys(EVENTS).forEach(function(name) {
-  EVENTS[name] = {
-    name: name,
-    listener: createListenerName(name),
-    dom: EVENTS[name]
-  }
-});
-
-function createListenerName (name) {
-  if (name === 'pageshow')
-    return 'onPageShow';
-  else
-    return ON_PREFIX + name.charAt(0).toUpperCase() + name.substr(1);
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/helpers.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-
-// NOTE: This file should only export Tab instances
-
-
-lazyRequire(this, './utils', { "getTabForBrowser": "getRawTabForBrowser" });
-const { modelFor } = require('../model/core');
-
-exports.getTabForRawTab = modelFor;
-
-function getTabForBrowser(browser) {
-  return modelFor(getRawTabForBrowser(browser)) || null;
-}
-exports.getTabForBrowser = getTabForBrowser;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/namespace.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* 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 { ns } = require('../core/namespace');
-
-exports.tabsNS = ns();
-exports.tabNS = ns();
-exports.rawTabNS = ns();
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/observer.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/* 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';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { EventTarget } = require("../event/target");
-const { emit } = require("../event/core");
-const { DOMEventAssembler } = require("../deprecated/events/assembler");
-const { Class } = require("../core/heritage");
-const { getActiveTab, getTabs } = require("./utils");
-const { browserWindowIterator } = require("../deprecated/window-utils");
-const { isBrowser, windows, getMostRecentBrowserWindow } = require("../window/utils");
-const { observer: windowObserver } = require("../windows/observer");
-const { when } = require("../system/unload");
-
-const EVENTS = {
-  "TabOpen": "open",
-  "TabClose": "close",
-  "TabSelect": "select",
-  "TabMove": "move",
-  "TabPinned": "pinned",
-  "TabUnpinned": "unpinned"
-};
-
-const selectedTab = Symbol("observer/state/selectedTab");
-
-// Event emitter objects used to register listeners and emit events on them
-// when they occur.
-const Observer = Class({
-  implements: [EventTarget, DOMEventAssembler],
-  initialize() {
-    this[selectedTab] = null;
-    // Currently Gecko does not dispatch any event on the previously selected
-    // tab before / after "TabSelect" is dispatched. In order to work around this
-    // limitation we keep track of selected tab and emit "deactivate" event with
-    // that before emitting "activate" on selected tab.
-    this.on("select", tab => {
-      const selected = this[selectedTab];
-      if (selected !== tab) {
-        if (selected) {
-          emit(this, 'deactivate', selected);
-        }
-
-        if (tab) {
-          this[selectedTab] = tab;
-          emit(this, 'activate', this[selectedTab]);
-        }
-      }
-    });
-
-
-    // We also observe opening / closing windows in order to add / remove it's
-    // containers to the observed list.
-    windowObserver.on("open", chromeWindow => {
-      if (isBrowser(chromeWindow)) {
-        this.observe(chromeWindow);
-      }
-    });
-
-    windowObserver.on("close", chromeWindow => {
-      if (isBrowser(chromeWindow)) {
-        // Bug 751546: Emit `deactivate` event on window close immediatly
-        // Otherwise we are going to face "dead object" exception on `select` event
-        if (getActiveTab(chromeWindow) === this[selectedTab]) {
-          emit(this, "deactivate", this[selectedTab]);
-          this[selectedTab] = null;
-        }
-        this.ignore(chromeWindow);
-      }
-    });
-
-
-    // Currently gecko does not dispatches "TabSelect" events when different
-    // window gets activated. To work around this limitation we emulate "select"
-    // event for this case.
-    windowObserver.on("activate", chromeWindow => {
-      if (isBrowser(chromeWindow)) {
-        emit(this, "select", getActiveTab(chromeWindow));
-      }
-    });
-
-    // We should synchronize state, since probably we already have at least one
-    // window open.
-    for (let chromeWindow of browserWindowIterator()) {
-      this.observe(chromeWindow);
-    }
-
-    when(_ => {
-      // Don't dispatch a deactivate event during unload.
-      this[selectedTab] = null;
-    });
-  },
-  /**
-   * Events that are supported and emitted by the module.
-   */
-  supportedEventsTypes: Object.keys(EVENTS),
-  /**
-   * Function handles all the supported events on all the windows that are
-   * observed. Method is used to proxy events to the listeners registered on
-   * this event emitter.
-   * @param {Event} event
-   *    Keyboard event being emitted.
-   */
-  handleEvent: function handleEvent(event) {
-    emit(this, EVENTS[event.type], event.target, event);
-  }
-});
-
-exports.observer = new Observer();
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/tab-fennec.js
+++ /dev/null
@@ -1,249 +0,0 @@
-/* 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 { Cc, Ci } = require('chrome');
-const { Class } = require('../core/heritage');
-const { tabNS, rawTabNS } = require('./namespace');
-const { EventTarget } = require('../event/target');
-const { activateTab, getTabTitle, setTabTitle, closeTab, getTabURL,
-        getTabContentWindow, getTabForBrowser, setTabURL, getOwnerWindow,
-        getTabContentDocument, getTabContentType, getTabId, isTab } = require('./utils');
-const { emit } = require('../event/core');
-const { isPrivate } = require('../private-browsing/utils');
-const { isWindowPrivate } = require('../window/utils');
-const { when: unload } = require('../system/unload');
-const { BLANK } = require('../content/thumbnail');
-const { viewFor } = require('../view/core');
-const { EVENTS } = require('./events');
-const { modelFor } = require('../model/core');
-
-const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec';
-
-const Tab = Class({
-  extends: EventTarget,
-  initialize: function initialize(options) {
-    options = options.tab ? options : { tab: options };
-    let tab = options.tab;
-
-    EventTarget.prototype.initialize.call(this, options);
-    let tabInternals = tabNS(this);
-    rawTabNS(tab).tab = this;
-
-    let window = tabInternals.window = options.window || getOwnerWindow(tab);
-    tabInternals.tab = tab;
-
-    // TabReady
-    let onReady = tabInternals.onReady = onTabReady.bind(this);
-    tab.browser.addEventListener(EVENTS.ready.dom, onReady);
-
-    // TabPageShow
-    let onPageShow = tabInternals.onPageShow = onTabPageShow.bind(this);
-    tab.browser.addEventListener(EVENTS.pageshow.dom, onPageShow);
-
-    // TabLoad
-    let onLoad = tabInternals.onLoad = onTabLoad.bind(this);
-    tab.browser.addEventListener(EVENTS.load.dom, onLoad, true);
-
-    // TabClose
-    let onClose = tabInternals.onClose = onTabClose.bind(this);
-    window.BrowserApp.deck.addEventListener(EVENTS.close.dom, onClose);
-
-    unload(cleanupTab.bind(null, this));
-  },
-
-  /**
-   * The title of the page currently loaded in the tab.
-   * Changing this property changes an actual title.
-   * @type {String}
-   */
-  get title() {
-    return getTabTitle(tabNS(this).tab);
-  },
-  set title(title) {
-    setTabTitle(tabNS(this).tab, title);
-  },
-
-  /**
-   * Location of the page currently loaded in this tab.
-   * Changing this property will loads page under under the specified location.
-   * @type {String}
-   */
-  get url() {
-    return tabNS(this).closed ? undefined : getTabURL(tabNS(this).tab);
-  },
-  set url(url) {
-    setTabURL(tabNS(this).tab, url);
-  },
-
-  getThumbnail: function() {
-    // TODO: implement!
-    console.error(ERR_FENNEC_MSG);
-
-    // return 80x45 blank default
-    return BLANK;
-  },
-
-  /**
-   * tab's document readyState, or 'uninitialized' if it doesn't even exist yet.
-   */
-  get readyState() {
-    let doc = getTabContentDocument(tabNS(this).tab);
-    return doc && doc.readyState || 'uninitialized';
-  },
-
-  get id() {
-    return getTabId(tabNS(this).tab);
-  },
-
-  /**
-   * The index of the tab relative to other tabs in the application window.
-   * Changing this property will change order of the actual position of the tab.
-   * @type {Number}
-   */
-  get index() {
-    if (tabNS(this).closed) return undefined;
-
-    let tabs = tabNS(this).window.BrowserApp.tabs;
-    let tab = tabNS(this).tab;
-    for (var i = tabs.length; i >= 0; i--) {
-      if (tabs[i] === tab)
-        return i;
-    }
-    return null;
-  },
-  set index(value) {
-    console.error(ERR_FENNEC_MSG); // TODO
-  },
-
-  /**
-   * Whether or not tab is pinned (Is an app-tab).
-   * @type {Boolean}
-   */
-  get isPinned() {
-    console.error(ERR_FENNEC_MSG); // TODO
-    return false; // TODO
-  },
-  pin: function pin() {
-    console.error(ERR_FENNEC_MSG); // TODO
-  },
-  unpin: function unpin() {
-    console.error(ERR_FENNEC_MSG); // TODO
-  },
-
-  /**
-   * Returns the MIME type that the document loaded in the tab is being
-   * rendered as.
-   * @type {String}
-   */
-  get contentType() {
-    return getTabContentType(tabNS(this).tab);
-  },
-
-  /**
-   * Create a worker for this tab, first argument is options given to Worker.
-   * @type {Worker}
-   */
-  attach: function attach(options) {
-    // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
-    // TODO: fix this circular dependency
-    let { Worker } = require('./worker');
-    return Worker(options, getTabContentWindow(tabNS(this).tab));
-  },
-
-  /**
-   * Make this tab active.
-   */
-  activate: function activate() {
-    activateTab(tabNS(this).tab, tabNS(this).window);
-  },
-
-  /**
-   * Close the tab
-   */
-  close: function close(callback) {
-    let tab = this;
-    this.once(EVENTS.close.name, function () {
-      tabNS(tab).closed = true;
-      if (callback) callback();
-    });
-
-    closeTab(tabNS(this).tab);
-  },
-
-  /**
-   * Reload the tab
-   */
-  reload: function reload() {
-    tabNS(this).tab.browser.reload();
-  }
-});
-exports.Tab = Tab;
-
-// Implement `viewFor` polymorphic function for the Tab
-// instances.
-viewFor.define(Tab, x => tabNS(x).tab);
-
-function cleanupTab(tab) {
-  let tabInternals = tabNS(tab);
-  if (!tabInternals.tab)
-    return;
-
-  if (tabInternals.tab.browser) {
-    tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady);
-    tabInternals.tab.browser.removeEventListener(EVENTS.pageshow.dom, tabInternals.onPageShow);
-    tabInternals.tab.browser.removeEventListener(EVENTS.load.dom, tabInternals.onLoad, true);
-  }
-  tabInternals.onReady = null;
-  tabInternals.onPageShow = null;
-  tabInternals.onLoad = null;
-  tabInternals.window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, tabInternals.onClose);
-  tabInternals.onClose = null;
-  rawTabNS(tabInternals.tab).tab = null;
-  tabInternals.tab = null;
-  tabInternals.window = null;
-}
-
-function onTabReady(event) {
-  let win = event.target.defaultView;
-
-  // ignore frames
-  if (win === win.top) {
-    emit(this, 'ready', this);
-  }
-}
-
-function onTabLoad (event) {
-  let win = event.target.defaultView;
-
-  // ignore frames
-  if (win === win.top) {
-    emit(this, 'load', this);
-  }
-}
-
-function onTabPageShow(event) {
-  let win = event.target.defaultView;
-  if (win === win.top)
-    emit(this, 'pageshow', this, event.persisted);
-}
-
-// TabClose
-function onTabClose(event) {
-  let rawTab = getTabForBrowser(event.target);
-  if (tabNS(this).tab !== rawTab)
-    return;
-
-  emit(this, EVENTS.close.name, this);
-  cleanupTab(this);
-};
-
-isPrivate.implement(Tab, tab => {
-  return isWindowPrivate(getTabContentWindow(tabNS(tab).tab));
-});
-
-// Implement `modelFor` function for the Tab instances.
-modelFor.when(isTab, rawTab => {
-  return rawTabNS(rawTab).tab;
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
+++ /dev/null
@@ -1,353 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { observer } = require('./observer');
-const { observer: windowObserver } = require('../windows/observer');
-const { addListItem, removeListItem } = require('../util/list');
-const { viewFor } = require('../view/core');
-const { modelFor } = require('../model/core');
-const { emit, setListeners } = require('../event/core');
-const { EventTarget } = require('../event/target');
-const { getBrowserForTab, setTabURL, getTabId, getTabURL, getTabForBrowser,
-        getTabs, getTabTitle, setTabTitle, getIndex, closeTab, reload, move,
-        activateTab, pin, unpin, isTab } = require('./utils');
-const { isBrowser, getInnerId, isWindowPrivate } = require('../window/utils');
-const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
-const { when } = require('../system/unload');
-const { ignoreWindow, isPrivate } = require('../private-browsing/utils')
-const { defer } = require('../lang/functional');
-const { getURL } = require('../url/utils');
-const { frames, remoteRequire } = require('../remote/parent');
-remoteRequire('sdk/content/tab-events');
-
-const modelsFor = new WeakMap();
-const viewsFor = new WeakMap();
-const destroyed = new WeakMap();
-
-const tabEvents = {};
-exports.tabEvents = tabEvents;
-
-function browser(tab) {
-  return getBrowserForTab(viewsFor.get(tab));
-}
-
-function isDestroyed(tab) {
-  return destroyed.has(tab);
-}
-
-function isClosed(tab) {
-  if (!viewsFor.has(tab))
-    return true;
-  return viewsFor.get(tab).closing;
-}
-
-// private tab attribute where the remote cached value is stored
-const remoteReadyStateCached = Symbol("remoteReadyStateCached");
-
-const Tab = Class({
-  implements: [EventTarget],
-  initialize: function(tabElement, options = null) {
-    modelsFor.set(tabElement, this);
-    viewsFor.set(this, tabElement);
-
-    if (options) {
-      EventTarget.prototype.initialize.call(this, options);
-
-      if (options.isPinned)
-        this.pin();
-
-      // Note that activate is defered and so will run after any open event
-      // is sent out
-      if (!options.inBackground)
-        this.activate();
-    }
-
-    getURL.implement(this, tab => tab.url);
-    isPrivate.implement(this, tab => {
-      return isWindowPrivate(viewsFor.get(tab).ownerGlobal);
-    });
-  },
-
-  get id() {
-    return isDestroyed(this) ? undefined : getTabId(viewsFor.get(this));
-  },
-
-  get title() {
-    return isDestroyed(this) ? undefined : getTabTitle(viewsFor.get(this));
-  },
-
-  set title(val) {
-    if (isDestroyed(this))
-      return;
-
-    setTabTitle(viewsFor.get(this), val);
-  },
-
-  get url() {
-    return isDestroyed(this) ? undefined : getTabURL(viewsFor.get(this));
-  },
-
-  set url(val) {
-    if (isDestroyed(this))
-      return;
-
-    setTabURL(viewsFor.get(this), val);
-  },
-
-  get contentType() {
-    return isDestroyed(this) ? undefined : browser(this).documentContentType;
-  },
-
-  get index() {
-    return isDestroyed(this) ? undefined : getIndex(viewsFor.get(this));
-  },
-
-  set index(val) {
-    if (isDestroyed(this))
-      return;
-
-    move(viewsFor.get(this), val);
-  },
-
-  get isPinned() {
-    return isDestroyed(this) ? undefined : viewsFor.get(this).pinned;
-  },
-
-  get window() {
-    if (isClosed(this))
-      return undefined;
-
-    // TODO: Remove the dependency on the windows module, see bug 792670
-    require('../windows');
-    let tabElement = viewsFor.get(this);
-    let domWindow = tabElement.ownerGlobal;
-    return modelFor(domWindow);
-  },
-
-  get readyState() {
-    return isDestroyed(this) ? undefined : this[remoteReadyStateCached] || "uninitialized";
-  },
-
-  pin: function() {
-    if (isDestroyed(this))
-      return;
-
-    pin(viewsFor.get(this));
-  },
-
-  unpin: function() {
-    if (isDestroyed(this))
-      return;
-
-    unpin(viewsFor.get(this));
-  },
-
-  close: function(callback) {
-    let tabElement = viewsFor.get(this);
-
-    if (isDestroyed(this) || !tabElement || !tabElement.parentNode) {
-      if (callback)
-        callback();
-      return;
-    }
-
-    this.once('close', () => {
-      this.destroy();
-      if (callback)
-        callback();
-    });
-
-    closeTab(tabElement);
-  },
-
-  reload: function() {
-    if (isDestroyed(this))
-      return;
-
-    reload(viewsFor.get(this));
-  },
-
-  activate: defer(function() {
-    if (isDestroyed(this))
-      return;
-
-    activateTab(viewsFor.get(this));
-  }),
-
-  getThumbnail: function() {
-    if (isDestroyed(this))
-      return BLANK;
-
-    // TODO: This is unimplemented in e10s: bug 1148601
-    if (browser(this).isRemoteBrowser) {
-      console.error('This method is not supported with E10S');
-      return BLANK;
-    }
-    return getThumbnailURIForWindow(browser(this).contentWindow);
-  },
-
-  attach: function(options) {
-    if (isDestroyed(this))
-      return;
-
-    let { Worker } = require('../content/worker');
-    let { connect, makeChildOptions } = require('../content/utils');
-
-    let worker = Worker(options);
-    worker.once("detach", () => {
-      worker.destroy();
-    });
-
-    let attach = frame => {
-      let childOptions = makeChildOptions(options);
-      frame.port.emit("sdk/tab/attach", childOptions);
-      connect(worker, frame, { id: childOptions.id, url: this.url });
-    };
-
-    // Do this synchronously if possible
-    let frame = frames.getFrameForBrowser(browser(this));
-    if (frame) {
-      attach(frame);
-    }
-    else {
-      let listener = (frame) => {
-        if (frame.frameElement != browser(this))
-          return;
-
-        frames.off("attach", listener);
-        attach(frame);
-      };
-      frames.on("attach", listener);
-    }
-
-    return worker;
-  },
-
-  destroy: function() {
-    if (isDestroyed(this))
-      return;
-
-    destroyed.set(this, true);
-  }
-});
-exports.Tab = Tab;
-
-viewFor.define(Tab, tab => viewsFor.get(tab));
-
-// Returns the high-level window for this DOM window if the windows module has
-// ever been loaded otherwise returns null
-function maybeWindowFor(domWindow) {
-  try {
-    return modelFor(domWindow);
-  }
-  catch (e) {
-    return null;
-  }
-}
-
-function tabEmit(tab, event, ...args) {
-  // Don't emit events for destroyed tabs
-  if (isDestroyed(tab))
-    return;
-
-  // If the windows module was never loaded this will return null. We don't need
-  // to emit to the window.tabs object in this case as nothing can be listening.
-  let tabElement = viewsFor.get(tab);
-  let window = maybeWindowFor(tabElement.ownerGlobal);
-  if (window)
-    emit(window.tabs, event, tab, ...args);
-
-  emit(tabEvents, event, tab, ...args);
-  emit(tab, event, tab, ...args);
-}
-
-function windowClosed(domWindow) {
-  if (!isBrowser(domWindow))
-    return;
-
-  for (let tabElement of getTabs(domWindow)) {
-    tabEventListener("close", tabElement);
-  }
-}
-windowObserver.on('close', windowClosed);
-
-// Don't want to send close events after unloaded
-when(_ => {
-  windowObserver.off('close', windowClosed);
-});
-
-// Listen for tabbrowser events
-function tabEventListener(event, tabElement, ...args) {
-  let domWindow = tabElement.ownerGlobal;
-
-  if (ignoreWindow(domWindow))
-    return;
-
-  // Don't send events for tabs that are already closing
-  if (event != "close" && (tabElement.closing || !tabElement.parentNode))
-    return;
-
-  let tab = modelsFor.get(tabElement);
-  if (!tab)
-    tab = new Tab(tabElement);
-
-  let window = maybeWindowFor(domWindow);
-
-  if (event == "open") {
-    // Note, add to the window tabs first because if this is the first access to
-    // window.tabs it will be prefilling itself with everything from tabs
-    if (window)
-      addListItem(window.tabs, tab);
-    // The tabs module will take care of adding to its internal list
-  }
-  else if (event == "close") {
-    if (window)
-      removeListItem(window.tabs, tab);
-    // The tabs module will take care of removing from its internal list
-  }
-  else if (event == "init" || event == "create" || event == "ready" || event == "load") {
-    // Ignore load events from before browser windows have fully loaded, these
-    // are for about:blank in the initial tab
-    if (isBrowser(domWindow) && !domWindow.gBrowserInit.delayedStartupFinished)
-      return;
-
-    // update the cached remote readyState value
-    let { readyState } = args[0] || {};
-    tab[remoteReadyStateCached] = readyState;
-  }
-
-  if (event == "init") {
-    // Do not emit events for the detected existent tabs, we only need to cache
-    // their current document.readyState value.
-    return;
-  }
-
-  tabEmit(tab, event, ...args);
-
-  // The tab object shouldn't be reachable after closed
-  if (event == "close") {
-    viewsFor.delete(tab);
-    modelsFor.delete(tabElement);
-  }
-}
-observer.on('*', tabEventListener);
-
-// Listen for tab events from content
-frames.port.on('sdk/tab/event', (frame, event, ...args) => {
-  if (!frame.isTab)
-    return;
-
-  let tabElement = getTabForBrowser(frame.frameElement);
-  if (!tabElement)
-    return;
-
-  tabEventListener(event, tabElement, ...args);
-});
-
-// Implement `modelFor` function for the Tab instances..
-modelFor.when(isTab, view => {
-  return modelsFor.get(view);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/tab.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-const { getTargetWindow } = require("../content/mod");
-lazyRequire(this, "./utils", "getTabContentWindow", "isTab");
-lazyRequire(this, "../view/core", "viewFor");
-
-if (require('../system/xul-app').name == 'Fennec') {
-  module.exports = require('./tab-fennec');
-}
-else {
-  module.exports = require('./tab-firefox');
-}
-
-getTargetWindow.when(isTab, tab => getTabContentWindow(tab));
-
-getTargetWindow.when(x => x instanceof module.exports.Tab,
-  tab => getTabContentWindow(viewFor(tab)));
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
+++ /dev/null
@@ -1,133 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { Tab, tabEvents } = require('./tab');
-const { EventTarget } = require('../event/target');
-lazyRequire(this, '../event/core', "emit", "setListeners");
-const { pipe } = require('../event/utils');
-const { observer: windowObserver } = require('../windows/observer');
-const { List, addListItem, removeListItem } = require('../util/list');
-lazyRequire(this, '../model/core', "modelFor");
-lazyRequire(this, '../view/core', "viewFor");
-lazyRequire(this, './utils', "getTabs", "getSelectedTab");
-lazyRequire(this, '../window/utils', "getMostRecentBrowserWindow", "isBrowser");
-lazyRequire(this, './common', "Options");
-lazyRequire(this, '../private-browsing', "isPrivate");
-lazyRequire(this, '../private-browsing/utils', "ignoreWindow", "isWindowPBSupported")
-const { isPrivateBrowsingSupported } = require('sdk/self');
-
-const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
-
-const Tabs = Class({
-  implements: [EventTarget],
-  extends: List,
-  initialize: function() {
-    List.prototype.initialize.call(this);
-
-    // We must do the list manipulation here where the object is extensible
-    this.on("open", tab => {
-      addListItem(this, tab);
-    });
-
-    this.on("close", tab => {
-      removeListItem(this, tab);
-    });
-  },
-
-  get activeTab() {
-    let activeDomWin = getMostRecentBrowserWindow();
-    if (!activeDomWin)
-      return null;
-    return modelFor(getSelectedTab(activeDomWin));
-  },
-
-  open: function(options) {
-    options = Options(options);
-
-    // TODO: Remove the dependency on the windows module: bug 792670
-    let windows = require('../windows').browserWindows;
-    let activeWindow = windows.activeWindow;
-
-    let privateState = supportPrivateTabs && options.isPrivate;
-    // When no isPrivate option was passed use the private state of the active
-    // window
-    if (activeWindow && privateState === undefined)
-      privateState = isPrivate(activeWindow);
-
-    function getWindow(privateState) {
-      for (let window of windows) {
-        if (privateState === isPrivate(window)) {
-          return window;
-        }
-      }
-      return null;
-    }
-
-    function openNewWindowWithTab() {
-      windows.open({
-        url: options.url,
-        isPrivate: privateState,
-        onOpen: function(newWindow) {
-          let tab = newWindow.tabs[0];
-          setListeners(tab, options);
-
-          if (options.isPinned)
-            tab.pin();
-
-          // We don't emit the open event for the first tab in a new window so
-          // do it now the listeners are attached
-          emit(tab, "open", tab);
-        }
-      });
-    }
-
-    if (options.inNewWindow)
-      return openNewWindowWithTab();
-
-    // if the active window is in the state that we need then use it
-    if (activeWindow && (privateState === isPrivate(activeWindow)))
-      return activeWindow.tabs.open(options);
-
-    // find a window in the state that we need
-    let window = getWindow(privateState);
-    if (window)
-      return window.tabs.open(options);
-
-    return openNewWindowWithTab();
-  }
-});
-
-const allTabs = new Tabs();
-module.exports = allTabs;
-pipe(tabEvents, allTabs);
-
-function addWindowTab(window, tabElement) {
-  let tab = new Tab(tabElement);
-  if (window)
-    addListItem(window.tabs, tab);
-  addListItem(allTabs, tab);
-  emit(allTabs, "open", tab);
-}
-
-// Find tabs in already open windows
-for (let tabElement of getTabs())
-  addWindowTab(null, tabElement);
-
-// Detect tabs in new windows
-windowObserver.on('open', domWindow => {
-  if (!isBrowser(domWindow) || ignoreWindow(domWindow))
-    return;
-
-  let window = null;
-  try {
-    modelFor(domWindow);
-  }
-  catch (e) { }
-
-  for (let tabElement of getTabs(domWindow)) {
-    addWindowTab(window, tabElement);
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ /dev/null
@@ -1,370 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-
-// NOTE: This file should only deal with xul/native tabs
-
-
-const { Ci, Cu } = require('chrome');
-lazyRequire(this, "../lang/functional", "defer");
-lazyRequire(this, '../window/utils', "windows", "isBrowser");
-lazyRequire(this, '../self', "isPrivateBrowsingSupported");
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-
-// Bug 834961: ignore private windows when they are not supported
-function getWindows() {
-  return windows(null, { includePrivate: isPrivateBrowsingSupported });
-}
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-// Define predicate functions that can be used to detech weather
-// we deal with fennec tabs or firefox tabs.
-
-// Predicate to detect whether tab is XUL "Tab" node.
-const isXULTab = tab =>
-  tab instanceof Ci.nsIDOMNode &&
-  tab.nodeName === "tab" &&
-  tab.namespaceURI === XUL_NS;
-exports.isXULTab = isXULTab;
-
-// Predicate to detecet whether given tab is a fettec tab.
-// Unfortunately we have to guess via duck typinng of:
-// http://mxr.mozilla.org/mozilla-central/source/mobile/android/chrome/content/browser.js#2583
-const isFennecTab = tab =>
-  tab &&
-  tab.QueryInterface &&
-  Ci.nsIBrowserTab &&
-  tab.QueryInterface(Ci.nsIBrowserTab) === tab;
-exports.isFennecTab = isFennecTab;
-
-const isTab = x => isXULTab(x) || isFennecTab(x);
-exports.isTab = isTab;
-
-function activateTab(tab, window) {
-  let gBrowser = getTabBrowserForTab(tab);
-
-  // normal case
-  if (gBrowser) {
-    gBrowser.selectedTab = tab;
-  }
-  // fennec ?
-  else if (window && window.BrowserApp) {
-    window.BrowserApp.selectTab(tab);
-  }
-  return null;
-}
-exports.activateTab = activateTab;
-
-function getTabBrowser(window) {
-  // bug 1009938 - may be null in SeaMonkey
-  return window.gBrowser || window.getBrowser();
-}
-exports.getTabBrowser = getTabBrowser;
-
-function getTabContainer(window) {
-  return getTabBrowser(window).tabContainer;
-}
-exports.getTabContainer = getTabContainer;
-
-/**
- * Returns the tabs for the `window` if given, or the tabs
- * across all the browser's windows otherwise.
- *
- * @param {nsIWindow} [window]
- *    A reference to a window
- *
- * @returns {Array} an array of Tab objects
- */
-function getTabs(window) {
-  if (arguments.length === 0) {
-    return getWindows().
-               filter(isBrowser).
-               reduce((tabs, window) => tabs.concat(getTabs(window)), []);
-  }
-
-  // fennec
-  if (window.BrowserApp)
-    return window.BrowserApp.tabs;
-
-  // firefox - default
-  return Array.filter(getTabContainer(window).children, t => !t.closing);
-}
-exports.getTabs = getTabs;
-
-function getActiveTab(window) {
-  return getSelectedTab(window);
-}
-exports.getActiveTab = getActiveTab;
-
-function getOwnerWindow(tab) {
-  // normal case
-  if (tab.ownerDocument)
-    return tab.ownerGlobal;
-
-  // try fennec case
-  return getWindowHoldingTab(tab);
-}
-exports.getOwnerWindow = getOwnerWindow;
-
-// fennec
-function getWindowHoldingTab(rawTab) {
-  for (let window of getWindows()) {
-    // this function may be called when not using fennec,
-    // but BrowserApp is only defined on Fennec
-    if (!window.BrowserApp)
-      continue;
-
-    for (let tab of window.BrowserApp.tabs) {
-      if (tab === rawTab)
-        return window;
-    }
-  }
-
-  return null;
-}
-
-function openTab(window, url, options) {
-  options = options || {};
-
-  // fennec?
-  if (window.BrowserApp) {
-    return window.BrowserApp.addTab(url, {
-      selected: options.inBackground ? false : true,
-      pinned: options.isPinned || false,
-      isPrivate: options.isPrivate || false,
-      parentId: window.BrowserApp.selectedTab.id
-    });
-  }
-
-  // firefox
-  let newTab = window.gBrowser.addTab(url);
-  if (!options.inBackground) {
-    activateTab(newTab);
-  }
-  return newTab;
-};
-exports.openTab = openTab;
-
-function isTabOpen(tab) {
-  // try normal case then fennec case
-  return !!((tab.linkedBrowser) || getWindowHoldingTab(tab));
-}
-exports.isTabOpen = isTabOpen;
-
-function closeTab(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // normal case?
-  if (gBrowser) {
-    // Bug 699450: the tab may already have been detached
-    if (!tab.parentNode)
-      return;
-    return gBrowser.removeTab(tab);
-  }
-
-  let window = getWindowHoldingTab(tab);
-  // fennec?
-  if (window && window.BrowserApp) {
-    // Bug 699450: the tab may already have been detached
-    if (!tab.browser)
-      return;
-    return window.BrowserApp.closeTab(tab);
-  }
-  return null;
-}
-exports.closeTab = closeTab;
-
-function getURI(tab) {
-  if (tab.browser) // fennec
-    return tab.browser.currentURI.spec;
-  return tab.linkedBrowser.currentURI.spec;
-}
-exports.getURI = getURI;
-
-function getTabBrowserForTab(tab) {
-  let outerWin = getOwnerWindow(tab);
-  if (outerWin)
-    return getOwnerWindow(tab).gBrowser;
-  return null;
-}
-exports.getTabBrowserForTab = getTabBrowserForTab;
-
-function getBrowserForTab(tab) {
-  if (tab.browser) // fennec
-    return tab.browser;
-
-  return tab.linkedBrowser;
-}
-exports.getBrowserForTab = getBrowserForTab;
-
-function getTabId(tab) {
-  if (tab.browser) // fennec
-    return tab.id
-
-  return String(tab.linkedPanel).split('panel').pop();
-}
-exports.getTabId = getTabId;
-
-function getTabForId(id) {
-  return getTabs().find(tab => getTabId(tab) === id) || null;
-}
-exports.getTabForId = getTabForId;
-
-function getTabTitle(tab) {
-  return getBrowserForTab(tab).contentTitle || tab.label || "";
-}
-exports.getTabTitle = getTabTitle;
-
-function setTabTitle(tab, title) {
-  title = String(title);
-  if (tab.browser) {
-    // Fennec
-    tab.browser.contentDocument.title = title;
-  }
-  else {
-    let browser = getBrowserForTab(tab);
-    // Note that we aren't actually setting the document title in e10s, just
-    // the title the browser thinks the content has
-    if (browser.isRemoteBrowser)
-      browser._contentTitle = title;
-    else
-      browser.contentDocument.title = title;
-  }
-  tab.label = String(title);
-}
-exports.setTabTitle = setTabTitle;
-
-function getTabContentDocument(tab) {
-  return getBrowserForTab(tab).contentDocument;
-}
-exports.getTabContentDocument = getTabContentDocument;
-
-function getTabContentWindow(tab) {
-  return getBrowserForTab(tab).contentWindow;
-}
-exports.getTabContentWindow = getTabContentWindow;
-
-/**
- * Returns all tabs' content windows across all the browsers' windows
- */
-function getAllTabContentWindows() {
-  return getTabs().map(getTabContentWindow);
-}
-exports.getAllTabContentWindows = getAllTabContentWindows;
-
-// gets the tab containing the provided window
-function getTabForContentWindow(window) {
-  return getTabs().find(tab => getTabContentWindow(tab) === window.top) || null;
-}
-exports.getTabForContentWindow = getTabForContentWindow;
-
-// only sdk/selection.js is relying on shims
-function getTabForContentWindowNoShim(window) {
-  function getTabContentWindowNoShim(tab) {
-    let browser = getBrowserForTab(tab);
-    return ShimWaiver.getProperty(browser, "contentWindow");
-  }
-  return getTabs().find(tab => getTabContentWindowNoShim(tab) === window.top) || null;
-}
-exports.getTabForContentWindowNoShim = getTabForContentWindowNoShim;
-
-function getTabURL(tab) {
-  return String(getBrowserForTab(tab).currentURI.spec);
-}
-exports.getTabURL = getTabURL;
-
-function setTabURL(tab, url) {
-  let browser = getBrowserForTab(tab);
-  browser.loadURI(String(url));
-}
-// "TabOpen" event is fired when it's still "about:blank" is loaded in the
-// changing `location` property of the `contentDocument` has no effect since
-// seems to be either ignored or overridden by internal listener, there for
-// location change is enqueued for the next turn of event loop.
-exports.setTabURL = defer(setTabURL);
-
-function getTabContentType(tab) {
-  return getBrowserForTab(tab).contentDocument.contentType;
-}
-exports.getTabContentType = getTabContentType;
-
-function getSelectedTab(window) {
-  if (window.BrowserApp) // fennec?
-    return window.BrowserApp.selectedTab;
-  if (window.gBrowser)
-    return window.gBrowser.selectedTab;
-  return null;
-}
-exports.getSelectedTab = getSelectedTab;
-
-
-function getTabForBrowser(browser) {
-  for (let window of getWindows()) {
-    // this function may be called when not using fennec
-    if (!window.BrowserApp)
-      continue;
-
-    for  (let tab of window.BrowserApp.tabs) {
-      if (tab.browser === browser)
-        return tab;
-    }
-  }
-
-  let tabbrowser = browser.getTabBrowser && browser.getTabBrowser()
-  return !!tabbrowser && tabbrowser.getTabForBrowser(browser);
-}
-exports.getTabForBrowser = getTabForBrowser;
-
-function pin(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // TODO: Implement Fennec support
-  if (gBrowser) gBrowser.pinTab(tab);
-}
-exports.pin = pin;
-
-function unpin(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // TODO: Implement Fennec support
-  if (gBrowser) gBrowser.unpinTab(tab);
-}
-exports.unpin = unpin;
-
-function isPinned(tab) {
-  return !!tab.pinned;
-}
-exports.isPinned = isPinned;
-
-function reload(tab) {
-  getBrowserForTab(tab).reload();
-}
-exports.reload = reload
-
-function getIndex(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // Firefox
-  if (gBrowser) {
-    return tab._tPos;
-  }
-  // Fennec
-  else {
-    let window = getWindowHoldingTab(tab)
-    let tabs = window.BrowserApp.tabs;
-    for (let i = tabs.length; i >= 0; i--)
-      if (tabs[i] === tab) return i;
-  }
-}
-exports.getIndex = getIndex;
-
-function move(tab, index) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // Firefox
-  if (gBrowser) gBrowser.moveTabTo(tab, index);
-  // TODO: Implement fennec support
-}
-exports.move = move;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/worker.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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 ContentWorker = require('../content/worker').Worker;
-
-function Worker(options, window) {
-  options.window = window;
-
-  let worker = ContentWorker(options);
-  worker.once("detach", function detach() {
-    worker.destroy();
-  });
-  return worker;
-}
-exports.Worker = Worker;
\ No newline at end of file
--- a/addon-sdk/source/lib/sdk/test/utils.js
+++ b/addon-sdk/source/lib/sdk/test/utils.js
@@ -178,22 +178,15 @@ function waitUntil (predicate, delay) {
   }, delay || 10);
   return promise;
 }
 exports.waitUntil = waitUntil;
 
 var cleanUI = function cleanUI() {
   let { promise, resolve } = defer();
 
-  let windows = getWindows(null, { includePrivate: true });
-  if (windows.length > 1) {
-    return closeWindow(windows[1]).then(cleanUI);
-  }
-
-  getTabs(windows[0]).slice(1).forEach(closeTab);
-
   resolve();
 
   return promise;
 }
 exports.cleanUI = cleanUI;
 
 exports.isTravisCI = ("TRAVIS" in env && "CI" in env);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/window/browser.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { windowNS } = require('./namespace');
-const { on, off, once } = require('../event/core');
-const { method } = require('../lang/functional');
-const { getWindowTitle } = require('./utils');
-const unload = require('../system/unload');
-const { EventTarget } = require('../event/target');
-const { isPrivate } = require('../private-browsing/utils');
-const { isWindowPrivate, isFocused } = require('../window/utils');
-const { viewFor } = require('../view/core');
-
-const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
-
-const BrowserWindow = Class({
-  initialize: function initialize(options) {
-    EventTarget.prototype.initialize.call(this, options);
-    windowNS(this).window = options.window;
-  },
-  activate: function activate() {
-    // TODO
-    return null;
-  },
-  close: function() {
-    throw new Error(ERR_FENNEC_MSG);
-    return null;
-  },
-  get title() {
-    return getWindowTitle(windowNS(this).window);
-  },
-  // NOTE: Fennec only has one window, which is assumed below
-  // TODO: remove assumption below
-  // NOTE: tabs requires windows
-  get tabs() {
-    return require('../tabs');
-  },
-  get activeTab() {
-    return require('../tabs').activeTab;
-  },
-  on: method(on),
-  removeListener: method(off),
-  once: method(once)
-});
-exports.BrowserWindow = BrowserWindow;
-
-const getWindowView = window => windowNS(window).window;
-
-viewFor.define(BrowserWindow, getWindowView);
-isPrivate.define(BrowserWindow, (window) => isWindowPrivate(viewFor(window).window));
-isFocused.define(BrowserWindow, (window) => isFocused(viewFor(window).window));
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/window/events.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Ci, Cu } = require("chrome");
-const { observe } = require("../event/chrome");
-const { open } = require("../event/dom");
-const { windows } = require("../window/utils");
-const { filter, merge, map, expand } = require("../event/utils");
-
-function documentMatches(weakWindow, event) {
-  let window = weakWindow.get();
-  return window && event.target === window.document;
-}
-
-function makeStrictDocumentFilter(window) {
-  // Note: Do not define a closure within this function.  Otherwise
-  //       you may leak the window argument.
-  let weak = Cu.getWeakReference(window);
-  return documentMatches.bind(null, weak);
-}
-
-function toEventWithDefaultViewTarget({type, target}) {
-  return { type: type, target: target.defaultView }
-}
-
-// Function registers single shot event listeners for relevant window events
-// that forward events to exported event stream.
-function eventsFor(window) {
-  // NOTE: Do no use pass a closure from this function into a stream
-  //       transform function.  You will capture the window in the
-  //       closure and leak the window until the event stream is
-  //       completely closed.
-  let interactive = open(window, "DOMContentLoaded", { capture: true });
-  let complete = open(window, "load", { capture: true });
-  let states = merge([interactive, complete]);
-  let changes = filter(states, makeStrictDocumentFilter(window));
-  return map(changes, toEventWithDefaultViewTarget);
-}
-
-// Create our event channels.  We do this in a separate function to
-// minimize the chance of leaking intermediate objects on the global.
-function makeEvents() {
-  // In addition to observing windows that are open we also observe windows
-  // that are already already opened in case they're in process of loading.
-  var opened = windows(null, { includePrivate: true });
-  var currentEvents = merge(opened.map(eventsFor));
-
-  // Register system event listeners for top level window open / close.
-  function rename({type, target, data}) {
-    return { type: rename[type], target: target, data: data }
-  }
-  rename.domwindowopened = "open";
-  rename.domwindowclosed = "close";
-
-  var openEvents = map(observe("domwindowopened"), rename);
-  var closeEvents = map(observe("domwindowclosed"), rename);
-  var futureEvents = expand(openEvents, ({target}) => eventsFor(target));
-
-  return merge([currentEvents, futureEvents, openEvents, closeEvents]);
-}
-
-exports.events = makeEvents();
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/window/helpers.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 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 { defer, all } = require('../core/promise');
-const events = require('../system/events');
-const { open: openWindow, onFocus, getToplevelWindow,
-        isInteractive, isStartupFinished, getOuterId } = require('./utils');
-const { Ci } = require("chrome");
-
-function open(uri, options) {
-  return promise(openWindow.apply(null, arguments), 'load').then(focus);
-}
-exports.open = open;
-
-function close(window) {
-  let deferred = defer();
-  let toplevelWindow = getToplevelWindow(window);
-  let outerId = getOuterId(toplevelWindow);
-  events.on("outer-window-destroyed", function onclose({subject}) {
-    let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    if (id == outerId) {
-      events.off("outer-window-destroyed", onclose);
-      deferred.resolve();
-    }
-  }, true);
-  window.close();
-  return deferred.promise;
-}
-exports.close = close;
-
-function focus(window) {
-  let p = onFocus(window);
-  window.focus();
-  return p;
-}
-exports.focus = focus;
-
-function ready(window) {
-  let { promise: result, resolve } = defer();
-
-  if (isInteractive(window))
-    resolve(window);
-  else
-    resolve(promise(window, 'DOMContentLoaded'));
-
-  return result;
-}
-exports.ready = ready;
-
-function startup(window) {
-  let { promise: result, resolve } = defer();
-
-  if (isStartupFinished(window)) {
-    resolve(window);
-  } else {
-    events.on("browser-delayed-startup-finished", function listener({subject}) {
-      if (subject === window) {
-        events.off("browser-delayed-startup-finished", listener);
-        resolve(window);
-      }
-    });
-  }
-
-  return result;
-}
-exports.startup = startup;
-
-function promise(target, evt, capture) {
-  let deferred = defer();
-  capture = !!capture;
-
-  target.addEventListener(evt, function() {
-    deferred.resolve(target);
-  }, {capture, once: true});
-
-  return deferred.promise;
-}
-exports.promise = promise;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/window/namespace.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* 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";
-
-exports.windowNS = require('../core/namespace').ns();
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'stable'
-};
-
-const { isBrowser } = require('./window/utils');
-const { modelFor } = require('./model/core');
-const { viewFor } = require('./view/core');
-
-
-if (require('./system/xul-app').is('Fennec')) {
-  module.exports = require('./windows/fennec');
-}
-else {
-  module.exports = require('./windows/firefox');
-}
-
-
-const browsers = module.exports.browserWindows;
-
-//
-modelFor.when(isBrowser, view => {
-  for (let model of browsers) {
-    if (viewFor(model) === view)
-      return model;
-  }
-  return null;
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows/fennec.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { BrowserWindow } = require('../window/browser');
-const { WindowTracker } = require('../deprecated/window-utils');
-const { isBrowser, getMostRecentBrowserWindow } = require('../window/utils');
-const { windowNS } = require('../window/namespace');
-const { on, off, once, emit } = require('../event/core');
-const { method } = require('../lang/functional');
-const { EventTarget } = require('../event/target');
-const { List, addListItem } = require('../util/list');
-
-const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
-
-// NOTE: On Fennec there is only one window.
-
-var BrowserWindows = Class({
-  implements: [ List ],
-  extends: EventTarget,
-  initialize: function() {
-    List.prototype.initialize.apply(this);
-  },
-  get activeWindow() {
-    let window = getMostRecentBrowserWindow();
-    return window ? getBrowserWindow({window: window}) : null;
-  },
-  open: function open(options) {
-    throw new Error(ERR_FENNEC_MSG);
-    return null;
-  }
-});
-const browserWindows = exports.browserWindows = BrowserWindows();
-
-
-/**
- * Gets a `BrowserWindow` for the given `chromeWindow` if previously
- * registered, `null` otherwise.
- */
-function getRegisteredWindow(chromeWindow) {
-  for (let window of browserWindows) {
-    if (chromeWindow === windowNS(window).window)
-      return window;
-  }
-
-  return null;
-}
-
-/**
- * Gets a `BrowserWindow` for the provided window options obj
- * @params {Object} options
- *    Options that are passed to the the `BrowserWindow`
- * @returns {BrowserWindow}
- */
-function getBrowserWindow(options) {
-  let window = null;
-
-  // if we have a BrowserWindow already then use it
-  if ('window' in options)
-    window = getRegisteredWindow(options.window);
-  if (window)
-    return window;
-
-  // we don't have a BrowserWindow yet, so create one
-  window = BrowserWindow(options);
-  addListItem(browserWindows, window);
-  return window;
-}
-
-WindowTracker({
-  onTrack: function onTrack(chromeWindow) {
-    if (!isBrowser(chromeWindow)) return;
-    let window = getBrowserWindow({ window: chromeWindow });
-    emit(browserWindows, 'open', window);
-  },
-  onUntrack: function onUntrack(chromeWindow) {
-    if (!isBrowser(chromeWindow)) return;
-    let window = getBrowserWindow({ window: chromeWindow });
-    emit(browserWindows, 'close', window);
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows/firefox.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { observer } = require('./observer');
-const { isBrowser, getMostRecentBrowserWindow, windows, open, getInnerId,
-        getWindowTitle, getToplevelWindow, isFocused, isWindowPrivate } = require('../window/utils');
-const { List, addListItem, removeListItem } = require('../util/list');
-const { viewFor } = require('../view/core');
-const { modelFor } = require('../model/core');
-const { emit, emitOnObject, setListeners } = require('../event/core');
-const { once } = require('../dom/events');
-const { EventTarget } = require('../event/target');
-const { getSelectedTab } = require('../tabs/utils');
-const { Cc, Ci } = require('chrome');
-const { Options } = require('../tabs/common');
-const system = require('../system/events');
-const { ignoreWindow, isPrivate, isWindowPBSupported } = require('../private-browsing/utils');
-const { data, isPrivateBrowsingSupported } = require('../self');
-const { setImmediate } = require('../timers');
-
-const supportPrivateWindows = isPrivateBrowsingSupported && isWindowPBSupported;
-
-const modelsFor = new WeakMap();
-const viewsFor = new WeakMap();
-
-const Window = Class({
-  implements: [EventTarget],
-  initialize: function(domWindow) {
-    modelsFor.set(domWindow, this);
-    viewsFor.set(this, domWindow);
-  },
-
-  get title() {
-    return getWindowTitle(viewsFor.get(this));
-  },
-
-  activate: function() {
-    viewsFor.get(this).focus();
-  },
-
-  close: function(callback) {
-    let domWindow = viewsFor.get(this);
-
-    if (callback) {
-      // We want to catch the close event immediately after the close events are
-      // emitted everywhere but without letting the event loop spin. Registering
-      // for the same events as windowEventListener but afterwards does this
-      let listener = (event, closedWin) => {
-        if (event != "close" || closedWin != domWindow)
-          return;
-
-        observer.off("*", listener);
-        callback();
-      }
-
-      observer.on("*", listener);
-    }
-
-    domWindow.close();
-  }
-});
-
-const windowTabs = new WeakMap();
-
-const BrowserWindow = Class({
-  extends: Window,
-
-  get tabs() {
-    let tabs = windowTabs.get(this);
-    if (tabs)
-      return tabs;
-
-    return new WindowTabs(this);
-  }
-});
-
-const WindowTabs = Class({
-  implements: [EventTarget],
-  extends: List,
-  initialize: function(window) {
-    List.prototype.initialize.call(this);
-    windowTabs.set(window, this);
-    viewsFor.set(this, viewsFor.get(window));
-
-    // Make sure the tabs module has loaded and found all existing tabs
-    const tabs = require('../tabs');
-
-    for (let tab of tabs) {
-      if (tab.window == window)
-        addListItem(this, tab);
-    }
-  },
-
-  get activeTab() {
-    return modelFor(getSelectedTab(viewsFor.get(this)));
-  },
-
-  open: function(options) {
-    options = Options(options);
-
-    let domWindow = viewsFor.get(this);
-    let { Tab } = require('../tabs/tab-firefox');
-
-    // The capturing listener will see the TabOpen event before
-    // sdk/tabs/observer giving us time to set up the tab and listeners before
-    // the real open event is fired
-    let listener = event => {
-      new Tab(event.target, options);
-    };
-
-    once(domWindow, "TabOpen", listener, true);
-    domWindow.gBrowser.addTab(options.url);
-  }
-});
-
-const BrowserWindows = Class({
-  implements: [EventTarget],
-  extends: List,
-  initialize: function() {
-    List.prototype.initialize.call(this);
-  },
-
-  get activeWindow() {
-    let domWindow = getMostRecentBrowserWindow();
-    if (ignoreWindow(domWindow))
-      return null;
-    return modelsFor.get(domWindow);
-  },
-
-  open: function(options) {
-    if (typeof options == "string")
-      options = { url: options };
-
-    let { url, isPrivate } = options;
-    if (url)
-      url = data.url(url);
-
-    let args = Cc["@mozilla.org/supports-string;1"].
-               createInstance(Ci.nsISupportsString);
-    args.data = url;
-
-    let features = {
-      chrome: true,
-      all: true,
-      dialog: false
-    };
-    features.private = supportPrivateWindows && isPrivate;
-
-    let domWindow = open(null, {
-      parent: null,
-      name: "_blank",
-      features,
-      args
-    })
-
-    let window = makeNewWindow(domWindow, true);
-    setListeners(window, options);
-    return window;
-  }
-});
-
-const browserWindows = new BrowserWindows();
-exports.browserWindows = browserWindows;
-
-function windowEmit(window, event, ...args) {
-  if (window instanceof BrowserWindow && (event == "open" || event == "close"))
-    emitOnObject(window, event, browserWindows, window, ...args);
-  else
-    emit(window, event, window, ...args);
-
-  if (window instanceof BrowserWindow)
-    emit(browserWindows, event, window, ...args);
-}
-
-function makeNewWindow(domWindow, browserHint = false) {
-  if (browserHint || isBrowser(domWindow))
-    return new BrowserWindow(domWindow);
-  else
-    return new Window(domWindow);
-}
-
-for (let domWindow of windows(null, {includePrivate: supportPrivateWindows})) {
-  let window = makeNewWindow(domWindow);
-  if (window instanceof BrowserWindow)
-    addListItem(browserWindows, window);
-}
-
-var windowEventListener = (event, domWindow, ...args) => {
-  let toplevelWindow = getToplevelWindow(domWindow);
-
-  if (ignoreWindow(toplevelWindow))
-    return;
-
-  let window = modelsFor.get(toplevelWindow);
-  if (!window)
-    window = makeNewWindow(toplevelWindow);
-
-  if (isBrowser(toplevelWindow)) {
-    if (event == "open")
-      addListItem(browserWindows, window);
-    else if (event == "close")
-      removeListItem(browserWindows, window);
-  }
-
-  windowEmit(window, event, ...args);
-
-  // The window object shouldn't be reachable after closed
-  if (event == "close") {
-    viewsFor.delete(window);
-    modelsFor.delete(toplevelWindow);
-  }
-};
-observer.on("*", windowEventListener);
-
-viewFor.define(BrowserWindow, window => {
-  return viewsFor.get(window);
-})
-
-const isBrowserWindow = (x) => x instanceof BrowserWindow;
-isPrivate.when(isBrowserWindow, (w) => isWindowPrivate(viewsFor.get(w)));
-isFocused.when(isBrowserWindow, (w) => isFocused(viewsFor.get(w)));
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows/observer.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { EventTarget } = require("../event/target");
-const { emit } = require("../event/core");
-const { WindowTracker, windowIterator } = require("../deprecated/window-utils");
-const { DOMEventAssembler } = require("../deprecated/events/assembler");
-const { Class } = require("../core/heritage");
-const { Cu } = require("chrome");
-
-// Event emitter objects used to register listeners and emit events on them
-// when they occur.
-const Observer = Class({
-  initialize() {
-    // Using `WindowTracker` to track window events.
-    WindowTracker({
-      onTrack: chromeWindow => {
-        emit(this, "open", chromeWindow);
-        this.observe(chromeWindow);
-      },
-      onUntrack: chromeWindow => {
-        emit(this, "close", chromeWindow);
-        this.ignore(chromeWindow);
-      }
-    });
-  },
-  implements: [EventTarget, DOMEventAssembler],
-  /**
-   * Events that are supported and emitted by the module.
-   */
-  supportedEventsTypes: [ "activate", "deactivate" ],
-  /**
-   * Function handles all the supported events on all the windows that are
-   * observed. Method is used to proxy events to the listeners registered on
-   * this event emitter.
-   * @param {Event} event
-   *    Keyboard event being emitted.
-   */
-  handleEvent(event) {
-    // Ignore events from windows in the child process as they can't be top-level
-    if (Cu.isCrossProcessWrapper(event.target))
-      return;
-    emit(this, event.type, event.target, event);
-  }
-});
-
-exports.observer = new Observer();
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows/tabs-fennec.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 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 { Class } = require('../core/heritage');
-const { Tab } = require('../tabs/tab');
-const { browserWindows } = require('./fennec');
-const { windowNS } = require('../window/namespace');
-const { tabsNS, tabNS } = require('../tabs/namespace');
-const { openTab, getTabs, getSelectedTab, getTabForBrowser: getRawTabForBrowser,
-        getTabContentWindow } = require('../tabs/utils');
-const { Options } = require('../tabs/common');
-const { getTabForBrowser, getTabForRawTab } = require('../tabs/helpers');
-const { on, once, off, emit } = require('../event/core');
-const { method } = require('../lang/functional');
-const { EVENTS } = require('../tabs/events');
-const { EventTarget } = require('../event/target');
-const { when: unload } = require('../system/unload');
-const { windowIterator } = require('../deprecated/window-utils');
-const { List, addListItem, removeListItem } = require('../util/list');
-const { isPrivateBrowsingSupported, data } = require('../self');
-const { isTabPBSupported, ignoreWindow } = require('../private-browsing/utils');
-
-const mainWindow = windowNS(browserWindows.activeWindow).window;
-
-const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec';
-
-const supportPrivateTabs = isPrivateBrowsingSupported && isTabPBSupported;
-
-const Tabs = Class({
-  implements: [ List ],
-  extends: EventTarget,
-  initialize: function initialize(options) {
-    let tabsInternals = tabsNS(this);
-    let window = tabsNS(this).window = options.window || mainWindow;
-
-    EventTarget.prototype.initialize.call(this, options);
-    List.prototype.initialize.apply(this, getTabs(window).map(Tab));
-
-    // TabOpen event
-    window.BrowserApp.deck.addEventListener(EVENTS.open.dom, onTabOpen);
-
-    // TabSelect
-    window.BrowserApp.deck.addEventListener(EVENTS.activate.dom, onTabSelect);
-  },
-  get activeTab() {
-    return getTabForRawTab(getSelectedTab(tabsNS(this).window));
-  },
-  open: function(options) {
-    options = Options(options);
-    let activeWin = browserWindows.activeWindow;
-
-    if (options.isPinned) {
-      console.error(ERR_FENNEC_MSG); // TODO
-    }
-
-    let url = options.url ? data.url(options.url) : options.url;
-    let rawTab = openTab(windowNS(activeWin).window, url, {
-      inBackground: options.inBackground,
-      isPrivate: supportPrivateTabs && options.isPrivate
-    });
-
-    // by now the tab has been created
-    let tab = getTabForRawTab(rawTab);
-
-    if (options.onClose)
-      tab.on('close', options.onClose);
-
-    if (options.onOpen) {
-      // NOTE: on Fennec this will be true
-      if (tabNS(tab).opened)
-        options.onOpen(tab);
-
-      tab.on('open', options.onOpen);
-    }
-
-    if (options.onReady)
-      tab.on('ready', options.onReady);
-
-    if (options.onLoad)
-      tab.on('load', options.onLoad);
-
-    if (options.onPageShow)
-      tab.on('pageshow', options.onPageShow);
-
-    if (options.onActivate)
-      tab.on('activate', options.onActivate);
-
-    return tab;
-  }
-});
-var gTabs = exports.tabs = Tabs(mainWindow);
-
-function tabsUnloader(event, window) {
-  window = window || (event && event.target);
-  if (!(window && window.BrowserApp))
-    return;
-  window.BrowserApp.deck.removeEventListener(EVENTS.open.dom, onTabOpen);
-  window.BrowserApp.deck.removeEventListener(EVENTS.activate.dom, onTabSelect);
-}
-
-// unload handler
-unload(function() {
-  for (let window in windowIterator()) {
-    tabsUnloader(null, window);
-  }
-});
-
-function addTab(tab) {
-  addListItem(gTabs, tab);
-  return tab;
-}
-
-function removeTab(tab) {
-  removeListItem(gTabs, tab);
-  return tab;
-}
-
-// TabOpen
-function onTabOpen(event) {
-  let browser = event.target;
-
-  // Eventually ignore private tabs
-  if (ignoreWindow(browser.contentWindow))
-    return;
-
-  let tab = getTabForBrowser(browser);
-  if (tab === null) {
-    let rawTab = getRawTabForBrowser(browser);
-
-    // create a Tab instance for this new tab
-    tab = addTab(Tab(rawTab));
-  }
-
-  tabNS(tab).opened = true;
-
-  tab.on('ready', () => emit(gTabs, 'ready', tab));
-  tab.once('close', onTabClose);
-
-  tab.on('pageshow', (_tab, persisted) =>
-    emit(gTabs, 'pageshow', tab, persisted));
-
-  emit(tab, 'open', tab);
-  emit(gTabs, 'open', tab);
-}
-
-// TabSelect
-function onTabSelect(event) {
-  let browser = event.target;
-
-  // Eventually ignore private tabs
-  if (ignoreWindow(browser.contentWindow))
-    return;
-
-  // Set value whenever new tab becomes active.
-  let tab = getTabForBrowser(browser);
-  emit(tab, 'activate', tab);
-  emit(gTabs, 'activate', tab);
-
-  for (let t of gTabs) {
-    if (t === tab) continue;
-    emit(t, 'deactivate', t);
-    emit(gTabs, 'deactivate', t);
-  }
-}
-
-// TabClose
-function onTabClose(tab) {
-  removeTab(tab);
-  emit(gTabs, EVENTS.close.name, tab);
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/worker/utils.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* 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';
-
-module.metadata = {
-  'stability': 'deprecated'
-};
-
-const {
-  requiresAddonGlobal, attach, detach, destroy, WorkerHost
-} = require('../content/utils');
-
-exports.WorkerHost = WorkerHost;
-exports.detach = detach;
-exports.attach = attach;
-exports.destroy = destroy;
-exports.requiresAddonGlobal = requiresAddonGlobal;