Bug 1350646: Part 6 - Remove SDK UI modules. r=Mossop
authorKris Maglione <maglione.k@gmail.com>
Wed, 02 Aug 2017 14:11:00 -0700
changeset 373704 f9dfc6d93bd677795a3377ae83b246a0da20dc63
parent 373703 b9fbf0b67b0976fcf8e0b45e239333b72becbd2c
child 373705 85d0f12f82e474c11f6e5f9eac6185de73235adf
push id93584
push usermaglione.k@gmail.com
push dateThu, 10 Aug 2017 03:41:19 +0000
treeherdermozilla-inbound@24d5dbf3a9dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1350646
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1350646: Part 6 - Remove SDK UI modules. r=Mossop MozReview-Commit-ID: Joln7vw9Y9r
addon-sdk/moz.build
addon-sdk/source/lib/diffpatcher/diff.js
addon-sdk/source/lib/diffpatcher/index.js
addon-sdk/source/lib/diffpatcher/patch.js
addon-sdk/source/lib/diffpatcher/rebase.js
addon-sdk/source/lib/diffpatcher/test/common.js
addon-sdk/source/lib/diffpatcher/test/diff.js
addon-sdk/source/lib/diffpatcher/test/index.js
addon-sdk/source/lib/diffpatcher/test/patch.js
addon-sdk/source/lib/diffpatcher/test/tap.js
addon-sdk/source/lib/framescript/context-menu.js
addon-sdk/source/lib/sdk/content/context-menu.js
addon-sdk/source/lib/sdk/context-menu.js
addon-sdk/source/lib/sdk/context-menu/context.js
addon-sdk/source/lib/sdk/context-menu/core.js
addon-sdk/source/lib/sdk/context-menu/readers.js
addon-sdk/source/lib/sdk/context-menu@2.js
addon-sdk/source/lib/sdk/input/browser.js
addon-sdk/source/lib/sdk/input/customizable-ui.js
addon-sdk/source/lib/sdk/input/frame.js
addon-sdk/source/lib/sdk/input/system.js
addon-sdk/source/lib/sdk/panel.js
addon-sdk/source/lib/sdk/panel/events.js
addon-sdk/source/lib/sdk/panel/utils.js
addon-sdk/source/lib/sdk/ui.js
addon-sdk/source/lib/sdk/ui/button/action.js
addon-sdk/source/lib/sdk/ui/button/contract.js
addon-sdk/source/lib/sdk/ui/button/toggle.js
addon-sdk/source/lib/sdk/ui/button/view.js
addon-sdk/source/lib/sdk/ui/button/view/events.js
addon-sdk/source/lib/sdk/ui/component.js
addon-sdk/source/lib/sdk/ui/frame.js
addon-sdk/source/lib/sdk/ui/frame/model.js
addon-sdk/source/lib/sdk/ui/frame/view.html
addon-sdk/source/lib/sdk/ui/frame/view.js
addon-sdk/source/lib/sdk/ui/id.js
addon-sdk/source/lib/sdk/ui/sidebar.js
addon-sdk/source/lib/sdk/ui/sidebar/actions.js
addon-sdk/source/lib/sdk/ui/sidebar/contract.js
addon-sdk/source/lib/sdk/ui/sidebar/namespace.js
addon-sdk/source/lib/sdk/ui/sidebar/utils.js
addon-sdk/source/lib/sdk/ui/sidebar/view.js
addon-sdk/source/lib/sdk/ui/state.js
addon-sdk/source/lib/sdk/ui/state/events.js
addon-sdk/source/lib/sdk/ui/toolbar.js
addon-sdk/source/lib/sdk/ui/toolbar/model.js
addon-sdk/source/lib/sdk/ui/toolbar/view.js
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -16,28 +16,18 @@ EXTRA_JS_MODULES.sdk += [
     'source/app-extension/bootstrap.js',
 ]
 
 EXTRA_JS_MODULES.sdk.system += [
     'source/modules/system/Startup.js',
 ]
 
 modules = [
-    'diffpatcher/diff.js',
-    'diffpatcher/index.js',
-    'diffpatcher/patch.js',
-    'diffpatcher/rebase.js',
-    'diffpatcher/test/common.js',
-    'diffpatcher/test/diff.js',
-    'diffpatcher/test/index.js',
-    'diffpatcher/test/patch.js',
-    'diffpatcher/test/tap.js',
     'framescript/FrameScriptManager.jsm',
     'framescript/content.jsm',
-    'framescript/context-menu.js',
     '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',
@@ -47,34 +37,28 @@ modules = [
     '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/context-menu.js',
     'sdk/content/events.js',
     'sdk/content/l10n-html.js',
     'sdk/content/loader.js',
     'sdk/content/mod.js',
     'sdk/content/page-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/context-menu.js',
-    'sdk/context-menu/context.js',
-    'sdk/context-menu/core.js',
-    'sdk/context-menu/readers.js',
-    'sdk/context-menu@2.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',
@@ -89,20 +73,16 @@ modules = [
     'sdk/event/core.js',
     'sdk/event/dom.js',
     'sdk/event/target.js',
     'sdk/event/utils.js',
     'sdk/frame/utils.js',
     'sdk/fs/path.js',
     'sdk/hotkeys.js',
     'sdk/indexed-db.js',
-    'sdk/input/browser.js',
-    'sdk/input/customizable-ui.js',
-    'sdk/input/frame.js',
-    'sdk/input/system.js',
     'sdk/io/buffer.js',
     'sdk/io/byte-streams.js',
     'sdk/io/file.js',
     'sdk/io/fs.js',
     'sdk/io/stream.js',
     'sdk/io/text-streams.js',
     'sdk/keyboard/hotkeys.js',
     'sdk/keyboard/observer.js',
@@ -126,19 +106,16 @@ modules = [
     'sdk/messaging.js',
     'sdk/model/core.js',
     'sdk/net/url.js',
     'sdk/net/xhr.js',
     'sdk/notifications.js',
     'sdk/output/system.js',
     'sdk/page-mod.js',
     'sdk/page-mod/match-pattern.js',
-    'sdk/panel.js',
-    'sdk/panel/events.js',
-    'sdk/panel/utils.js',
     'sdk/passwords.js',
     'sdk/passwords/utils.js',
     'sdk/platform/xpcom.js',
     'sdk/preferences/event-target.js',
     'sdk/preferences/native-options.js',
     'sdk/preferences/service.js',
     'sdk/preferences/utils.js',
     'sdk/private-browsing.js',
@@ -183,39 +160,16 @@ modules = [
     'sdk/test/harness.js',
     'sdk/test/httpd.js',
     'sdk/test/loader.js',
     'sdk/test/memory.js',
     'sdk/test/options.js',
     'sdk/test/runner.js',
     'sdk/test/utils.js',
     'sdk/timers.js',
-    'sdk/ui.js',
-    'sdk/ui/button/action.js',
-    'sdk/ui/button/contract.js',
-    'sdk/ui/button/toggle.js',
-    'sdk/ui/button/view.js',
-    'sdk/ui/button/view/events.js',
-    'sdk/ui/component.js',
-    'sdk/ui/frame.js',
-    'sdk/ui/frame/model.js',
-    'sdk/ui/frame/view.html',
-    'sdk/ui/frame/view.js',
-    'sdk/ui/id.js',
-    'sdk/ui/sidebar.js',
-    'sdk/ui/sidebar/actions.js',
-    'sdk/ui/sidebar/contract.js',
-    'sdk/ui/sidebar/namespace.js',
-    'sdk/ui/sidebar/utils.js',
-    'sdk/ui/sidebar/view.js',
-    'sdk/ui/state.js',
-    'sdk/ui/state/events.js',
-    'sdk/ui/toolbar.js',
-    'sdk/ui/toolbar/model.js',
-    'sdk/ui/toolbar/view.js',
     'sdk/uri/resource.js',
     'sdk/url.js',
     'sdk/url/utils.js',
     'sdk/util/array.js',
     'sdk/util/collection.js',
     'sdk/util/contract.js',
     'sdk/util/deprecate.js',
     'sdk/util/dispatcher.js',
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/diff.js
+++ /dev/null
@@ -1,45 +0,0 @@
-"use strict";
-
-var method = require("../method/core")
-
-// Method is designed to work with data structures representing application
-// state. Calling it with a state should return object representing `delta`
-// that has being applied to a previous state to get to a current state.
-//
-// Example
-//
-// diff(state) // => { "item-id-1": { title: "some title" } "item-id-2": null }
-var diff = method("diff@diffpatcher")
-
-// diff between `null` / `undefined` to any hash is a hash itself.
-diff.define(null, function(from, to) { return to })
-diff.define(undefined, function(from, to) { return to })
-diff.define(Object, function(from, to) {
-  return calculate(from, to || {}) || {}
-})
-
-function calculate(from, to) {
-  var diff = {}
-  var changes = 0
-  Object.keys(from).forEach(function(key) {
-    changes = changes + 1
-    if (!(key in to) && from[key] != null) diff[key] = null
-    else changes = changes - 1
-  })
-  Object.keys(to).forEach(function(key) {
-    changes = changes + 1
-    var previous = from[key]
-    var current = to[key]
-    if (previous === current) return (changes = changes - 1)
-    if (typeof(current) !== "object") return diff[key] = current
-    if (typeof(previous) !== "object") return diff[key] = current
-    var delta = calculate(previous, current)
-    if (delta) diff[key] = delta
-    else changes = changes - 1
-  })
-  return changes ? diff : null
-}
-
-diff.calculate = calculate
-
-module.exports = diff
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-"use strict";
-
-exports.diff = require("./diff")
-exports.patch = require("./patch")
-exports.rebase = require("./rebase")
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/patch.js
+++ /dev/null
@@ -1,21 +0,0 @@
-"use strict";
-
-var method = require("../method/core")
-var rebase = require("./rebase")
-
-// Method is designed to work with data structures representing application
-// state. Calling it with a state and delta should return object representing
-// new state, with changes in `delta` being applied to previous.
-//
-// ## Example
-//
-// patch(state, {
-//   "item-id-1": { completed: false }, // update
-//   "item-id-2": null                  // delete
-// })
-var patch = method("patch@diffpatcher")
-patch.define(Object, function patch(hash, delta) {
-  return rebase({}, hash, delta)
-})
-
-module.exports = patch
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/rebase.js
+++ /dev/null
@@ -1,36 +0,0 @@
-"use strict";
-
-var nil = {}
-var owns = ({}).hasOwnProperty
-
-function rebase(result, parent, delta) {
-  var key, current, previous, update
-  for (key in parent) {
-    if (owns.call(parent, key)) {
-      previous = parent[key]
-      update = owns.call(delta, key) ? delta[key] : nil
-      if (previous === null) continue
-      else if (previous === void(0)) continue
-      else if (update === null) continue
-      else if (update === void(0)) continue
-      else result[key] = previous
-    }
-  }
-  for (key in delta) {
-    if (owns.call(delta, key)) {
-      update = delta[key]
-      current = owns.call(result, key) ? result[key] : nil
-      if (current === update) continue
-      else if (update === null) continue
-      else if (update === void(0)) continue
-      else if (current === nil) result[key] = update
-      else if (typeof(update) !== "object") result[key] = update
-      else if (typeof(current) !== "object") result[key] = update
-      else result[key]= rebase({}, current, update)
-    }
-  }
-
-  return result
-}
-
-module.exports = rebase
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/test/common.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-require("test").run(require("./index"))
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/test/diff.js
+++ /dev/null
@@ -1,59 +0,0 @@
-"use strict";
-
-var diff = require("../diff")
-
-exports["test diff from null"] = function(assert) {
-  var to = { a: 1, b: 2 }
-  assert.equal(diff(null, to), to, "diff null to x returns x")
-  assert.equal(diff(void(0), to), to, "diff undefined to x returns x")
-
-}
-
-exports["test diff to null"] = function(assert) {
-  var from = { a: 1, b: 2 }
-  assert.deepEqual(diff({ a: 1, b: 2 }, null),
-                   { a: null, b: null },
-                   "diff x null returns x with all properties nullified")
-}
-
-exports["test diff identical"] = function(assert) {
-  assert.deepEqual(diff({}, {}), {}, "diff on empty objects is {}")
-
-  assert.deepEqual(diff({ a: 1, b: 2 }, { a: 1, b: 2 }), {},
-                   "if properties match diff is {}")
-
-  assert.deepEqual(diff({ a: 1, b: { c: { d: 3, e: 4 } } },
-                        { a: 1, b: { c: { d: 3, e: 4 } } }), {},
-                   "diff between identical nested hashes is {}")
-
-}
-
-exports["test diff delete"] = function(assert) {
-  assert.deepEqual(diff({ a: 1, b: 2 }, { b: 2 }), { a: null },
-                   "missing property is deleted")
-  assert.deepEqual(diff({ a: 1, b: 2 }, { a: 2 }), { a: 2, b: null },
-                   "missing property is deleted another updated")
-  assert.deepEqual(diff({ a: 1, b: 2 }, {}), { a: null, b: null },
-                   "missing propertes are deleted")
-  assert.deepEqual(diff({ a: 1, b: { c: { d: 2 } } }, {}),
-                   { a: null, b: null },
-                   "missing deep propertes are deleted")
-  assert.deepEqual(diff({ a: 1, b: { c: { d: 2 } } }, { b: { c: {} } }),
-                   { a: null, b: { c: { d: null } } },
-                   "missing nested propertes are deleted")
-}
-
-exports["test add update"] = function(assert) {
-  assert.deepEqual(diff({ a: 1, b: 2 }, { b: 2, c: 3 }), { a: null, c: 3 },
-                   "delete and add")
-  assert.deepEqual(diff({ a: 1, b: 2 }, { a: 2, c: 3 }), { a: 2, b: null, c: 3 },
-                   "delete and adds")
-  assert.deepEqual(diff({}, { a: 1, b: 2 }), { a: 1, b: 2 },
-                   "diff on empty objcet returns equivalen of to")
-  assert.deepEqual(diff({ a: 1, b: { c: { d: 2 } } }, { d: 3 }),
-                   { a: null, b: null, d: 3 },
-                   "missing deep propertes are deleted")
-  assert.deepEqual(diff({ b: { c: {} }, d: null }, { a: 1, b: { c: { d: 2 } } }),
-                   { a: 1, b: { c: { d: 2 } } },
-                   "missing nested propertes are deleted")
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/test/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-"use strict";
-
-var diff = require("../diff")
-var patch = require("../patch")
-
-exports["test diff"] = require("./diff")
-exports["test patch"] = require("./patch")
-
-exports["test patch(a, diff(a, b)) => b"] = function(assert) {
-  var a = { a: { b: 1 }, c: { d: 2 } }
-  var b = { a: { e: 3 }, c: { d: 4 } }
-
-  assert.deepEqual(patch(a, diff(a, b)), b, "patch(a, diff(a, b)) => b")
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/test/patch.js
+++ /dev/null
@@ -1,83 +0,0 @@
-"use strict";
-
-var patch = require("../patch")
-
-exports["test patch delete"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, { a: null }), { b: 2 }, "null removes property")
-}
-
-exports["test patch delete with void"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, { a: void(0) }), { b: 2 },
-                   "void(0) removes property")
-}
-
-exports["test patch delete missing"] = function(assert) {
-  assert.deepEqual(patch({ a: 1, b: 2 }, { c: null }),
-                   { a: 1, b: 2 },
-                   "null removes property if exists");
-
-  assert.deepEqual(patch({ a: 1, b: 2 }, { c: void(0) }),
-                   { a: 1, b: 2 },
-                   "void removes property if exists");
-}
-
-exports["test delete deleted"] = function(assert) {
-  assert.deepEqual(patch({ a: null, b: 2, c: 3, d: void(0)},
-                         { a: void(0), b: null, d: null }),
-                   {c: 3},
-                  "removed all existing and non existing");
-}
-
-exports["test update deleted"] = function(assert) {
-  assert.deepEqual(patch({ a: null, b: void(0), c: 3},
-                         { a: { b: 2 } }),
-                   { a: { b: 2 }, c: 3 },
-                   "replace deleted");
-}
-
-exports["test patch delete with void"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, { a: void(0) }), { b: 2 },
-                   "void(0) removes property")
-}
-
-
-exports["test patch addition"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, { c: 3 }), { a: 1, b: 2, c: 3 },
-                   "new properties are added")
-}
-
-exports["test patch addition"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, { c: 3 }), { a: 1, b: 2, c: 3 },
-                   "new properties are added")
-}
-
-exports["test hash on itself"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, hash), hash,
-                   "applying hash to itself returns hash itself")
-}
-
-exports["test patch with empty delta"] = function(assert) {
-  var hash = { a: 1, b: 2 }
-
-  assert.deepEqual(patch(hash, {}), hash,
-                   "applying empty delta results in no changes")
-}
-
-exports["test patch nested data"] = function(assert) {
-  assert.deepEqual(patch({ a: { b: 1 }, c: { d: 2 } },
-                         { a: { b: null, e: 3 }, c: { d: 4 } }),
-                   { a: { e: 3 }, c: { d: 4 } },
-                   "nested structures can also be patched")
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/test/tap.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-require("retape")(require("./index"))
deleted file mode 100644
--- a/addon-sdk/source/lib/framescript/context-menu.js
+++ /dev/null
@@ -1,215 +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 { query, constant, cache } = require("sdk/lang/functional");
-const { pairs, each, map, object } = require("sdk/util/sequence");
-const { nodeToMessageManager } = require("./util");
-
-// Decorator function that takes `f` function and returns one that attempts
-// to run `f` with given arguments. In case of exception error is logged
-// and `fallback` is returned instead.
-const Try = (fn, fallback=null) => (...args) => {
-  try {
-    return fn(...args);
-  } catch(error) {
-    console.error(error);
-    return fallback;
-  }
-};
-
-// Decorator funciton that takes `f` function and returns one that returns
-// JSON cloned result of whatever `f` returns for given arguments.
-const JSONReturn = f => (...args) => JSON.parse(JSON.stringify(f(...args)));
-
-const Null = constant(null);
-
-// Table of readers mapped to field names they're going to be reading.
-const readers = Object.create(null);
-// Read function takes "contextmenu" event target `node` and returns table of
-// read field names mapped to appropriate values. Read uses above defined read
-// table to read data for all registered readers.
-const read = node =>
-  object(...map(([id, read]) => [id, read(node, id)], pairs(readers)));
-
-// Table of built-in readers, each takes a descriptor and returns a reader:
-// descriptor -> node -> JSON
-const parsers = Object.create(null)
-// Function takes a descriptor of the remotely defined reader and parsese it
-// to construct a local reader that's going to read out data from context menu
-// target.
-const parse = descriptor => {
-  const parser = parsers[descriptor.category];
-  if (!parser) {
-    console.error("Unknown reader descriptor was received", descriptor, `"${descriptor.category}"`);
-    return Null
-  }
-  return Try(parser(descriptor));
-}
-
-// TODO: Test how chrome's mediaType behaves to try and match it's behavior.
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const SVG_NS = "http://www.w3.org/2000/svg";
-
-// Firefox always creates a HTMLVideoElement when loading an ogg file
-// directly. If the media is actually audio, be smarter and provide a
-// context menu with audio operations.
-// Source: https://github.com/mozilla/gecko-dev/blob/28c2fca3753c5371643843fc2f2f205146b083b7/browser/base/content/nsContextMenu.js#L632-L637
-const isVideoLoadingAudio = node =>
-  node.readyState >= node.HAVE_METADATA &&
-    (node.videoWidth == 0 || node.videoHeight == 0)
-
-const isVideo = node =>
-  node instanceof node.ownerGlobal.HTMLVideoElement &&
-  !isVideoLoadingAudio(node);
-
-const isAudio = node => {
-  const {HTMLVideoElement, HTMLAudioElement} = node.ownerGlobal;
-  return node instanceof HTMLAudioElement ? true :
-         node instanceof HTMLVideoElement ? isVideoLoadingAudio(node) :
-         false;
-};
-
-const isImage = ({namespaceURI, localName}) =>
-  namespaceURI === HTML_NS && localName === "img" ? true :
-  namespaceURI === XUL_NS && localName === "image" ? true :
-  namespaceURI === SVG_NS && localName === "image" ? true :
-  false;
-
-parsers["reader/MediaType()"] = constant(node =>
-  isImage(node) ? "image" :
-  isAudio(node) ? "audio" :
-  isVideo(node) ? "video" :
-  null);
-
-
-const readLink = node =>
-  node.namespaceURI === HTML_NS && node.localName === "a" ? node.href :
-  readLink(node.parentNode);
-
-parsers["reader/LinkURL()"] = constant(node =>
-  node.matches("a, a *") ? readLink(node) : null);
-
-// Reader that reads out `true` if "contextmenu" `event.target` matches
-// `descriptor.selector` and `false` if it does not.
-parsers["reader/SelectorMatch()"] = ({selector}) =>
-  node => node.matches(selector);
-
-// Accessing `selectionStart` and `selectionEnd` properties on non
-// editable input nodes throw exceptions, there for we need this util
-// function to guard us against them.
-const getInputSelection = node => {
-  try {
-    if ("selectionStart" in node && "selectionEnd" in node) {
-      const {selectionStart, selectionEnd} = node;
-      return {selectionStart, selectionEnd}
-    }
-  }
-  catch(_) {}
-
-  return null;
-}
-
-// Selection reader does not really cares about descriptor so it is
-// a constant function returning selection reader. Selection reader
-// returns string of the selected text or `null` if there is no selection.
-parsers["reader/Selection()"] = constant(node => {
-  const selection = node.ownerDocument.getSelection();
-  if (!selection.isCollapsed) {
-    return selection.toString();
-  }
-  // If target node is editable (text, input, textarea, etc..) document does
-  // not really handles selections there. There for we fallback to checking
-  // `selectionStart` `selectionEnd` properties and if they are present we
-  // extract selections manually from the `node.value`.
-  else {
-    const selection = getInputSelection(node);
-    const isSelected = selection &&
-                       Number.isInteger(selection.selectionStart) &&
-                       Number.isInteger(selection.selectionEnd) &&
-                       selection.selectionStart !== selection.selectionEnd;
-    return  isSelected ? node.value.substring(selection.selectionStart,
-                                              selection.selectionEnd) :
-            null;
-  }
-});
-
-// Query reader just reads out properties from the node, so we just use `query`
-// utility function.
-parsers["reader/Query()"] = ({path}) => JSONReturn(query(path));
-// Attribute reader just reads attribute of the event target node.
-parsers["reader/Attribute()"] = ({name}) => node => node.getAttribute(name);
-
-// Extractor reader defines generates a reader out of serialized function, who's
-// return value is JSON cloned. Note: We do know source will evaluate to function
-// as that's what we serialized on the other end, it's also ok if generated function
-// is going to throw as registered readers are wrapped in try catch to avoid breakting
-// unrelated readers.
-parsers["reader/Extractor()"] = ({source}) =>
-  JSONReturn(new Function("return (" + source + ")")());
-
-// If the context-menu target node or any of its ancestors is one of these,
-// Firefox uses a tailored context menu, and so the page context doesn't apply.
-// There for `reader/isPage()` will read `false` in that case otherwise it's going
-// to read `true`.
-const nonPageElements = ["a", "applet", "area", "button", "canvas", "object",
-                         "embed", "img", "input", "map", "video", "audio", "menu",
-                         "option", "select", "textarea", "[contenteditable=true]"];
-const nonPageSelector = nonPageElements.
-                          concat(nonPageElements.map(tag => `${tag} *`)).
-                          join(", ");
-
-// Note: isPageContext implementation could have actually used SelectorMatch reader,
-// but old implementation was also checked for collapsed selection there for to keep
-// the behavior same we end up implementing a new reader.
-parsers["reader/isPage()"] = constant(node =>
-  node.ownerGlobal.getSelection().isCollapsed &&
-  !node.matches(nonPageSelector));
-
-// Reads `true` if node is in an iframe otherwise returns true.
-parsers["reader/isFrame()"] = constant(node =>
-  !!node.ownerGlobal.frameElement);
-
-parsers["reader/isEditable()"] = constant(node => {
-  const selection = getInputSelection(node);
-  return selection ? !node.readOnly && !node.disabled : node.isContentEditable;
-});
-
-
-// TODO: Add some reader to read out tab id.
-
-const onReadersUpdate = message => {
-  each(([id, descriptor]) => {
-    if (descriptor) {
-      readers[id] = parse(descriptor);
-    }
-    else {
-      delete readers[id];
-    }
-  }, pairs(message.data));
-};
-exports.onReadersUpdate = onReadersUpdate;
-
-
-const onContextMenu = event => {
-  if (!event.defaultPrevented) {
-    const manager = nodeToMessageManager(event.target);
-    manager.sendSyncMessage("sdk/context-menu/read", read(event.target), readers);
-  }
-};
-exports.onContextMenu = onContextMenu;
-
-
-const onContentFrame = (frame) => {
-  // Listen for contextmenu events in on this frame.
-  frame.addEventListener("contextmenu", onContextMenu);
-  // Listen to registered reader changes and update registry.
-  frame.addMessageListener("sdk/context-menu/readers", onReadersUpdate);
-
-  // Request table of readers (if this is loaded in a new process some table
-  // changes may be missed, this is way to sync up).
-  frame.sendAsyncMessage("sdk/context-menu/readers?");
-};
-exports.onContentFrame = onContentFrame;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/content/context-menu.js
+++ /dev/null
@@ -1,407 +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 self = require("../self");
-const { WorkerChild } = require("./worker-child");
-const { getInnerId } = require("../window/utils");
-const { Ci } = require("chrome");
-const { Services } = require("resource://gre/modules/Services.jsm");
-const system = require('../system/events');
-const { process } = require('../remote/child');
-
-// These functions are roughly copied from sdk/selection which doesn't work
-// in the content process
-function getElementWithSelection(window) {
-  let element = Services.focus.getFocusedElementForWindow(window, false, {});
-  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) {
-    console.exception(err);
-    return null;
-  }
-}
-
-function safeGetRange(selection, rangeNumber) {
-  try {
-    let { rangeCount } = selection;
-    let range = null;
-
-    for (let rangeNumber = 0; rangeNumber < rangeCount; rangeNumber++ ) {
-      range = selection.getRangeAt(rangeNumber);
-
-      if (range && range.toString())
-        break;
-
-      range = null;
-    }
-
-    return range;
-  }
-  catch (e) {
-    return null;
-  }
-}
-
-function getSelection(window) {
-  let selection = window.getSelection();
-  let range = safeGetRange(selection);
-  if (range)
-    return range.toString();
-
-  let node = getElementWithSelection(window);
-  if (!node)
-    return null;
-
-  return node.value.substring(node.selectionStart, node.selectionEnd);
-}
-
-//These are used by PageContext.isCurrent below. If the popupNode or any of
-//its ancestors is one of these, Firefox uses a tailored context menu, and so
-//the page context doesn't apply.
-const NON_PAGE_CONTEXT_ELTS = [
-  Ci.nsIDOMHTMLAnchorElement,
-  Ci.nsIDOMHTMLAreaElement,
-  Ci.nsIDOMHTMLButtonElement,
-  Ci.nsIDOMHTMLCanvasElement,
-  Ci.nsIDOMHTMLEmbedElement,
-  Ci.nsIDOMHTMLImageElement,
-  Ci.nsIDOMHTMLInputElement,
-  Ci.nsIDOMHTMLMapElement,
-  Ci.nsIDOMHTMLMediaElement,
-  Ci.nsIDOMHTMLMenuElement,
-  Ci.nsIDOMHTMLObjectElement,
-  Ci.nsIDOMHTMLOptionElement,
-  Ci.nsIDOMHTMLSelectElement,
-  Ci.nsIDOMHTMLTextAreaElement,
-];
-
-// List all editable types of inputs.  Or is it better to have a list
-// of non-editable inputs?
-var editableInputs = {
-  email: true,
-  number: true,
-  password: true,
-  search: true,
-  tel: true,
-  text: true,
-  textarea: true,
-  url: true
-};
-
-var CONTEXTS = {};
-
-var Context = Class({
-  initialize: function(id) {
-    this.id = id;
-  },
-
-  adjustPopupNode: function adjustPopupNode(popupNode) {
-    return popupNode;
-  },
-
-  // Gets state to pass through to the parent process for the node the user
-  // clicked on
-  getState: function(popupNode) {
-    return false;
-  }
-});
-
-// Matches when the context-clicked node doesn't have any of
-// NON_PAGE_CONTEXT_ELTS in its ancestors
-CONTEXTS.PageContext = Class({
-  extends: Context,
-
-  getState: function(popupNode) {
-    // If there is a selection in the window then this context does not match
-    if (!popupNode.ownerGlobal.getSelection().isCollapsed)
-      return false;
-
-    // If the clicked node or any of its ancestors is one of the blocked
-    // NON_PAGE_CONTEXT_ELTS then this context does not match
-    while (!(popupNode instanceof Ci.nsIDOMDocument)) {
-      if (NON_PAGE_CONTEXT_ELTS.some(type => popupNode instanceof type))
-        return false;
-
-      popupNode = popupNode.parentNode;
-    }
-
-    return true;
-  }
-});
-
-// Matches when there is an active selection in the window
-CONTEXTS.SelectionContext = Class({
-  extends: Context,
-
-  getState: function(popupNode) {
-    if (!popupNode.ownerGlobal.getSelection().isCollapsed)
-      return true;
-
-    try {
-      // The node may be a text box which has selectionStart and selectionEnd
-      // properties. If not this will throw.
-      let { selectionStart, selectionEnd } = popupNode;
-      return !isNaN(selectionStart) && !isNaN(selectionEnd) &&
-             selectionStart !== selectionEnd;
-    }
-    catch (e) {
-      return false;
-    }
-  }
-});
-
-// Matches when the context-clicked node or any of its ancestors matches the
-// selector given
-CONTEXTS.SelectorContext = Class({
-  extends: Context,
-
-  initialize: function initialize(id, selector) {
-    Context.prototype.initialize.call(this, id);
-    this.selector = selector;
-  },
-
-  adjustPopupNode: function adjustPopupNode(popupNode) {
-    let selector = this.selector;
-
-    while (!(popupNode instanceof Ci.nsIDOMDocument)) {
-      if (popupNode.matches(selector))
-        return popupNode;
-
-      popupNode = popupNode.parentNode;
-    }
-
-    return null;
-  },
-
-  getState: function(popupNode) {
-    return !!this.adjustPopupNode(popupNode);
-  }
-});
-
-// Matches when the page url matches any of the patterns given
-CONTEXTS.URLContext = Class({
-  extends: Context,
-
-  getState: function(popupNode) {
-    return popupNode.ownerDocument.URL;
-  }
-});
-
-// Matches when the user-supplied predicate returns true
-CONTEXTS.PredicateContext = Class({
-  extends: Context,
-
-  getState: function(node) {
-    let window = node.ownerGlobal;
-    let data = {};
-
-    data.documentType = node.ownerDocument.contentType;
-
-    data.documentURL = node.ownerDocument.location.href;
-    data.targetName = node.nodeName.toLowerCase();
-    data.targetID = node.id || null ;
-
-    if ((data.targetName === 'input' && editableInputs[node.type]) ||
-        data.targetName === 'textarea') {
-      data.isEditable = !node.readOnly && !node.disabled;
-    }
-    else {
-      data.isEditable = node.isContentEditable;
-    }
-
-    data.selectionText = getSelection(window, "TEXT");
-
-    data.srcURL = node.src || null;
-    data.value = node.value || null;
-
-    while (!data.linkURL && node) {
-      data.linkURL = node.href || null;
-      node = node.parentNode;
-    }
-
-    return data;
-  },
-});
-
-function instantiateContext({ id, type, args }) {
-  if (!(type in CONTEXTS)) {
-    console.error("Attempt to use unknown context " + type);
-    return;
-  }
-  return new CONTEXTS[type](id, ...args);
-}
-
-var ContextWorker = Class({
-  implements: [ WorkerChild ],
-
-  // Calls the context workers context listeners and returns the first result
-  // that is either a string or a value that evaluates to true. If all of the
-  // listeners returned false then returns false. If there are no listeners,
-  // returns true (show the menu item by default).
-  getMatchedContext: function getCurrentContexts(popupNode) {
-    let results = this.sandbox.emitSync("context", popupNode);
-    if (!results.length)
-      return true;
-    return results.reduce((val, result) => val || result);
-  },
-
-  // Emits a click event in the worker's port. popupNode is the node that was
-  // context-clicked, and clickedItemData is the data of the item that was
-  // clicked.
-  fireClick: function fireClick(popupNode, clickedItemData) {
-    this.sandbox.emitSync("click", popupNode, clickedItemData);
-  }
-});
-
-// Gets the item's content script worker for a window, creating one if necessary
-// Once created it will be automatically destroyed when the window unloads.
-// If there is not content scripts for the item then null will be returned.
-function getItemWorkerForWindow(item, window) {
-  if (!item.contentScript && !item.contentScriptFile)
-    return null;
-
-  let id = getInnerId(window);
-  let worker = item.workerMap.get(id);
-
-  if (worker)
-    return worker;
-
-  worker = ContextWorker({
-    id: item.id,
-    window,
-    manager: item.manager,
-    contentScript: item.contentScript,
-    contentScriptFile: item.contentScriptFile,
-    onDetach: function() {
-      item.workerMap.delete(id);
-    }
-  });
-
-  item.workerMap.set(id, worker);
-
-  return worker;
-}
-
-// A very simple remote proxy for every item. It's job is to provide data for
-// the main process to use to determine visibility state and to call into
-// content scripts when clicked.
-var RemoteItem = Class({
-  initialize: function(options, manager) {
-    this.id = options.id;
-    this.contexts = options.contexts.map(instantiateContext);
-    this.contentScript = options.contentScript;
-    this.contentScriptFile = options.contentScriptFile;
-
-    this.manager = manager;
-
-    this.workerMap = new Map();
-    keepAlive.set(this.id, this);
-  },
-
-  destroy: function() {
-    for (let worker of this.workerMap.values()) {
-      worker.destroy();
-    }
-    keepAlive.delete(this.id);
-  },
-
-  activate: function(popupNode, data) {
-    let worker = getItemWorkerForWindow(this, popupNode.ownerGlobal);
-    if (!worker)
-      return;
-
-    for (let context of this.contexts)
-      popupNode = context.adjustPopupNode(popupNode);
-
-    worker.fireClick(popupNode, data);
-  },
-
-  // Fills addonInfo with state data to send through to the main process
-  getContextState: function(popupNode, addonInfo) {
-    if (!(self.id in addonInfo)) {
-      addonInfo[self.id] = {
-        processID: process.id,
-        items: {}
-      };
-    }
-
-    let worker = getItemWorkerForWindow(this, popupNode.ownerGlobal);
-    let contextStates = {};
-    for (let context of this.contexts)
-      contextStates[context.id] = context.getState(popupNode);
-
-    addonInfo[self.id].items[this.id] = {
-      // It isn't ideal to create a PageContext for every item but there isn't
-      // a good shared place to do it.
-      pageContext: (new CONTEXTS.PageContext()).getState(popupNode),
-      contextStates,
-      hasWorker: !!worker,
-      workerContext: worker ? worker.getMatchedContext(popupNode) : true
-    }
-  }
-});
-exports.RemoteItem = RemoteItem;
-
-// Holds remote items for this frame.
-var keepAlive = new Map();
-
-// Called to create remote proxies for items. If they already exist we destroy
-// and recreate. This can happen if the item changes in some way or in odd
-// timing cases where the frame script is create around the same time as the
-// item is created in the main process
-process.port.on('sdk/contextmenu/createitems', (process, items) => {
-  for (let itemoptions of items) {
-    let oldItem = keepAlive.get(itemoptions.id);
-    if (oldItem) {
-      oldItem.destroy();
-    }
-
-    let item = new RemoteItem(itemoptions, this);
-  }
-});
-
-process.port.on('sdk/contextmenu/destroyitems', (process, items) => {
-  for (let id of items) {
-    let item = keepAlive.get(id);
-    item.destroy();
-  }
-});
-
-var lastPopupNode = null;
-
-system.on('content-contextmenu', ({ subject }) => {
-  let { event: { target: popupNode }, addonInfo } = subject.wrappedJSObject;
-  lastPopupNode = popupNode;
-
-  for (let item of keepAlive.values()) {
-    item.getContextState(popupNode, addonInfo);
-  }
-}, true);
-
-process.port.on('sdk/contextmenu/activateitems', (process, items, data) => {
-  for (let id of items) {
-    let item = keepAlive.get(id);
-    if (!item)
-      continue;
-
-    item.activate(lastPopupNode, data);
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/context-menu.js
+++ /dev/null
@@ -1,1187 +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": {
-    // TODO Fennec support Bug 788334
-    "Firefox": "*",
-    "SeaMonkey": "*"
-  }
-};
-
-const { Class, mix } = require("./core/heritage");
-const { ns } = require("./core/namespace");
-lazyRequire(this, "./deprecated/api-utils", "validateOptions", "getTypeOf");
-lazyRequire(this, "./url", "URL", "isValidURI");
-lazyRequire(this, "./deprecated/window-utils", "WindowTracker", "browserWindowIterator");
-lazyRequire(this, "./window/utils", "isBrowser", "getInnerId");
-lazyRequire(this, "./util/match-pattern", "MatchPattern");
-const { EventTarget } = require("./event/target");
-lazyRequire(this, './event/core', "emit");
-const { when } = require('./system/unload');
-const { contract: loaderContract } = require('./content/loader');
-const { omit } = require('./util/object');
-lazyRequireModule(this, './self', "self");
-const { remoteRequire, processes } = require('./remote/parent');
-remoteRequire('sdk/content/context-menu');
-
-// All user items we add have this class.
-const ITEM_CLASS = "addon-context-menu-item";
-
-// Items in the top-level context menu also have this class.
-const TOPLEVEL_ITEM_CLASS = "addon-context-menu-item-toplevel";
-
-// Items in the overflow submenu also have this class.
-const OVERFLOW_ITEM_CLASS = "addon-context-menu-item-overflow";
-
-// The class of the menu separator that separates standard context menu items
-// from our user items.
-const SEPARATOR_CLASS = "addon-context-menu-separator";
-
-// If more than this number of items are added to the context menu, all items
-// overflow into a "Jetpack" submenu.
-const OVERFLOW_THRESH_DEFAULT = 10;
-const OVERFLOW_THRESH_PREF =
-  "extensions.addon-sdk.context-menu.overflowThreshold";
-
-// The label of the overflow sub-xul:menu.
-//
-// TODO: Localize these.
-const OVERFLOW_MENU_LABEL = "Add-ons";
-const OVERFLOW_MENU_ACCESSKEY = "A";
-
-// The class of the overflow sub-xul:menu.
-const OVERFLOW_MENU_CLASS = "addon-content-menu-overflow-menu";
-
-// The class of the overflow submenu's xul:menupopup.
-const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup";
-
-// Holds private properties for API objects
-var internal = ns();
-
-// A little hacky but this is the last process ID that last opened the context
-// menu
-var lastContextProcessId = null;
-
-var uuidModule = require('./util/uuid');
-function uuid() {
-  return uuidModule.uuid().toString();
-}
-
-function getScheme(spec) {
-  try {
-    return URL(spec).scheme;
-  }
-  catch(e) {
-    return null;
-  }
-}
-
-var Context = Class({
-  initialize: function() {
-    internal(this).id = uuid();
-  },
-
-  // Returns the node that made this context current
-  adjustPopupNode: function adjustPopupNode(popupNode) {
-    return popupNode;
-  },
-
-  // Returns whether this context is current for the current node
-  isCurrent: function isCurrent(state) {
-    return state;
-  }
-});
-
-// Matches when the context-clicked node doesn't have any of
-// NON_PAGE_CONTEXT_ELTS in its ancestors
-var PageContext = Class({
-  extends: Context,
-
-  serialize: function() {
-    return {
-      id: internal(this).id,
-      type: "PageContext",
-      args: []
-    }
-  }
-});
-exports.PageContext = PageContext;
-
-// Matches when there is an active selection in the window
-var SelectionContext = Class({
-  extends: Context,
-
-  serialize: function() {
-    return {
-      id: internal(this).id,
-      type: "SelectionContext",
-      args: []
-    }
-  }
-});
-exports.SelectionContext = SelectionContext;
-
-// Matches when the context-clicked node or any of its ancestors matches the
-// selector given
-var SelectorContext = Class({
-  extends: Context,
-
-  initialize: function initialize(selector) {
-    Context.prototype.initialize.call(this);
-    let options = validateOptions({ selector: selector }, {
-      selector: {
-        is: ["string"],
-        msg: "selector must be a string."
-      }
-    });
-    internal(this).selector = options.selector;
-  },
-
-  serialize: function() {
-    return {
-      id: internal(this).id,
-      type: "SelectorContext",
-      args: [internal(this).selector]
-    }
-  }
-});
-exports.SelectorContext = SelectorContext;
-
-// Matches when the page url matches any of the patterns given
-var URLContext = Class({
-  extends: Context,
-
-  initialize: function initialize(patterns) {
-    Context.prototype.initialize.call(this);
-    patterns = Array.isArray(patterns) ? patterns : [patterns];
-
-    try {
-      internal(this).patterns = patterns.map(p => new MatchPattern(p));
-    }
-    catch (err) {
-      throw new Error("Patterns must be a string, regexp or an array of " +
-                      "strings or regexps: " + err);
-    }
-  },
-
-  isCurrent: function isCurrent(url) {
-    return internal(this).patterns.some(p => p.test(url));
-  },
-
-  serialize: function() {
-    return {
-      id: internal(this).id,
-      type: "URLContext",
-      args: []
-    }
-  }
-});
-exports.URLContext = URLContext;
-
-// Matches when the user-supplied predicate returns true
-var PredicateContext = Class({
-  extends: Context,
-
-  initialize: function initialize(predicate) {
-    Context.prototype.initialize.call(this);
-    let options = validateOptions({ predicate: predicate }, {
-      predicate: {
-        is: ["function"],
-        msg: "predicate must be a function."
-      }
-    });
-    internal(this).predicate = options.predicate;
-  },
-
-  isCurrent: function isCurrent(state) {
-    return internal(this).predicate(state);
-  },
-
-  serialize: function() {
-    return {
-      id: internal(this).id,
-      type: "PredicateContext",
-      args: []
-    }
-  }
-});
-exports.PredicateContext = PredicateContext;
-
-function removeItemFromArray(array, item) {
-  return array.filter(i => i !== item);
-}
-
-// Converts anything that isn't false, null or undefined into a string
-function stringOrNull(val) {
-  return val ? String(val) : val;
-}
-
-// Shared option validation rules for Item, Menu, and Separator
-var baseItemRules = {
-  parentMenu: {
-    is: ["object", "undefined"],
-    ok: function (v) {
-      if (!v)
-        return true;
-      return (v instanceof ItemContainer) || (v instanceof Menu);
-    },
-    msg: "parentMenu must be a Menu or not specified."
-  },
-  context: {
-    is: ["undefined", "object", "array"],
-    ok: function (v) {
-      if (!v)
-        return true;
-      let arr = Array.isArray(v) ? v : [v];
-      return arr.every(o => o instanceof Context);
-    },
-    msg: "The 'context' option must be a Context object or an array of " +
-         "Context objects."
-  },
-  onMessage: {
-    is: ["function", "undefined"]
-  },
-  contentScript: loaderContract.rules.contentScript,
-  contentScriptFile: loaderContract.rules.contentScriptFile
-};
-
-var labelledItemRules =  mix(baseItemRules, {
-  label: {
-    map: stringOrNull,
-    is: ["string"],
-    ok: v => !!v,
-    msg: "The item must have a non-empty string label."
-  },
-  accesskey: {
-    map: stringOrNull,
-    is: ["string", "undefined", "null"],
-    ok: (v) => {
-      if (!v) {
-        return true;
-      }
-      return typeof v == "string" && v.length === 1;
-    },
-    msg: "The item must have a single character accesskey, or no accesskey."
-  },
-  image: {
-    map: stringOrNull,
-    is: ["string", "undefined", "null"],
-    ok: function (url) {
-      if (!url)
-        return true;
-      return isValidURI(url);
-    },
-    msg: "Image URL validation failed"
-  }
-});
-
-// Additional validation rules for Item
-var itemRules = mix(labelledItemRules, {
-  data: {
-    map: stringOrNull,
-    is: ["string", "undefined", "null"]
-  }
-});
-
-// Additional validation rules for Menu
-var menuRules = mix(labelledItemRules, {
-  items: {
-    is: ["array", "undefined"],
-    ok: function (v) {
-      if (!v)
-        return true;
-      return v.every(function (item) {
-        return item instanceof BaseItem;
-      });
-    },
-    msg: "items must be an array, and each element in the array must be an " +
-         "Item, Menu, or Separator."
-  }
-});
-
-// Returns true if any contexts match. If there are no contexts then a
-// PageContext is tested instead
-function hasMatchingContext(contexts, addonInfo) {
-  for (let context of contexts) {
-    if (!(internal(context).id in addonInfo.contextStates)) {
-      console.error("Missing state for context " + internal(context).id + " this is an error in the SDK modules.");
-      return false;
-    }
-    if (!context.isCurrent(addonInfo.contextStates[internal(context).id]))
-      return false;
-  }
-
-  return true;
-}
-
-// Tests whether an item should be visible or not based on its contexts and
-// content scripts
-function isItemVisible(item, addonInfo, usePageWorker) {
-  if (!item.context.length) {
-    if (!addonInfo.hasWorker)
-      return usePageWorker ? addonInfo.pageContext : true;
-  }
-
-  if (!hasMatchingContext(item.context, addonInfo))
-    return false;
-
-  let context = addonInfo.workerContext;
-  if (typeof(context) === "string" && context != "")
-    item.label = context;
-
-  return !!context;
-}
-
-// Called when an item is clicked to send out click events to the content
-// scripts
-function itemActivated(item, clickedNode) {
-  let items = [internal(item).id];
-  let data = item.data;
-
-  while (item.parentMenu) {
-    item = item.parentMenu;
-    items.push(internal(item).id);
-  }
-
-  let process = processes.getById(lastContextProcessId);
-  if (process)
-    process.port.emit('sdk/contextmenu/activateitems', items, data);
-}
-
-function serializeItem(item) {
-  return {
-    id: internal(item).id,
-    contexts: item.context.map(c => c.serialize()),
-    contentScript: item.contentScript,
-    contentScriptFile: item.contentScriptFile,
-  };
-}
-
-// All things that appear in the context menu extend this
-var BaseItem = Class({
-  initialize: function initialize() {
-    internal(this).id = uuid();
-
-    internal(this).contexts = [];
-    if ("context" in internal(this).options && internal(this).options.context) {
-      let contexts = internal(this).options.context;
-      if (Array.isArray(contexts)) {
-        for (let context of contexts)
-          internal(this).contexts.push(context);
-      }
-      else {
-        internal(this).contexts.push(contexts);
-      }
-    }
-
-    let parentMenu = internal(this).options.parentMenu;
-    if (!parentMenu)
-      parentMenu = contentContextMenu;
-
-    parentMenu.addItem(this);
-
-    Object.defineProperty(this, "contentScript", {
-      enumerable: true,
-      value: internal(this).options.contentScript
-    });
-
-    // Resolve URIs here as tests may have overriden self
-    let files = internal(this).options.contentScriptFile;
-    if (files) {
-      if (!Array.isArray(files))
-        files = [files];
-      files = files.map(self.data.url);
-    }
-    internal(this).options.contentScriptFile = files;
-    Object.defineProperty(this, "contentScriptFile", {
-      enumerable: true,
-      value: internal(this).options.contentScriptFile
-    });
-
-    // Notify all frames of this new item
-    sendItems([serializeItem(this)]);
-  },
-
-  destroy: function destroy() {
-    if (internal(this).destroyed)
-      return;
-
-    // Tell all existing frames that this item has been destroyed
-    processes.port.emit("sdk/contextmenu/destroyitems", [internal(this).id]);
-
-    if (this.parentMenu)
-      this.parentMenu.removeItem(this);
-
-    internal(this).destroyed = true;
-  },
-
-  get context() {
-    let contexts = internal(this).contexts.slice(0);
-    contexts.add = (context) => {
-      internal(this).contexts.push(context);
-      // Notify all frames that this item has changed
-      sendItems([serializeItem(this)]);
-    };
-    contexts.remove = (context) => {
-      internal(this).contexts = internal(this).contexts.filter(c => {
-        return c != context;
-      });
-      // Notify all frames that this item has changed
-      sendItems([serializeItem(this)]);
-    };
-    return contexts;
-  },
-
-  set context(val) {
-    internal(this).contexts = val.slice(0);
-    // Notify all frames that this item has changed
-    sendItems([serializeItem(this)]);
-  },
-
-  get parentMenu() {
-    return internal(this).parentMenu;
-  },
-});
-
-function workerMessageReceived(process, id, args) {
-  if (internal(this).id != id)
-    return;
-
-  emit(this, ...JSON.parse(args));
-}
-
-// All things that have a label on the context menu extend this
-var LabelledItem = Class({
-  extends: BaseItem,
-  implements: [ EventTarget ],
-
-  initialize: function initialize(options) {
-    BaseItem.prototype.initialize.call(this);
-    EventTarget.prototype.initialize.call(this, options);
-
-    internal(this).messageListener = workerMessageReceived.bind(this);
-    processes.port.on('sdk/worker/event', internal(this).messageListener);
-  },
-
-  destroy: function destroy() {
-    if (internal(this).destroyed)
-      return;
-
-    processes.port.off('sdk/worker/event', internal(this).messageListener);
-
-    BaseItem.prototype.destroy.call(this);
-  },
-
-  get label() {
-    return internal(this).options.label;
-  },
-
-  set label(val) {
-    internal(this).options.label = val;
-
-    MenuManager.updateItem(this);
-  },
-
-  get accesskey() {
-    return internal(this).options.accesskey;
-  },
-
-  set accesskey(val) {
-    internal(this).options.accesskey = val;
-
-    MenuManager.updateItem(this);
-  },
-
-  get image() {
-    return internal(this).options.image;
-  },
-
-  set image(val) {
-    internal(this).options.image = val;
-
-    MenuManager.updateItem(this);
-  },
-
-  get data() {
-    return internal(this).options.data;
-  },
-
-  set data(val) {
-    internal(this).options.data = val;
-  }
-});
-
-var Item = Class({
-  extends: LabelledItem,
-
-  initialize: function initialize(options) {
-    internal(this).options = validateOptions(options, itemRules);
-
-    LabelledItem.prototype.initialize.call(this, options);
-  },
-
-  toString: function toString() {
-    return "[object Item \"" + this.label + "\"]";
-  },
-
-  get data() {
-    return internal(this).options.data;
-  },
-
-  set data(val) {
-    internal(this).options.data = val;
-
-    MenuManager.updateItem(this);
-  },
-});
-exports.Item = Item;
-
-var ItemContainer = Class({
-  initialize: function initialize() {
-    internal(this).children = [];
-  },
-
-  destroy: function destroy() {
-    // Destroys the entire hierarchy
-    for (let item of internal(this).children)
-      item.destroy();
-  },
-
-  addItem: function addItem(item) {
-    let oldParent = item.parentMenu;
-
-    // Don't just call removeItem here as that would remove the corresponding
-    // UI element which is more costly than just moving it to the right place
-    if (oldParent)
-      internal(oldParent).children = removeItemFromArray(internal(oldParent).children, item);
-
-    let after = null;
-    let children = internal(this).children;
-    if (children.length > 0)
-      after = children[children.length - 1];
-
-    children.push(item);
-    internal(item).parentMenu = this;
-
-    // If there was an old parent then we just have to move the item, otherwise
-    // it needs to be created
-    if (oldParent)
-      MenuManager.moveItem(item, after);
-    else
-      MenuManager.createItem(item, after);
-  },
-
-  removeItem: function removeItem(item) {
-    // If the item isn't a child of this menu then ignore this call
-    if (item.parentMenu !== this)
-      return;
-
-    MenuManager.removeItem(item);
-
-    internal(this).children = removeItemFromArray(internal(this).children, item);
-    internal(item).parentMenu = null;
-  },
-
-  get items() {
-    return internal(this).children.slice(0);
-  },
-
-  set items(val) {
-    // Validate the arguments before making any changes
-    if (!Array.isArray(val))
-      throw new Error(menuOptionRules.items.msg);
-
-    for (let item of val) {
-      if (!(item instanceof BaseItem))
-        throw new Error(menuOptionRules.items.msg);
-    }
-
-    // Remove the old items and add the new ones
-    for (let item of internal(this).children)
-      this.removeItem(item);
-
-    for (let item of val)
-      this.addItem(item);
-  },
-});
-
-var Menu = Class({
-  extends: LabelledItem,
-  implements: [ItemContainer],
-
-  initialize: function initialize(options) {
-    internal(this).options = validateOptions(options, menuRules);
-
-    LabelledItem.prototype.initialize.call(this, options);
-    ItemContainer.prototype.initialize.call(this);
-
-    if (internal(this).options.items) {
-      for (let item of internal(this).options.items)
-        this.addItem(item);
-    }
-  },
-
-  destroy: function destroy() {
-    ItemContainer.prototype.destroy.call(this);
-    LabelledItem.prototype.destroy.call(this);
-  },
-
-  toString: function toString() {
-    return "[object Menu \"" + this.label + "\"]";
-  },
-});
-exports.Menu = Menu;
-
-var Separator = Class({
-  extends: BaseItem,
-
-  initialize: function initialize(options) {
-    internal(this).options = validateOptions(options, baseItemRules);
-
-    BaseItem.prototype.initialize.call(this);
-  },
-
-  toString: function toString() {
-    return "[object Separator]";
-  }
-});
-exports.Separator = Separator;
-
-// Holds items for the content area context menu
-var contentContextMenu = ItemContainer();
-exports.contentContextMenu = contentContextMenu;
-
-function getContainerItems(container) {
-  let items = [];
-  for (let item of internal(container).children) {
-    items.push(serializeItem(item));
-    if (item instanceof Menu)
-      items = items.concat(getContainerItems(item));
-  }
-  return items;
-}
-
-// Notify all frames of these new or changed items
-function sendItems(items) {
-  processes.port.emit("sdk/contextmenu/createitems", items);
-}
-
-// Called when a new process is created and needs to get the current list of items
-function remoteItemRequest(process) {
-  let items = getContainerItems(contentContextMenu);
-  if (items.length == 0)
-    return;
-
-  process.port.emit("sdk/contextmenu/createitems", items);
-}
-processes.forEvery(remoteItemRequest);
-
-when(function() {
-  contentContextMenu.destroy();
-});
-
-// App specific UI code lives here, it should handle populating the context
-// menu and passing clicks etc. through to the items.
-
-function countVisibleItems(nodes) {
-  return Array.reduce(nodes, function(sum, node) {
-    return node.hidden ? sum : sum + 1;
-  }, 0);
-}
-
-var MenuWrapper = Class({
-  initialize: function initialize(winWrapper, items, contextMenu) {
-    this.winWrapper = winWrapper;
-    this.window = winWrapper.window;
-    this.items = items;
-    this.contextMenu = contextMenu;
-    this.populated = false;
-    this.menuMap = new Map();
-
-    // updateItemVisibilities will run first, updateOverflowState will run after
-    // all other instances of this module have run updateItemVisibilities
-    this._updateItemVisibilities = this.updateItemVisibilities.bind(this);
-    this.contextMenu.addEventListener("popupshowing", this._updateItemVisibilities, true);
-    this._updateOverflowState = this.updateOverflowState.bind(this);
-    this.contextMenu.addEventListener("popupshowing", this._updateOverflowState);
-  },
-
-  destroy: function destroy() {
-    this.contextMenu.removeEventListener("popupshowing", this._updateOverflowState);
-    this.contextMenu.removeEventListener("popupshowing", this._updateItemVisibilities, true);
-
-    if (!this.populated)
-      return;
-
-    // If we're getting unloaded at runtime then we must remove all the
-    // generated XUL nodes
-    let oldParent = null;
-    for (let item of internal(this.items).children) {
-      let xulNode = this.getXULNodeForItem(item);
-      oldParent = xulNode.parentNode;
-      oldParent.removeChild(xulNode);
-    }
-
-    if (oldParent)
-      this.onXULRemoved(oldParent);
-  },
-
-  get separator() {
-    return this.contextMenu.querySelector("." + SEPARATOR_CLASS);
-  },
-
-  get overflowMenu() {
-    return this.contextMenu.querySelector("." + OVERFLOW_MENU_CLASS);
-  },
-
-  get overflowPopup() {
-    return this.contextMenu.querySelector("." + OVERFLOW_POPUP_CLASS);
-  },
-
-  get topLevelItems() {
-    return this.contextMenu.querySelectorAll("." + TOPLEVEL_ITEM_CLASS);
-  },
-
-  get overflowItems() {
-    return this.contextMenu.querySelectorAll("." + OVERFLOW_ITEM_CLASS);
-  },
-
-  getXULNodeForItem: function getXULNodeForItem(item) {
-    return this.menuMap.get(item);
-  },
-
-  // Recurses through the item hierarchy creating XUL nodes for everything
-  populate: function populate(menu) {
-    for (let i = 0; i < internal(menu).children.length; i++) {
-      let item = internal(menu).children[i];
-      let after = i === 0 ? null : internal(menu).children[i - 1];
-      this.createItem(item, after);
-
-      if (item instanceof Menu)
-        this.populate(item);
-    }
-  },
-
-  // Recurses through the menu setting the visibility of items. Returns true
-  // if any of the items in this menu were visible
-  setVisibility: function setVisibility(menu, addonInfo, usePageWorker) {
-    let anyVisible = false;
-
-    for (let item of internal(menu).children) {
-      let visible = isItemVisible(item, addonInfo[internal(item).id], usePageWorker);
-
-      // Recurse through Menus, if none of the sub-items were visible then the
-      // menu is hidden too.
-      if (visible && (item instanceof Menu))
-        visible = this.setVisibility(item, addonInfo, false);
-
-      let xulNode = this.getXULNodeForItem(item);
-      xulNode.hidden = !visible;
-
-      anyVisible = anyVisible || visible;
-    }
-
-    return anyVisible;
-  },
-
-  // Works out where to insert a XUL node for an item in a browser window
-  insertIntoXUL: function insertIntoXUL(item, node, after) {
-    let menupopup = null;
-    let before = null;
-
-    let menu = item.parentMenu;
-    if (menu === this.items) {
-      // Insert into the overflow popup if it exists, otherwise the normal
-      // context menu
-      menupopup = this.overflowPopup;
-      if (!menupopup)
-        menupopup = this.contextMenu;
-    }
-    else {
-      let xulNode = this.getXULNodeForItem(menu);
-      menupopup = xulNode.firstChild;
-    }
-
-    if (after) {
-      let afterNode = this.getXULNodeForItem(after);
-      before = afterNode.nextSibling;
-    }
-    else if (menupopup === this.contextMenu) {
-      let topLevel = this.topLevelItems;
-      if (topLevel.length > 0)
-        before = topLevel[topLevel.length - 1].nextSibling;
-      else
-        before = this.separator.nextSibling;
-    }
-
-    menupopup.insertBefore(node, before);
-  },
-
-  // Sets the right class for XUL nodes
-  updateXULClass: function updateXULClass(xulNode) {
-    if (xulNode.parentNode == this.contextMenu)
-      xulNode.classList.add(TOPLEVEL_ITEM_CLASS);
-    else
-      xulNode.classList.remove(TOPLEVEL_ITEM_CLASS);
-
-    if (xulNode.parentNode == this.overflowPopup)
-      xulNode.classList.add(OVERFLOW_ITEM_CLASS);
-    else
-      xulNode.classList.remove(OVERFLOW_ITEM_CLASS);
-  },
-
-  // Creates a XUL node for an item
-  createItem: function createItem(item, after) {
-    if (!this.populated)
-      return;
-
-    // Create the separator if it doesn't already exist
-    if (!this.separator) {
-      let separator = this.window.document.createElement("menuseparator");
-      separator.setAttribute("class", SEPARATOR_CLASS);
-
-      // Insert before the separator created by the old context-menu if it
-      // exists to avoid bug 832401
-      let oldSeparator = this.window.document.getElementById("jetpack-context-menu-separator");
-      if (oldSeparator && oldSeparator.parentNode != this.contextMenu)
-        oldSeparator = null;
-      this.contextMenu.insertBefore(separator, oldSeparator);
-    }
-
-    let type = "menuitem";
-    if (item instanceof Menu)
-      type = "menu";
-    else if (item instanceof Separator)
-      type = "menuseparator";
-
-    let xulNode = this.window.document.createElement(type);
-    xulNode.setAttribute("class", ITEM_CLASS);
-    if (item instanceof LabelledItem) {
-      xulNode.setAttribute("label", item.label);
-      if (item.accesskey)
-        xulNode.setAttribute("accesskey", item.accesskey);
-      if (item.image) {
-        xulNode.setAttribute("image", item.image);
-        if (item instanceof Menu)
-          xulNode.classList.add("menu-iconic");
-        else
-          xulNode.classList.add("menuitem-iconic");
-      }
-      if (item.data)
-        xulNode.setAttribute("value", item.data);
-
-      let self = this;
-      xulNode.addEventListener("command", function(event) {
-        // Only care about clicks directly on this item
-        if (event.target !== xulNode)
-          return;
-
-        itemActivated(item, xulNode);
-      });
-    }
-
-    this.insertIntoXUL(item, xulNode, after);
-    this.updateXULClass(xulNode);
-    xulNode.data = item.data;
-
-    if (item instanceof Menu) {
-      let menupopup = this.window.document.createElement("menupopup");
-      xulNode.appendChild(menupopup);
-    }
-
-    this.menuMap.set(item, xulNode);
-  },
-
-  // Updates the XUL node for an item in this window
-  updateItem: function updateItem(item) {
-    if (!this.populated)
-      return;
-
-    let xulNode = this.getXULNodeForItem(item);
-
-    // TODO figure out why this requires setAttribute
-    xulNode.setAttribute("label", item.label);
-    xulNode.setAttribute("accesskey", item.accesskey || "");
-
-    if (item.image) {
-      xulNode.setAttribute("image", item.image);
-      if (item instanceof Menu)
-        xulNode.classList.add("menu-iconic");
-      else
-        xulNode.classList.add("menuitem-iconic");
-    }
-    else {
-      xulNode.removeAttribute("image");
-      xulNode.classList.remove("menu-iconic");
-      xulNode.classList.remove("menuitem-iconic");
-    }
-
-    if (item.data)
-      xulNode.setAttribute("value", item.data);
-    else
-      xulNode.removeAttribute("value");
-  },
-
-  // Moves the XUL node for an item in this window to its new place in the
-  // hierarchy
-  moveItem: function moveItem(item, after) {
-    if (!this.populated)
-      return;
-
-    let xulNode = this.getXULNodeForItem(item);
-    let oldParent = xulNode.parentNode;
-
-    this.insertIntoXUL(item, xulNode, after);
-    this.updateXULClass(xulNode);
-    this.onXULRemoved(oldParent);
-  },
-
-  // Removes the XUL nodes for an item in every window we've ever populated.
-  removeItem: function removeItem(item) {
-    if (!this.populated)
-      return;
-
-    let xulItem = this.getXULNodeForItem(item);
-
-    let oldParent = xulItem.parentNode;
-
-    oldParent.removeChild(xulItem);
-    this.menuMap.delete(item);
-
-    this.onXULRemoved(oldParent);
-  },
-
-  // Called when any XUL nodes have been removed from a menupopup. This handles
-  // making sure the separator and overflow are correct
-  onXULRemoved: function onXULRemoved(parent) {
-    if (parent == this.contextMenu) {
-      let toplevel = this.topLevelItems;
-
-      // If there are no more items then remove the separator
-      if (toplevel.length == 0) {
-        let separator = this.separator;
-        if (separator)
-          separator.remove();
-      }
-    }
-    else if (parent == this.overflowPopup) {
-      // If there are no more items then remove the overflow menu and separator
-      if (parent.childNodes.length == 0) {
-        let separator = this.separator;
-        separator.remove();
-        this.contextMenu.removeChild(parent.parentNode);
-      }
-    }
-  },
-
-  // Recurses through all the items owned by this module and sets their hidden
-  // state
-  updateItemVisibilities: function updateItemVisibilities(event) {
-    try {
-      if (event.type != "popupshowing")
-        return;
-      if (event.target != this.contextMenu)
-        return;
-
-      if (internal(this.items).children.length == 0)
-        return;
-
-      if (!this.populated) {
-        this.populated = true;
-        this.populate(this.items);
-      }
-
-      let mainWindow = event.target.ownerGlobal;
-      this.contextMenuContentData = mainWindow.gContextMenuContentData
-      if (!(self.id in this.contextMenuContentData.addonInfo)) {
-        console.warn("No context menu state data was provided.");
-        return;
-      }
-      let addonInfo = this.contextMenuContentData.addonInfo[self.id];
-      lastContextProcessId = addonInfo.processID;
-      this.setVisibility(this.items, addonInfo.items, true);
-    }
-    catch (e) {
-      console.exception(e);
-    }
-  },
-
-  // Counts the number of visible items across all modules and makes sure they
-  // are in the right place between the top level context menu and the overflow
-  // menu
-  updateOverflowState: function updateOverflowState(event) {
-    try {
-      if (event.type != "popupshowing")
-        return;
-      if (event.target != this.contextMenu)
-        return;
-
-      // The main items will be in either the top level context menu or the
-      // overflow menu at this point. Count the visible ones and if they are in
-      // the wrong place move them
-      let toplevel = this.topLevelItems;
-      let overflow = this.overflowItems;
-      let visibleCount = countVisibleItems(toplevel) +
-                         countVisibleItems(overflow);
-
-      if (visibleCount == 0) {
-        let separator = this.separator;
-        if (separator)
-          separator.hidden = true;
-        let overflowMenu = this.overflowMenu;
-        if (overflowMenu)
-          overflowMenu.hidden = true;
-      }
-      else if (visibleCount > MenuManager.overflowThreshold) {
-        this.separator.hidden = false;
-        let overflowPopup = this.overflowPopup;
-        if (overflowPopup)
-          overflowPopup.parentNode.hidden = false;
-
-        if (toplevel.length > 0) {
-          // The overflow menu shouldn't exist here but let's play it safe
-          if (!overflowPopup) {
-            let overflowMenu = this.window.document.createElement("menu");
-            overflowMenu.setAttribute("class", OVERFLOW_MENU_CLASS);
-            overflowMenu.setAttribute("label", OVERFLOW_MENU_LABEL);
-            overflowMenu.setAttribute("accesskey", OVERFLOW_MENU_ACCESSKEY);
-            this.contextMenu.insertBefore(overflowMenu, this.separator.nextSibling);
-
-            overflowPopup = this.window.document.createElement("menupopup");
-            overflowPopup.setAttribute("class", OVERFLOW_POPUP_CLASS);
-            overflowMenu.appendChild(overflowPopup);
-          }
-
-          for (let xulNode of toplevel) {
-            overflowPopup.appendChild(xulNode);
-            this.updateXULClass(xulNode);
-          }
-        }
-      }
-      else {
-        this.separator.hidden = false;
-
-        if (overflow.length > 0) {
-          // Move all the overflow nodes out of the overflow menu and position
-          // them immediately before it
-          for (let xulNode of overflow) {
-            this.contextMenu.insertBefore(xulNode, xulNode.parentNode.parentNode);
-            this.updateXULClass(xulNode);
-          }
-          this.contextMenu.removeChild(this.overflowMenu);
-        }
-      }
-    }
-    catch (e) {
-      console.exception(e);
-    }
-  }
-});
-
-// This wraps every window that we've seen
-var WindowWrapper = Class({
-  initialize: function initialize(window) {
-    this.window = window;
-    this.menus = [
-      new MenuWrapper(this, contentContextMenu, window.document.getElementById("contentAreaContextMenu")),
-    ];
-  },
-
-  destroy: function destroy() {
-    for (let menuWrapper of this.menus)
-      menuWrapper.destroy();
-  },
-
-  getMenuWrapperForItem: function getMenuWrapperForItem(item) {
-    let root = item.parentMenu;
-    while (root.parentMenu)
-      root = root.parentMenu;
-
-    for (let wrapper of this.menus) {
-      if (wrapper.items === root)
-        return wrapper;
-    }
-
-    return null;
-  }
-});
-
-var MenuManager = {
-  windowMap: new Map(),
-
-  get overflowThreshold() {
-    let prefs = require("./preferences/service");
-    return prefs.get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
-  },
-
-  // When a new window is added start watching it for context menu shows
-  onTrack: function onTrack(window) {
-    if (!isBrowser(window))
-      return;
-
-    // Generally shouldn't happen, but just in case
-    if (this.windowMap.has(window)) {
-      console.warn("Already seen this window");
-      return;
-    }
-
-    let winWrapper = WindowWrapper(window);
-    this.windowMap.set(window, winWrapper);
-  },
-
-  onUntrack: function onUntrack(window) {
-    if (!isBrowser(window))
-      return;
-
-    let winWrapper = this.windowMap.get(window);
-    // This shouldn't happen but protect against it anyway
-    if (!winWrapper)
-      return;
-    winWrapper.destroy();
-
-    this.windowMap.delete(window);
-  },
-
-  // Creates a XUL node for an item in every window we've already populated
-  createItem: function createItem(item, after) {
-    for (let [window, winWrapper] of this.windowMap) {
-      let menuWrapper = winWrapper.getMenuWrapperForItem(item);
-      if (menuWrapper)
-        menuWrapper.createItem(item, after);
-    }
-  },
-
-  // Updates the XUL node for an item in every window we've already populated
-  updateItem: function updateItem(item) {
-    for (let [window, winWrapper] of this.windowMap) {
-      let menuWrapper = winWrapper.getMenuWrapperForItem(item);
-      if (menuWrapper)
-        menuWrapper.updateItem(item);
-    }
-  },
-
-  // Moves the XUL node for an item in every window we've ever populated to its
-  // new place in the hierarchy
-  moveItem: function moveItem(item, after) {
-    for (let [window, winWrapper] of this.windowMap) {
-      let menuWrapper = winWrapper.getMenuWrapperForItem(item);
-      if (menuWrapper)
-        menuWrapper.moveItem(item, after);
-    }
-  },
-
-  // Removes the XUL nodes for an item in every window we've ever populated.
-  removeItem: function removeItem(item) {
-    for (let [window, winWrapper] of this.windowMap) {
-      let menuWrapper = winWrapper.getMenuWrapperForItem(item);
-      if (menuWrapper)
-        menuWrapper.removeItem(item);
-    }
-  }
-};
-
-WindowTracker(MenuManager);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/context-menu/context.js
+++ /dev/null
@@ -1,146 +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/. */
-
-const { Class } = require("../core/heritage");
-lazyRequire(this, "../util/match-pattern", "MatchPattern");
-const readers = require("./readers");
-
-// Context class is required to implement a single `isCurrent(target)` method
-// that must return boolean value indicating weather given target matches a
-// context or not. Most context implementations below will have an associated
-// reader that way context implementation can setup a reader to extract necessary
-// information to make decision if target is matching a context.
-const Context = Class({
-  isRequired: false,
-  isCurrent(target) {
-    throw Error("Context class must implement isCurrent(target) method");
-  },
-  get required() {
-    Object.defineProperty(this, "required", {
-      value: Object.assign(Object.create(Object.getPrototypeOf(this)),
-                           this,
-                           {isRequired: true})
-    });
-    return this.required;
-  }
-});
-Context.required = function(...params) {
-  return Object.assign(new this(...params), {isRequired: true});
-};
-exports.Context = Context;
-
-
-// Next few context implementations use an associated reader to extract info
-// from the context target and story it to a private symbol associtaed with
-// a context implementation. That way name collisions are avoided while required
-// information is still carried along.
-const isPage = Symbol("context/page?")
-const PageContext = Class({
-  extends: Context,
-  read: {[isPage]: new readers.isPage()},
-  isCurrent: target => target[isPage]
-});
-exports.Page = PageContext;
-
-const isFrame = Symbol("context/frame?");
-const FrameContext = Class({
-  extends: Context,
-  read: {[isFrame]: new readers.isFrame()},
-  isCurrent: target => target[isFrame]
-});
-exports.Frame = FrameContext;
-
-const selection = Symbol("context/selection")
-const SelectionContext = Class({
-  read: {[selection]: new readers.Selection()},
-  isCurrent: target => !!target[selection]
-});
-exports.Selection = SelectionContext;
-
-const link = Symbol("context/link");
-const LinkContext = Class({
-  extends: Context,
-  read: {[link]: new readers.LinkURL()},
-  isCurrent: target => !!target[link]
-});
-exports.Link = LinkContext;
-
-const isEditable = Symbol("context/editable?")
-const EditableContext = Class({
-  extends: Context,
-  read: {[isEditable]: new readers.isEditable()},
-  isCurrent: target => target[isEditable]
-});
-exports.Editable = EditableContext;
-
-
-const mediaType = Symbol("context/mediaType")
-
-const ImageContext = Class({
-  extends: Context,
-  read: {[mediaType]: new readers.MediaType()},
-  isCurrent: target => target[mediaType] === "image"
-});
-exports.Image = ImageContext;
-
-
-const VideoContext = Class({
-  extends: Context,
-  read: {[mediaType]: new readers.MediaType()},
-  isCurrent: target => target[mediaType] === "video"
-});
-exports.Video = VideoContext;
-
-
-const AudioContext = Class({
-  extends: Context,
-  read: {[mediaType]: new readers.MediaType()},
-  isCurrent: target => target[mediaType] === "audio"
-});
-exports.Audio = AudioContext;
-
-const isSelectorMatch = Symbol("context/selector/mathches?")
-const SelectorContext = Class({
-  extends: Context,
-  initialize(selector) {
-    this.selector = selector;
-    // Each instance of selector context will need to store read
-    // data into different field, so that case with multilpe selector
-    // contexts won't cause a conflicts.
-    this[isSelectorMatch] = Symbol(selector);
-    this.read = {[this[isSelectorMatch]]: new readers.SelectorMatch(selector)};
-  },
-  isCurrent(target) {
-    return target[this[isSelectorMatch]];
-  }
-});
-exports.Selector = SelectorContext;
-
-const url = Symbol("context/url");
-const URLContext = Class({
-  extends: Context,
-  initialize(pattern) {
-    this.pattern = new MatchPattern(pattern);
-  },
-  read: {[url]: new readers.PageURL()},
-  isCurrent(target) {
-    return this.pattern.test(target[url]);
-  }
-});
-exports.URL = URLContext;
-
-var PredicateContext = Class({
-  extends: Context,
-  initialize(isMatch) {
-    if (typeof(isMatch) !== "function") {
-      throw TypeError("Predicate context mus be passed a function");
-    }
-
-    this.isMatch = isMatch
-  },
-  isCurrent(target) {
-    return this.isMatch(target);
-  }
-});
-exports.Predicate = PredicateContext;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/context-menu/core.js
+++ /dev/null
@@ -1,384 +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 Contexts = require("./context");
-const Readers = require("./readers");
-const Component = require("../ui/component");
-const { Class } = require("../core/heritage");
-const { map, filter, object, reduce, keys, symbols,
-        pairs, values, each, some, isEvery, count } = require("../util/sequence");
-const { loadModule } = require("framescript/manager");
-const { Cu, Cc, Ci } = require("chrome");
-const prefs = require("sdk/preferences/service");
-
-const globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]
-                              .getService(Ci.nsIMessageListenerManager);
-const preferencesService = Cc["@mozilla.org/preferences-service;1"].
-                            getService(Ci.nsIPrefService).
-                            getBranch(null);
-
-
-const readTable = Symbol("context-menu/read-table");
-const nameTable = Symbol("context-menu/name-table");
-const onContext = Symbol("context-menu/on-context");
-const isMatching = Symbol("context-menu/matching-handler?");
-
-exports.onContext = onContext;
-exports.readTable = readTable;
-exports.nameTable = nameTable;
-
-
-const propagateOnContext = (item, data) =>
-  each(child => child[onContext](data), item.state.children);
-
-const isContextMatch = item => !item[isMatching] || item[isMatching]();
-
-// For whatever reason addWeakMessageListener does not seems to work as our
-// instance seems to dropped even though it's alive. This is simple workaround
-// to avoid dead object excetptions.
-const WeakMessageListener = function(receiver, handler="receiveMessage") {
-  this.receiver = receiver
-  this.handler = handler
-};
-WeakMessageListener.prototype = {
-  constructor: WeakMessageListener,
-  receiveMessage(message) {
-    if (Cu.isDeadWrapper(this.receiver)) {
-      message.target.messageManager.removeMessageListener(message.name, this);
-    }
-    else {
-      this.receiver[this.handler](message);
-    }
-  }
-};
-
-const OVERFLOW_THRESH = "extensions.addon-sdk.context-menu.overflowThreshold";
-const onMessage = Symbol("context-menu/message-listener");
-const onPreferceChange = Symbol("context-menu/preference-change");
-const ContextMenuExtension = Class({
-  extends: Component,
-  initialize: Component,
-  setup() {
-    const messageListener = new WeakMessageListener(this, onMessage);
-    loadModule(globalMessageManager, "framescript/context-menu", true, "onContentFrame");
-    globalMessageManager.addMessageListener("sdk/context-menu/read", messageListener);
-    globalMessageManager.addMessageListener("sdk/context-menu/readers?", messageListener);
-
-    preferencesService.addObserver(OVERFLOW_THRESH, this);
-  },
-  observe(_, __, name) {
-    if (name === OVERFLOW_THRESH) {
-      const overflowThreshold = prefs.get(OVERFLOW_THRESH, 10);
-      this[Component.patch]({overflowThreshold});
-    }
-  },
-  [onMessage]({name, data, target}) {
-    if (name === "sdk/context-menu/read")
-      this[onContext]({target, data});
-    if (name === "sdk/context-menu/readers?")
-      target.messageManager.sendAsyncMessage("sdk/context-menu/readers",
-                                             JSON.parse(JSON.stringify(this.state.readers)));
-  },
-  [Component.initial](options={}, children) {
-    const element = options.element || null;
-    const target = options.target || null;
-    const readers = Object.create(null);
-    const users = Object.create(null);
-    const registry = new WeakSet();
-    const overflowThreshold = prefs.get(OVERFLOW_THRESH, 10);
-
-    return { target, children: [], readers, users, element,
-             registry, overflowThreshold };
-  },
-  [Component.isUpdated](before, after) {
-    // Update only if target changed, since there is no point in re-rendering
-    // when children are. Also new items added won't be in sync with a latest
-    // context target so we should really just render before drawing context
-    // menu.
-    return before.target !== after.target;
-  },
-  [Component.render]({element, children, overflowThreshold}) {
-    if (!element) return null;
-
-    const items = children.filter(isContextMatch);
-    const body = items.length === 0 ? items :
-                 items.length < overflowThreshold ? [new Separator(),
-                                                     ...items] :
-                 [{tagName: "menu",
-                   className: "sdk-context-menu-overflow-menu",
-                   label: "Add-ons",
-                   accesskey: "A",
-                   children: [{tagName: "menupopup",
-                               children: items}]}];
-    return {
-      element: element,
-      tagName: "menugroup",
-      style: "-moz-box-orient: vertical;",
-      className: "sdk-context-menu-extension",
-      children: body
-    }
-  },
-  // Adds / remove child to it's own list.
-  add(item) {
-    this[Component.patch]({children: this.state.children.concat(item)});
-  },
-  remove(item) {
-    this[Component.patch]({
-      children: this.state.children.filter(x => x !== item)
-    });
-  },
-  register(item) {
-    const { users, registry } = this.state;
-    if (registry.has(item)) return;
-    registry.add(item);
-
-    // Each (ContextHandler) item has a readTable that is a
-    // map of keys to readers extracting them from the content.
-    // During the registraction we update intrnal record of unique
-    // readers and users per reader. Most context will have a reader
-    // shared across all instances there for map of users per reader
-    // is stored separately from the reader so that removing reader
-    // will occur only when no users remain.
-    const table = item[readTable];
-    // Context readers store data in private symbols so we need to
-    // collect both table keys and private symbols.
-    const names = [...keys(table), ...symbols(table)];
-    const readers = map(name => table[name], names);
-    // Create delta for registered readers that will be merged into
-    // internal readers table.
-    const added = filter(x => !users[x.id], readers);
-    const delta = object(...map(x => [x.id, x], added));
-
-    const update = reduce((update, reader) => {
-      const n = update[reader.id] || 0;
-      update[reader.id] = n + 1;
-      return update;
-    }, Object.assign({}, users), readers);
-
-    // Patch current state with a changes that registered item caused.
-    this[Component.patch]({users: update,
-                           readers: Object.assign(this.state.readers, delta)});
-
-    if (count(added)) {
-      globalMessageManager.broadcastAsyncMessage("sdk/context-menu/readers",
-                                                 JSON.parse(JSON.stringify(delta)));
-    }
-  },
-  unregister(item) {
-    const { users, registry } = this.state;
-    if (!registry.has(item)) return;
-    registry.delete(item);
-
-    const table = item[readTable];
-    const names = [...keys(table), ...symbols(table)];
-    const readers = map(name => table[name], names);
-    const update = reduce((update, reader) => {
-      update[reader.id] = update[reader.id] - 1;
-      return update;
-    }, Object.assign({}, users), readers);
-    const removed = filter(id => !update[id], keys(update));
-    const delta = object(...map(x => [x, null], removed));
-
-    this[Component.patch]({users: update,
-                           readers: Object.assign(this.state.readers, delta)});
-
-    if (count(removed)) {
-      globalMessageManager.broadcastAsyncMessage("sdk/context-menu/readers",
-                                                 JSON.parse(JSON.stringify(delta)));
-    }
-  },
-
-  [onContext]({data, target}) {
-    propagateOnContext(this, data);
-    const document = target.ownerDocument;
-    const element = document.getElementById("contentAreaContextMenu");
-
-    this[Component.patch]({target: data, element: element});
-  }
-});this,
-exports.ContextMenuExtension = ContextMenuExtension;
-
-// Takes an item options and
-const makeReadTable = ({context, read}) => {
-  // Result of this function is a tuple of all readers &
-  // name, reader id pairs.
-
-  // Filter down to contexts that have a reader associated.
-  const contexts = filter(context => context.read, context);
-  // Merge all contexts read maps to a single hash, note that there should be
-  // no name collisions as context implementations expect to use private
-  // symbols for storing it's read data.
-  return Object.assign({}, ...map(({read}) => read, contexts), read);
-}
-
-const readTarget = (nameTable, data) =>
-  object(...map(([name, id]) => [name, data[id]], nameTable))
-
-const ContextHandler = Class({
-  extends: Component,
-  initialize: Component,
-  get context() {
-    return this.state.options.context;
-  },
-  get read() {
-    return this.state.options.read;
-  },
-  [Component.initial](options) {
-    return {
-      table: makeReadTable(options),
-      requiredContext: filter(context => context.isRequired, options.context),
-      optionalContext: filter(context => !context.isRequired, options.context)
-    }
-  },
-  [isMatching]() {
-    const {target, requiredContext, optionalContext} = this.state;
-    return isEvery(context => context.isCurrent(target), requiredContext) &&
-            (count(optionalContext) === 0 ||
-             some(context => context.isCurrent(target), optionalContext));
-  },
-  setup() {
-    const table = makeReadTable(this.state.options);
-    this[readTable] = table;
-    this[nameTable] = [...map(symbol => [symbol, table[symbol].id], symbols(table)),
-                       ...map(name => [name, table[name].id], keys(table))];
-
-
-    contextMenu.register(this);
-
-    each(child => contextMenu.remove(child), this.state.children);
-    contextMenu.add(this);
-  },
-  dispose() {
-    contextMenu.remove(this);
-
-    each(child => contextMenu.unregister(child), this.state.children);
-    contextMenu.unregister(this);
-  },
-  // Internal `Symbol("onContext")` method is invoked when "contextmenu" event
-  // occurs in content process. Context handles with children delegate to each
-  // child and patch it's internal state to reflect new contextmenu target.
-  [onContext](data) {
-    propagateOnContext(this, data);
-    this[Component.patch]({target: readTarget(this[nameTable], data)});
-  }
-});
-const isContextHandler = item => item instanceof ContextHandler;
-
-exports.ContextHandler = ContextHandler;
-
-const Menu = Class({
-  extends: ContextHandler,
-  [isMatching]() {
-    return ContextHandler.prototype[isMatching].call(this) &&
-           this.state.children.filter(isContextHandler)
-                              .some(isContextMatch);
-  },
-  [Component.render]({children, options}) {
-    const items = children.filter(isContextMatch);
-    return {tagName: "menu",
-            className: "sdk-context-menu menu-iconic",
-            label: options.label,
-            accesskey: options.accesskey,
-            image: options.icon,
-            children: [{tagName: "menupopup",
-                        children: items}]};
-  }
-});
-exports.Menu = Menu;
-
-const onCommand = Symbol("context-menu/item/onCommand");
-const Item = Class({
-  extends: ContextHandler,
-  get onClick() {
-    return this.state.options.onClick;
-  },
-  [Component.render]({options}) {
-    const {label, icon, accesskey} = options;
-    return {tagName: "menuitem",
-            className: "sdk-context-menu-item menuitem-iconic",
-            label,
-            accesskey,
-            image: icon,
-            oncommand: this};
-  },
-  handleEvent(event) {
-    if (this.onClick)
-      this.onClick(this.state.target);
-  }
-});
-exports.Item = Item;
-
-var Separator = Class({
-  extends: Component,
-  initialize: Component,
-  [Component.render]() {
-    return {tagName: "menuseparator",
-            className: "sdk-context-menu-separator"}
-  },
-  [onContext]() {
-
-  }
-});
-exports.Separator = Separator;
-
-exports.Contexts = Contexts;
-exports.Readers = Readers;
-
-const createElement = (vnode, {document}) => {
-   const node = vnode.namespace ?
-              document.createElementNS(vnode.namespace, vnode.tagName) :
-              document.createElement(vnode.tagName);
-
-   node.setAttribute("data-component-path", vnode[Component.path]);
-
-   each(([key, value]) => {
-     if (key === "tagName") {
-       return;
-     }
-     if (key === "children") {
-       return;
-     }
-
-     if (key.startsWith("on")) {
-       node.addEventListener(key.substr(2), value)
-       return;
-     }
-
-     if (typeof(value) !== "object" &&
-         typeof(value) !== "function" &&
-         value !== void(0) &&
-         value !== null)
-    {
-       if (key === "className") {
-         node[key] = value;
-       }
-       else {
-         node.setAttribute(key, value);
-       }
-       return;
-     }
-   }, pairs(vnode));
-
-  each(child => node.appendChild(createElement(child, {document})), vnode.children);
-  return node;
-};
-
-const htmlWriter = tree => {
-  if (tree !== null) {
-    const root = tree.element;
-    const node = createElement(tree, {document: root.ownerDocument});
-    const before = root.querySelector("[data-component-path='/']");
-    if (before) {
-      root.replaceChild(node, before);
-    } else {
-      root.appendChild(node);
-    }
-  }
-};
-
-
-const contextMenu = ContextMenuExtension();
-exports.contextMenu = contextMenu;
-Component.mount(contextMenu, htmlWriter);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/context-menu/readers.js
+++ /dev/null
@@ -1,112 +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/. */
-const { Class } = require("../core/heritage");
-const { extend } = require("../util/object");
-const { memoize, method, identity } = require("../lang/functional");
-
-const serializeCategory = ({type}) => ({ category: `reader/${type}()` });
-
-const Reader = Class({
-  initialize() {
-    this.id = `reader/${this.type}()`
-  },
-  toJSON() {
-    return serializeCategory(this);
-  }
-});
-
-
-const MediaTypeReader = Class({ extends: Reader, type: "MediaType" });
-exports.MediaType = MediaTypeReader;
-
-const LinkURLReader = Class({ extends: Reader, type: "LinkURL" });
-exports.LinkURL = LinkURLReader;
-
-const SelectionReader = Class({ extends: Reader, type: "Selection" });
-exports.Selection = SelectionReader;
-
-const isPageReader = Class({ extends: Reader, type: "isPage" });
-exports.isPage = isPageReader;
-
-const isFrameReader = Class({ extends: Reader, type: "isFrame" });
-exports.isFrame = isFrameReader;
-
-const isEditable = Class({ extends: Reader, type: "isEditable"});
-exports.isEditable = isEditable;
-
-
-
-const ParameterizedReader = Class({
-  extends: Reader,
-  readParameter: function(value) {
-    return value;
-  },
-  toJSON: function() {
-    var json = serializeCategory(this);
-    json[this.parameter] = this[this.parameter];
-    return json;
-  },
-  initialize(...params) {
-    if (params.length) {
-      this[this.parameter] = this.readParameter(...params);
-    }
-    this.id = `reader/${this.type}(${JSON.stringify(this[this.parameter])})`;
-  }
-});
-exports.ParameterizedReader = ParameterizedReader;
-
-
-const QueryReader = Class({
-  extends: ParameterizedReader,
-  type: "Query",
-  parameter: "path"
-});
-exports.Query = QueryReader;
-
-
-const AttributeReader = Class({
-  extends: ParameterizedReader,
-  type: "Attribute",
-  parameter: "name"
-});
-exports.Attribute = AttributeReader;
-
-const SrcURLReader = Class({
-  extends: AttributeReader,
-  name: "src",
-});
-exports.SrcURL = SrcURLReader;
-
-const PageURLReader = Class({
-  extends: QueryReader,
-  path: "ownerDocument.URL",
-});
-exports.PageURL = PageURLReader;
-
-const SelectorMatchReader = Class({
-  extends: ParameterizedReader,
-  type: "SelectorMatch",
-  parameter: "selector"
-});
-exports.SelectorMatch = SelectorMatchReader;
-
-const extractors = new WeakMap();
-extractors.id = 0;
-
-
-var Extractor = Class({
-  extends: ParameterizedReader,
-  type: "Extractor",
-  parameter: "source",
-  initialize: function(f) {
-    this[this.parameter] = String(f);
-    if (!extractors.has(f)) {
-      extractors.id = extractors.id + 1;
-      extractors.set(f, extractors.id);
-    }
-
-    this.id = `reader/${this.type}.for(${extractors.get(f)})`
-  }
-});
-exports.Extractor = Extractor;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/context-menu@2.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";
-
-const shared = require("toolkit/require");
-const { Item, Separator, Menu, Contexts, Readers } = shared.require("sdk/context-menu/core");
-const { setupDisposable, disposeDisposable, Disposable } = require("sdk/core/disposable")
-const { Class } = require("sdk/core/heritage")
-
-const makeDisposable = Type => Class({
-  extends: Type,
-  implements: [Disposable],
-  initialize: Type.prototype.initialize,
-  setup(...params) {
-    Type.prototype.setup.call(this, ...params);
-    setupDisposable(this);
-  },
-  dispose(...params) {
-    disposeDisposable(this);
-    Type.prototype.dispose.call(this, ...params);
-  }
-});
-
-exports.Separator = Separator;
-exports.Contexts = Contexts;
-exports.Readers = Readers;
-
-// Subclass Item & Menu shared classes so their items
-// will be unloaded when add-on is unloaded.
-exports.Item = makeDisposable(Item);
-exports.Menu = makeDisposable(Menu);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/browser.js
+++ /dev/null
@@ -1,73 +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 { windows, isBrowser, isInteractive, isDocumentLoaded,
-        getOuterId } = require("../window/utils");
-const { InputPort } = require("./system");
-const { lift, merges, foldp, keepIf, start, Input } = require("../event/utils");
-const { patch } = require("diffpatcher/index");
-const { Sequence, seq, filter, object, pairs } = require("../util/sequence");
-
-
-// Create lazy iterators from the regular arrays, although
-// once https://github.com/mozilla/addon-sdk/pull/1314 lands
-// `windows` will be transforme to lazy iterators.
-// When iterated over belowe sequences items will represent
-// state of windows at the time of iteration.
-const opened = seq(function*() {
-  const items = windows("navigator:browser", {includePrivate: true});
-  for (let item of items) {
-      yield [getOuterId(item), item];
-  }
-});
-const interactive = filter(([_, window]) => isInteractive(window), opened);
-const loaded = filter(([_, window]) => isDocumentLoaded(window), opened);
-
-// Helper function that converts given argument to a delta.
-const Update = window => window && object([getOuterId(window), window]);
-const Delete = window => window && object([getOuterId(window), null]);
-
-
-// Signal represents delta for last top level window close.
-const LastClosed = lift(Delete,
-                        keepIf(isBrowser, null,
-                               new InputPort({topic: "domwindowclosed"})));
-exports.LastClosed = LastClosed;
-
-const windowFor = document => document && document.defaultView;
-
-// Signal represent delta for last top level window document becoming interactive.
-const InteractiveDoc = new InputPort({topic: "chrome-document-interactive"});
-const InteractiveWin = lift(windowFor, InteractiveDoc);
-const LastInteractive = lift(Update, keepIf(isBrowser, null, InteractiveWin));
-exports.LastInteractive = LastInteractive;
-
-// Signal represent delta for last top level window loaded.
-const LoadedDoc = new InputPort({topic: "chrome-document-loaded"});
-const LoadedWin = lift(windowFor, LoadedDoc);
-const LastLoaded = lift(Update, keepIf(isBrowser, null, LoadedWin));
-exports.LastLoaded = LastLoaded;
-
-
-const initialize = input => {
-  if (!input.initialized) {
-    input.value = object(...input.value);
-    Input.start(input);
-    input.initialized = true;
-  }
-};
-
-// Signal represents set of top level interactive windows, updated any
-// time new window becomes interactive or one get's closed.
-const Interactive = foldp(patch, interactive, merges([LastInteractive,
-                                                      LastClosed]));
-Interactive[start] = initialize;
-exports.Interactive = Interactive;
-
-// Signal represents set of top level loaded window, updated any time
-// new window becomes interactive or one get's closed.
-const Loaded = foldp(patch, loaded, merges([LastLoaded, LastClosed]));
-Loaded[start] = initialize;
-exports.Loaded = Loaded;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/customizable-ui.js
+++ /dev/null
@@ -1,28 +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 { Cu } = require("chrome");
-const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { receive } = require("../event/utils");
-const { InputPort } = require("./system");
-const { object} = require("../util/sequence");
-const { getOuterId } = require("../window/utils");
-
-const Input = function() {};
-Input.prototype = Object.create(InputPort.prototype);
-
-Input.prototype.onCustomizeStart = function (window) {
-  receive(this, object([getOuterId(window), true]));
-}
-
-Input.prototype.onCustomizeEnd = function (window) {
-  receive(this, object([getOuterId(window), null]));
-}
-
-Input.prototype.addListener = input => CustomizableUI.addListener(input);
-
-Input.prototype.removeListener = input => CustomizableUI.removeListener(input);
-
-exports.CustomizationInput = Input;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/frame.js
+++ /dev/null
@@ -1,85 +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 { InputPort } = require("./system");
-const { getFrameElement, getOuterId,
-        getOwnerBrowserWindow } = require("../window/utils");
-const { isnt } = require("../lang/functional");
-const { foldp, lift, merges, keepIf } = require("../event/utils");
-const { object } = require("../util/sequence");
-const { compose } = require("../lang/functional");
-const { LastClosed } = require("./browser");
-const { patch } = require("diffpatcher/index");
-
-const Document = Ci.nsIDOMDocument;
-
-const isntNull = isnt(null);
-
-const frameID = frame => frame.id;
-const browserID = compose(getOuterId, getOwnerBrowserWindow);
-
-const isInnerFrame = frame =>
-  frame && frame.hasAttribute("data-is-sdk-inner-frame");
-
-// Utility function that given content window loaded in our frame views returns
-// an actual frame. This basically takes care of fact that actual frame document
-// is loaded in the nested iframe. If content window is not loaded in the nested
-// frame of the frame view it returs null.
-const getFrame = document =>
-  document && document.defaultView && getFrameElement(document.defaultView);
-
-const FrameInput = function(options) {
-  const input = keepIf(isInnerFrame, null,
-                       lift(getFrame, new InputPort(options)));
-  return lift(frame => {
-    if (!frame) return frame;
-    const [id, owner] = [frameID(frame), browserID(frame)];
-    return object([id, {owners: object([owner, options.update])}]);
-  }, input);
-};
-
-const LastLoading = new FrameInput({topic: "document-element-inserted",
-                                    update: {readyState: "loading"}});
-exports.LastLoading = LastLoading;
-
-const LastInteractive = new FrameInput({topic: "content-document-interactive",
-                                        update: {readyState: "interactive"}});
-exports.LastInteractive = LastInteractive;
-
-const LastLoaded = new FrameInput({topic: "content-document-loaded",
-                                   update: {readyState: "complete"}});
-exports.LastLoaded = LastLoaded;
-
-const LastUnloaded = new FrameInput({topic: "content-page-hidden",
-                                    update: null});
-exports.LastUnloaded = LastUnloaded;
-
-// Represents state of SDK frames in form of data structure:
-// {"frame#1": {"id": "frame#1",
-//              "inbox": {"data": "ping",
-//                        "target": {"id": "frame#1", "owner": "outerWindowID#2"},
-//                        "source": {"id": "frame#1"}}
-//              "url": "resource://addon-1/data/index.html",
-//              "owners": {"outerWindowID#1": {"readyState": "loading"},
-//                         "outerWindowID#2": {"readyState": "complete"}}
-//
-//
-//  frame#2: {"id": "frame#2",
-//            "url": "resource://addon-1/data/main.html",
-//            "outbox": {"data": "pong",
-//                       "source": {"id": "frame#2", "owner": "outerWindowID#1"}
-//                       "target": {"id": "frame#2"}}
-//            "owners": {outerWindowID#1: {readyState: "interacitve"}}}}
-const Frames = foldp(patch, {}, merges([
-  LastLoading,
-  LastInteractive,
-  LastLoaded,
-  LastUnloaded,
-  new InputPort({ id: "frame-mailbox" }),
-  new InputPort({ id: "frame-change" }),
-  new InputPort({ id: "frame-changed" })
-]));
-exports.Frames = Frames;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/system.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";
-
-const { Cc, Ci, Cr, Cu } = require("chrome");
-const { Input, start, stop, end, receive, outputs } = require("../event/utils");
-const { once, off } = require("../event/core");
-const { id: addonID } = require("../self");
-
-const unloadMessage = require("@loader/unload");
-const observerService = Cc['@mozilla.org/observer-service;1'].
-                          getService(Ci.nsIObserverService);
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
-const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
-
-
-const addonUnloadTopic = "sdk:loader:destroy";
-
-const isXrayWrapper = Cu.isXrayWrapper;
-// In the past SDK used to double-wrap notifications dispatched, which
-// made them awkward to use outside of SDK. At present they no longer
-// do that, although we still supported for legacy reasons.
-const isLegacyWrapper = x =>
-    x && x.wrappedJSObject &&
-    "observersModuleSubjectWrapper" in x.wrappedJSObject;
-
-const unwrapLegacy = x => x.wrappedJSObject.object;
-
-// `InputPort` provides a way to create a signal out of the observer
-// notification subject's for the given `topic`. If `options.initial`
-// is provided it is used as initial value otherwise `null` is used.
-// Constructor can be given `options.id` that will be used to create
-// a `topic` which is namespaced to an add-on (this avoids conflicts
-// when multiple add-on are used, although in a future host probably
-// should just be shared across add-ons). It is also possible to
-// specify a specific `topic` via `options.topic` which is used as
-// without namespacing. Created signal ends whenever add-on is
-// unloaded.
-const InputPort = function InputPort({id, topic, initial}) {
-  this.id = id || topic;
-  this.topic = topic || "sdk:" + addonID + ":" + id;
-  this.value = initial === void(0) ? null : initial;
-  this.observing = false;
-  this[outputs] = [];
-};
-
-// InputPort type implements `Input` signal interface.
-InputPort.prototype = new Input();
-InputPort.prototype.constructor = InputPort;
-
-// When port is started (which is when it's subgraph get's
-// first subscriber) actual observer is registered.
-InputPort.start = input => {
-  input.addListener(input);
-  // Also register add-on unload observer to end this signal
-  // when that happens.
-  addObserver(input, addonUnloadTopic, false);
-};
-InputPort.prototype[start] = InputPort.start;
-
-InputPort.addListener = input => addObserver(input, input.topic, false);
-InputPort.prototype.addListener = InputPort.addListener;
-
-// When port is stopped (which is when it's subgraph has no
-// no subcribers left) an actual observer unregistered.
-// Note that port stopped once it ends as well (which is when
-// add-on is unloaded).
-InputPort.stop = input => {
-  input.removeListener(input);
-  removeObserver(input, addonUnloadTopic);
-};
-InputPort.prototype[stop] = InputPort.stop;
-
-InputPort.removeListener = input => removeObserver(input, input.topic);
-InputPort.prototype.removeListener = InputPort.removeListener;
-
-// `InputPort` also implements `nsIObserver` interface and
-// `nsISupportsWeakReference` interfaces as it's going to be used as such.
-InputPort.prototype.QueryInterface = function(iid) {
-  if (!iid.equals(Ci.nsIObserver) && !iid.equals(Ci.nsISupportsWeakReference))
-    throw Cr.NS_ERROR_NO_INTERFACE;
-
-  return this;
-};
-
-// `InputPort` instances implement `observe` method, which is invoked when
-// observer notifications are dispatched. The `subject` of that notification
-// are received on this signal.
-InputPort.prototype.observe = function(subject, topic, data) {
-  // Unwrap message from the subject. SDK used to have it's own version of
-  // wrappedJSObjects which take precedence, if subject has `wrappedJSObject`
-  // and it's not an XrayWrapper use it as message. Otherwise use subject as
-  // is.
-  const message = subject === null ? null :
-        isLegacyWrapper(subject) ? unwrapLegacy(subject) :
-        isXrayWrapper(subject) ? subject :
-        subject.wrappedJSObject ? subject.wrappedJSObject :
-        subject;
-
-  // If observer topic matches topic of the input port receive a message.
-  if (topic === this.topic) {
-    receive(this, message);
-  }
-
-  // If observe topic is add-on unload topic we create an end message.
-  if (topic === addonUnloadTopic && message === unloadMessage) {
-    end(this);
-  }
-};
-
-exports.InputPort = InputPort;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/panel.js
+++ /dev/null
@@ -1,436 +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";
-
-// The panel module currently supports only Firefox and SeaMonkey.
-// See: https://bugzilla.mozilla.org/show_bug.cgi?id=jetpack-panel-apps
-module.metadata = {
-  "stability": "stable",
-  "engines": {
-    "Firefox": "*",
-    "SeaMonkey": "*"
-  }
-};
-
-const { Cu, Ci } = require("chrome");
-lazyRequire(this, './timers', "setTimeout");
-const { Class } = require("./core/heritage");
-const { DefaultWeakMap, merge } = require("./util/object");
-const { WorkerHost } = require("./content/utils");
-lazyRequire(this, "./deprecated/sync-worker", "Worker");
-const { Disposable } = require("./core/disposable");
-const { WeakReference } = require('./core/reference');
-const { contract: loaderContract } = require("./content/loader");
-const { contract } = require("./util/contract");
-lazyRequire(this, "./event/core", "on", "off", "emit", "setListeners");
-const { EventTarget } = require("./event/target");
-lazyRequireModule(this, "./panel/utils", "domPanel");
-lazyRequire(this, './frame/utils', "getDocShell");
-const { events } = require("./panel/events");
-const { filter, pipe, stripListeners } = require("./event/utils");
-lazyRequire(this, "./view/core", "getNodeView", "getActiveView");
-lazyRequire(this, "./lang/type", "isNil", "isObject", "isNumber");
-lazyRequire(this, "./content/utils", "getAttachEventType");
-const { number, boolean, object } = require('./deprecated/api-utils');
-lazyRequire(this, "./stylesheet/style", "Style");
-lazyRequire(this, "./content/mod", "attach", "detach");
-
-var isRect = ({top, right, bottom, left}) => [top, right, bottom, left].
-  some(value => isNumber(value) && !isNaN(value));
-
-var isSDKObj = obj => obj instanceof Class;
-
-var rectContract = contract({
-  top: number,
-  right: number,
-  bottom: number,
-  left: number
-});
-
-var position = {
-  is: object,
-  map: v => (isNil(v) || isSDKObj(v) || !isObject(v)) ? v : rectContract(v),
-  ok: v => isNil(v) || isSDKObj(v) || (isObject(v) && isRect(v)),
-  msg: 'The option "position" must be a SDK object registered as anchor; ' +
-        'or an object with one or more of the following keys set to numeric ' +
-        'values: top, right, bottom, left.'
-}
-
-var displayContract = contract({
-  width: number,
-  height: number,
-  focus: boolean,
-  position: position
-});
-
-var panelContract = contract(merge({
-  // contentStyle* / contentScript* are sharing the same validation constraints,
-  // so they can be mostly reused, except for the messages.
-  contentStyle: merge(Object.create(loaderContract.rules.contentScript), {
-    msg: 'The `contentStyle` option must be a string or an array of strings.'
-  }),
-  contentStyleFile: merge(Object.create(loaderContract.rules.contentScriptFile), {
-    msg: 'The `contentStyleFile` option must be a local URL or an array of URLs'
-  }),
-  contextMenu: boolean,
-  allow: {
-    is: ['object', 'undefined', 'null'],
-    map: function (allow) { return { script: !allow || allow.script !== false }}
-  },
-}, displayContract.rules, loaderContract.rules));
-
-function Allow(panel) {
-  return {
-    get script() { return getDocShell(viewFor(panel).backgroundFrame).allowJavascript; },
-    set script(value) { return setScriptState(panel, value); },
-  };
-}
-
-function setScriptState(panel, value) {
-  let view = viewFor(panel);
-  getDocShell(view.backgroundFrame).allowJavascript = value;
-  getDocShell(view.viewFrame).allowJavascript = value;
-  view.setAttribute("sdkscriptenabled", "" + value);
-}
-
-function isDisposed(panel) {
-  return !views.has(panel);
-}
-
-var optionsMap = new WeakMap();
-var panels = new WeakMap();
-var models = new WeakMap();
-var views = new DefaultWeakMap(panel => {
-  let model = models.get(panel);
-
-  // Setup view
-  let viewOptions = {allowJavascript: !model.allow || (model.allow.script !== false)};
-  let view = domPanel.make(null, viewOptions);
-  panels.set(view, panel);
-
-  // Load panel content.
-  domPanel.setURL(view, model.contentURL);
-
-  // Allow context menu
-  domPanel.allowContextMenu(view, model.contextMenu);
-
-  return view;
-});
-var workers = new DefaultWeakMap(panel => {
-  let options = optionsMap.get(panel);
-
-  let worker = new Worker(stripListeners(options));
-  workers.set(panel, worker);
-
-  // pipe events from worker to a panel.
-  pipe(worker, panel);
-
-  return worker;
-});
-var styles = new WeakMap();
-
-const viewFor = (panel) => views.get(panel);
-const modelFor = (panel) => models.get(panel);
-const panelFor = (view) => panels.get(view);
-const workerFor = (panel) => workers.get(panel);
-const styleFor = (panel) => styles.get(panel);
-
-function getPanelFromWeakRef(weakRef) {
-  if (!weakRef) {
-    return null;
-  }
-  let panel = weakRef.get();
-  if (!panel) {
-    return null;
-  }
-  if (isDisposed(panel)) {
-    return null;
-  }
-  return panel;
-}
-
-var SinglePanelManager = {
-  visiblePanel: null,
-  enqueuedPanel: null,
-  enqueuedPanelCallback: null,
-  // Calls |callback| with no arguments when the panel may be shown.
-  requestOpen: function(panelToOpen, callback) {
-    let currentPanel = getPanelFromWeakRef(SinglePanelManager.visiblePanel);
-    if (currentPanel || SinglePanelManager.enqueuedPanel) {
-      SinglePanelManager.enqueuedPanel = Cu.getWeakReference(panelToOpen);
-      SinglePanelManager.enqueuedPanelCallback = callback;
-      if (currentPanel && currentPanel.isShowing) {
-        currentPanel.hide();
-      }
-    } else {
-      SinglePanelManager.notifyPanelCanOpen(panelToOpen, callback);
-    }
-  },
-  notifyPanelCanOpen: function(panel, callback) {
-    let view = viewFor(panel);
-    // Can't pass an arrow function as the event handler because we need to be
-    // able to call |removeEventListener| later.
-    view.addEventListener("popuphidden", SinglePanelManager.onVisiblePanelHidden, true);
-    view.addEventListener("popupshown", SinglePanelManager.onVisiblePanelShown);
-    SinglePanelManager.enqueuedPanel = null;
-    SinglePanelManager.enqueuedPanelCallback = null;
-    SinglePanelManager.visiblePanel = Cu.getWeakReference(panel);
-    callback();
-  },
-  onVisiblePanelShown: function(event) {
-    let panel = panelFor(event.target);
-    if (SinglePanelManager.enqueuedPanel) {
-      // Another panel started waiting for |panel| to close before |panel| was
-      // even done opening.
-      panel.hide();
-    }
-  },
-  onVisiblePanelHidden: function(event) {
-    let view = event.target;
-    let panel = panelFor(view);
-    let currentPanel = getPanelFromWeakRef(SinglePanelManager.visiblePanel);
-    if (currentPanel && currentPanel != panel) {
-      return;
-    }
-    SinglePanelManager.visiblePanel = null;
-    view.removeEventListener("popuphidden", SinglePanelManager.onVisiblePanelHidden, true);
-    view.removeEventListener("popupshown", SinglePanelManager.onVisiblePanelShown);
-    let nextPanel = getPanelFromWeakRef(SinglePanelManager.enqueuedPanel);
-    let nextPanelCallback = SinglePanelManager.enqueuedPanelCallback;
-    if (nextPanel) {
-      SinglePanelManager.notifyPanelCanOpen(nextPanel, nextPanelCallback);
-    }
-  }
-};
-
-const Panel = Class({
-  implements: [
-    // Generate accessors for the validated properties that update model on
-    // set and return values from model on get.
-    panelContract.properties(modelFor),
-    EventTarget,
-    Disposable,
-    WeakReference
-  ],
-  extends: WorkerHost(workerFor),
-  setup: function setup(options) {
-    let model = merge({
-      defaultWidth: 320,
-      defaultHeight: 240,
-      focus: true,
-      position: Object.freeze({}),
-      contextMenu: false
-    }, panelContract(options));
-    model.ready = false;
-    models.set(this, model);
-
-    if (model.contentStyle || model.contentStyleFile) {
-      styles.set(this, Style({
-        uri: model.contentStyleFile,
-        source: model.contentStyle
-      }));
-    }
-
-    optionsMap.set(this, options);
-
-    // Setup listeners.
-    setListeners(this, options);
-  },
-  dispose: function dispose() {
-    if (views.has(this))
-      this.hide();
-    off(this);
-
-    workerFor(this).destroy();
-    detach(styleFor(this));
-
-    if (views.has(this))
-      domPanel.dispose(viewFor(this));
-
-    views.delete(this);
-  },
-  /* Public API: Panel.width */
-  get width() {
-    return modelFor(this).width;
-  },
-  set width(value) {
-    this.resize(value, this.height);
-  },
-  /* Public API: Panel.height */
-  get height() {
-    return modelFor(this).height;
-  },
-  set height(value) {
-    this.resize(this.width, value);
-  },
-
-  /* Public API: Panel.focus */
-  get focus() {
-    return modelFor(this).focus;
-  },
-
-  /* Public API: Panel.position */
-  get position() {
-    return modelFor(this).position;
-  },
-
-  /* Public API: Panel.contextMenu */
-  get contextMenu() {
-    return modelFor(this).contextMenu;
-  },
-  set contextMenu(allow) {
-    let model = modelFor(this);
-    model.contextMenu = panelContract({ contextMenu: allow }).contextMenu;
-    domPanel.allowContextMenu(viewFor(this), model.contextMenu);
-  },
-
-  get contentURL() {
-    return modelFor(this).contentURL;
-  },
-  set contentURL(value) {
-    let model = modelFor(this);
-    model.contentURL = panelContract({ contentURL: value }).contentURL;
-    domPanel.setURL(viewFor(this), model.contentURL);
-    // Detach worker so that messages send will be queued until it's
-    // reatached once panel content is ready.
-    workerFor(this).detach();
-  },
-
-  get allow() { return Allow(this); },
-  set allow(value) {
-    let allowJavascript = panelContract({ allow: value }).allow.script;
-    return setScriptState(this, value);
-  },
-
-  /* Public API: Panel.isShowing */
-  get isShowing() {
-    return !isDisposed(this) && domPanel.isOpen(viewFor(this));
-  },
-
-  /* Public API: Panel.show */
-  show: function show(options={}, anchor) {
-    let view = viewFor(this);
-    SinglePanelManager.requestOpen(this, () => {
-      if (options instanceof Ci.nsIDOMElement) {
-        [anchor, options] = [options, null];
-      }
-
-      if (anchor instanceof Ci.nsIDOMElement) {
-        console.warn(
-          "Passing a DOM node to Panel.show() method is an unsupported " +
-          "feature that will be soon replaced. " +
-          "See: https://bugzilla.mozilla.org/show_bug.cgi?id=878877"
-        );
-      }
-
-      let model = modelFor(this);
-      let anchorView = getNodeView(anchor || options.position || model.position);
-
-      options = merge({
-        position: model.position,
-        width: model.width,
-        height: model.height,
-        defaultWidth: model.defaultWidth,
-        defaultHeight: model.defaultHeight,
-        focus: model.focus,
-        contextMenu: model.contextMenu
-      }, displayContract(options));
-
-      if (!isDisposed(this)) {
-        domPanel.show(view, options, anchorView);
-      }
-    });
-    return this;
-  },
-
-  /* Public API: Panel.hide */
-  hide: function hide() {
-    // Quit immediately if panel is disposed or there is no state change.
-    domPanel.close(viewFor(this));
-
-    return this;
-  },
-
-  /* Public API: Panel.resize */
-  resize: function resize(width, height) {
-    let model = modelFor(this);
-    let view = viewFor(this);
-    let change = panelContract({
-      width: width || model.width || model.defaultWidth,
-      height: height || model.height || model.defaultHeight
-    });
-
-    model.width = change.width
-    model.height = change.height
-
-    domPanel.resize(view, model.width, model.height);
-
-    return this;
-  }
-});
-exports.Panel = Panel;
-
-// Note must be defined only after value to `Panel` is assigned.
-getActiveView.define(Panel, viewFor);
-
-// Filter panel events to only panels that are create by this module.
-var panelEvents = filter(events, ({target}) => panelFor(target));
-
-// Panel events emitted after panel has being shown.
-var shows = filter(panelEvents, ({type}) => type === "popupshown");
-
-// Panel events emitted after panel became hidden.
-var hides = filter(panelEvents, ({type}) => type === "popuphidden");
-
-// Panel events emitted after content inside panel is ready. For different
-// panels ready may mean different state based on `contentScriptWhen` attribute.
-// Weather given event represents readyness is detected by `getAttachEventType`
-// helper function.
-var ready = filter(panelEvents, ({type, target}) =>
-  getAttachEventType(modelFor(panelFor(target))) === type);
-
-// Panel event emitted when the contents of the panel has been loaded.
-var readyToShow = filter(panelEvents, ({type}) => type === "DOMContentLoaded");
-
-// Styles should be always added as soon as possible, and doesn't makes them
-// depends on `contentScriptWhen`
-var start = filter(panelEvents, ({type}) => type === "document-element-inserted");
-
-// Forward panel show / hide events to panel's own event listeners.
-on(shows, "data", ({target}) => {
-  let panel = panelFor(target);
-  if (modelFor(panel).ready)
-    emit(panel, "show");
-});
-
-on(hides, "data", ({target}) => {
-  let panel = panelFor(target);
-  if (modelFor(panel).ready)
-    emit(panel, "hide");
-});
-
-on(ready, "data", ({target}) => {
-  let panel = panelFor(target);
-  let window = domPanel.getContentDocument(target).defaultView;
-
-  workerFor(panel).attach(window);
-});
-
-on(readyToShow, "data", ({target}) => {
-  let panel = panelFor(target);
-
-  if (!modelFor(panel).ready) {
-    modelFor(panel).ready = true;
-
-    if (viewFor(panel).state == "open")
-      emit(panel, "show");
-  }
-});
-
-on(start, "data", ({target}) => {
-  let panel = panelFor(target);
-  let window = domPanel.getContentDocument(target).defaultView;
-
-  attach(styleFor(panel), window);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/panel/events.js
+++ /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";
-
-// This module basically translates system/events to a SDK standard events
-// so that `map`, `filter` and other utilities could be used with them.
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const events = require("../system/events");
-lazyRequire(this, "../event/core", "emit");
-
-var channel = {};
-
-function forward({ subject, type, data }) {
-  return emit(channel, "data", { target: subject, type: type, data: data });
-}
-
-["popupshowing", "popuphiding", "popupshown", "popuphidden",
-"document-element-inserted", "DOMContentLoaded", "load"
-].forEach(type => events.on(type, forward));
-
-exports.events = channel;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/panel/utils.js
+++ /dev/null
@@ -1,451 +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 { Cc, Ci } = require("chrome");
-const { Services } = require("resource://gre/modules/Services.jsm");
-lazyRequire(this, "../timers", "setTimeout");
-lazyRequire(this, "../system", "platform");
-lazyRequire(this, "../window/utils", "getMostRecentBrowserWindow", "getOwnerBrowserWindow",
-            "getScreenPixelsPerCSSPixel");
-
-lazyRequire(this, "../frame/utils", { "create": "createFrame" }, "swapFrameLoaders", "getDocShell");
-lazyRequire(this, "../addon/window", { "window": "addonWindow" });
-lazyRequire(this, "../lang/type", "isNil");
-lazyRequire(this, '../self', "data");
-
-lazyRequireModule(this, "../system/events", "events");
-
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-function calculateRegion({ position, width, height, defaultWidth, defaultHeight }, rect) {
-  position = position || {};
-
-  let x, y;
-
-  let hasTop = !isNil(position.top);
-  let hasRight = !isNil(position.right);
-  let hasBottom = !isNil(position.bottom);
-  let hasLeft = !isNil(position.left);
-  let hasWidth = !isNil(width);
-  let hasHeight = !isNil(height);
-
-  // if width is not specified by constructor or show's options, then get
-  // the default width
-  if (!hasWidth)
-    width = defaultWidth;
-
-  // if height is not specified by constructor or show's options, then get
-  // the default height
-  if (!hasHeight)
-    height = defaultHeight;
-
-  // default position is centered
-  x = (rect.right - width) / 2;
-  y = (rect.top + rect.bottom - height) / 2;
-
-  if (hasTop) {
-    y = rect.top + position.top;
-
-    if (hasBottom && !hasHeight)
-      height = rect.bottom - position.bottom - y;
-  }
-  else if (hasBottom) {
-    y = rect.bottom - position.bottom - height;
-  }
-
-  if (hasLeft) {
-    x = position.left;
-
-    if (hasRight && !hasWidth)
-      width = rect.right - position.right - x;
-  }
-  else if (hasRight) {
-    x = rect.right - width - position.right;
-  }
-
-  return {x: x, y: y, width: width, height: height};
-}
-
-function open(panel, options, anchor) {
-  // Wait for the XBL binding to be constructed
-  if (!panel.openPopup) setTimeout(open, 50, panel, options, anchor);
-  else display(panel, options, anchor);
-}
-exports.open = open;
-
-function isOpen(panel) {
-  return panel.state === "open"
-}
-exports.isOpen = isOpen;
-
-function isOpening(panel) {
-  return panel.state === "showing"
-}
-exports.isOpening = isOpening
-
-function close(panel) {
-  // Sometimes "TypeError: panel.hidePopup is not a function" is thrown
-  // when quitting the host application while a panel is visible.  To suppress
-  // these errors, check for "hidePopup" in panel before calling it.
-  // It's not clear if there's an issue or it's expected behavior.
-  // See Bug 1151796.
-
-  return panel.hidePopup && panel.hidePopup();
-}
-exports.close = close
-
-
-function resize(panel, width, height) {
-  // Resize the iframe instead of using panel.sizeTo
-  // because sizeTo doesn't work with arrow panels
-  if (panel.firstChild) {
-    panel.firstChild.style.width = width + "px";
-    panel.firstChild.style.height = height + "px";
-  }
-}
-exports.resize = resize
-
-function display(panel, options, anchor) {
-  let document = panel.ownerDocument;
-
-  let x, y;
-  let { width, height, defaultWidth, defaultHeight } = options;
-
-  let popupPosition = null;
-
-  // Panel XBL has some SDK incompatible styling decisions. We shim panel
-  // instances until proper fix for Bug 859504 is shipped.
-  shimDefaultStyle(panel);
-
-  if (!anchor) {
-    // The XUL Panel doesn't have an arrow, so the margin needs to be reset
-    // in order to, be positioned properly
-    panel.style.margin = "0";
-
-    let viewportRect = document.defaultView.gBrowser.getBoundingClientRect();
-
-    ({x, y, width, height} = calculateRegion(options, viewportRect));
-  }
-  else {
-    // The XUL Panel has an arrow, so the margin needs to be reset
-    // to the default value.
-    panel.style.margin = "";
-    let { CustomizableUI, window } = anchor.ownerGlobal;
-
-    // In Australis, widgets may be positioned in an overflow panel or the
-    // menu panel.
-    // In such cases clicking this widget will hide the overflow/menu panel,
-    // and the widget's panel will show instead.
-    // If `CustomizableUI` is not available, it means the anchor is not in a
-    // chrome browser window, and therefore there is no need for this check.
-    if (CustomizableUI) {
-      let node = anchor;
-      ({anchor} = CustomizableUI.getWidget(anchor.id).forWindow(window));
-
-      // if `node` is not the `anchor` itself, it means the widget is
-      // positioned in a panel, therefore we have to hide it before show
-      // the widget's panel in the same anchor
-      if (node !== anchor)
-        CustomizableUI.hidePanelForNode(anchor);
-    }
-
-    width = width || defaultWidth;
-    height = height || defaultHeight;
-
-    // Open the popup by the anchor.
-    let rect = anchor.getBoundingClientRect();
-
-    let zoom = getScreenPixelsPerCSSPixel(window);
-    let screenX = rect.left + window.mozInnerScreenX * zoom;
-    let screenY = rect.top + window.mozInnerScreenY * zoom;
-
-    // Set up the vertical position of the popup relative to the anchor
-    // (always display the arrow on anchor center)
-    let horizontal, vertical;
-    if (screenY > window.screen.availHeight / 2 + height)
-      vertical = "top";
-    else
-      vertical = "bottom";
-
-    if (screenY > window.screen.availWidth / 2 + width)
-      horizontal = "left";
-    else
-      horizontal = "right";
-
-    let verticalInverse = vertical == "top" ? "bottom" : "top";
-    popupPosition = vertical + "center " + verticalInverse + horizontal;
-
-    // Allow panel to flip itself if the panel can't be displayed at the
-    // specified position (useful if we compute a bad position or if the
-    // user moves the window and panel remains visible)
-    panel.setAttribute("flip", "both");
-  }
-
-  if (!panel.viewFrame) {
-    panel.viewFrame = document.importNode(panel.backgroundFrame, false);
-    panel.appendChild(panel.viewFrame);
-
-    let {privateBrowsingId} = getDocShell(panel.viewFrame).getOriginAttributes();
-    let principal = Services.scriptSecurityManager.createNullPrincipal({privateBrowsingId});
-    getDocShell(panel.viewFrame).createAboutBlankContentViewer(principal);
-  }
-
-  // Resize the iframe instead of using panel.sizeTo
-  // because sizeTo doesn't work with arrow panels
-  panel.firstChild.style.width = width + "px";
-  panel.firstChild.style.height = height + "px";
-
-  panel.openPopup(anchor, popupPosition, x, y);
-}
-exports.display = display;
-
-// This utility function is just a workaround until Bug 859504 has shipped.
-function shimDefaultStyle(panel) {
-  let document = panel.ownerDocument;
-  // Please note that `panel` needs to be part of document in order to reach
-  // it's anonymous nodes. One of the anonymous node has a big padding which
-  // doesn't work well since panel frame needs to fill all of the panel.
-  // XBL binding is a not the best option as it's applied asynchronously, and
-  // makes injected frames behave in strange way. Also this feels a lot
-  // cheaper to do.
-  ["panel-inner-arrowcontent", "panel-arrowcontent"].forEach(function(value) {
-    let node = document.getAnonymousElementByAttribute(panel, "class", value);
-      if (node) node.style.padding = 0;
-  });
-}
-
-function show(panel, options, anchor) {
-  // Prevent the panel from getting focus when showing up
-  // if focus is set to false
-  panel.setAttribute("noautofocus", !options.focus);
-
-  let window = anchor && getOwnerBrowserWindow(anchor);
-  let { document } = window ? window : getMostRecentBrowserWindow();
-  attach(panel, document);
-
-  open(panel, options, anchor);
-}
-exports.show = show
-
-function onPanelClick(event) {
-  let { target, metaKey, ctrlKey, shiftKey, button } = event;
-  let accel = platform === "darwin" ? metaKey : ctrlKey;
-  let isLeftClick = button === 0;
-  let isMiddleClick = button === 1;
-
-  if ((isLeftClick && (accel || shiftKey)) || isMiddleClick) {
-    let link = target.closest('a');
-
-    if (link && link.href)
-       getMostRecentBrowserWindow().openUILink(link.href, event)
-  }
-}
-
-function setupPanelFrame(frame) {
-  frame.setAttribute("flex", 1);
-  frame.setAttribute("transparent", "transparent");
-  frame.setAttribute("autocompleteenabled", true);
-  frame.setAttribute("tooltip", "aHTMLTooltip");
-  if (platform === "darwin") {
-    frame.style.borderRadius = "var(--arrowpanel-border-radius, 3.5px)";
-    frame.style.padding = "1px";
-  }
-}
-
-function make(document, options) {
-  document = document || getMostRecentBrowserWindow().document;
-  let panel = document.createElementNS(XUL_NS, "panel");
-  panel.setAttribute("type", "arrow");
-  panel.setAttribute("sdkscriptenabled", options.allowJavascript);
-
-  // The panel needs to be attached to a browser window in order for us
-  // to copy browser styles to the content document when it loads.
-  attach(panel, document);
-
-  let frameOptions =  {
-    allowJavascript: options.allowJavascript,
-    allowPlugins: true,
-    allowAuth: true,
-    allowWindowControl: false,
-    // Need to override `nodeName` to use `iframe` as `browsers` save session
-    // history and in consequence do not dispatch "inner-window-destroyed"
-    // notifications.
-    browser: false,
-  };
-
-  let backgroundFrame = createFrame(addonWindow, frameOptions);
-  setupPanelFrame(backgroundFrame);
-
-  getDocShell(backgroundFrame).inheritPrivateBrowsingId = false;
-
-  function onPopupShowing({type, target}) {
-    if (target === this) {
-      let attrs = getDocShell(backgroundFrame).getOriginAttributes();
-      getDocShell(panel.viewFrame).setOriginAttributes(attrs);
-
-      swapFrameLoaders(backgroundFrame, panel.viewFrame);
-    }
-  }
-
-  function onPopupHiding({type, target}) {
-    if (target === this) {
-      swapFrameLoaders(backgroundFrame, panel.viewFrame);
-
-      panel.viewFrame.remove();
-      panel.viewFrame = null;
-    }
-  }
-
-  function onContentReady({target, type}) {
-    if (target === getContentDocument(panel)) {
-      style(panel);
-      events.emit(type, { subject: panel });
-    }
-  }
-
-  function onContentLoad({target, type}) {
-    if (target === getContentDocument(panel))
-      events.emit(type, { subject: panel });
-  }
-
-  function onContentChange({subject: document, type}) {
-    if (document === getContentDocument(panel) && document.defaultView)
-      events.emit(type, { subject: panel });
-  }
-
-  function onPanelStateChange({target, type}) {
-    if (target === this)
-      events.emit(type, { subject: panel })
-  }
-
-  panel.addEventListener("popupshowing", onPopupShowing);
-  panel.addEventListener("popuphiding", onPopupHiding);
-  for (let event of ["popupshowing", "popuphiding", "popupshown", "popuphidden"])
-    panel.addEventListener(event, onPanelStateChange);
-
-  panel.addEventListener("click", onPanelClick);
-
-  // Panel content document can be either in panel `viewFrame` or in
-  // a `backgroundFrame` depending on panel state. Listeners are set
-  // on both to avoid setting and removing listeners on panel state changes.
-
-  panel.addEventListener("DOMContentLoaded", onContentReady, true);
-  backgroundFrame.addEventListener("DOMContentLoaded", onContentReady, true);
-
-  panel.addEventListener("load", onContentLoad, true);
-  backgroundFrame.addEventListener("load", onContentLoad, true);
-
-  events.on("document-element-inserted", onContentChange);
-
-  panel.backgroundFrame = backgroundFrame;
-  panel.viewFrame = null;
-
-  // Store event listener on the panel instance so that it won't be GC-ed
-  // while panel is alive.
-  panel.onContentChange = onContentChange;
-
-  return panel;
-}
-exports.make = make;
-
-function attach(panel, document) {
-  document = document || getMostRecentBrowserWindow().document;
-  let container = document.getElementById("mainPopupSet");
-  if (container !== panel.parentNode) {
-    detach(panel);
-    document.getElementById("mainPopupSet").appendChild(panel);
-  }
-}
-exports.attach = attach;
-
-function detach(panel) {
-  if (panel.parentNode) panel.remove();
-}
-exports.detach = detach;
-
-function dispose(panel) {
-  panel.backgroundFrame.remove();
-  panel.backgroundFrame = null;
-  events.off("document-element-inserted", panel.onContentChange);
-  panel.onContentChange = null;
-  detach(panel);
-}
-exports.dispose = dispose;
-
-function style(panel) {
-  /**
-  Injects default OS specific panel styles into content document that is loaded
-  into given panel. Optionally `document` of the browser window can be
-  given to inherit styles from it, by default it will use either panel owner
-  document or an active browser's document. It should not matter though unless
-  Firefox decides to style windows differently base on profile or mode like
-  chrome for example.
-  **/
-
-  try {
-    let document = panel.ownerDocument;
-    let contentDocument = getContentDocument(panel);
-    let window = document.defaultView;
-    let node = document.getAnonymousElementByAttribute(panel, "class",
-                                                       "panel-arrowcontent");
-
-    let { color, fontFamily, fontSize, fontWeight } = window.getComputedStyle(node);
-
-    let style = contentDocument.createElement("style");
-    style.id = "sdk-panel-style";
-    style.textContent = "body { " +
-      "color: " + color + ";" +
-      "font-family: " + fontFamily + ";" +
-      "font-weight: " + fontWeight + ";" +
-      "font-size: " + fontSize + ";" +
-    "}";
-
-    let container = contentDocument.head ? contentDocument.head :
-                    contentDocument.documentElement;
-
-    if (container.firstChild)
-      container.insertBefore(style, container.firstChild);
-    else
-      container.appendChild(style);
-  }
-  catch (error) {
-    console.error("Unable to apply panel style");
-    console.exception(error);
-  }
-}
-exports.style = style;
-
-var getContentFrame = panel => panel.viewFrame || panel.backgroundFrame;
-exports.getContentFrame = getContentFrame;
-
-function getContentDocument(panel) {
-  return getContentFrame(panel).contentDocument;
-}
-exports.getContentDocument = getContentDocument;
-
-function setURL(panel, url) {
-  let frame = getContentFrame(panel);
-  let webNav = getDocShell(frame).QueryInterface(Ci.nsIWebNavigation);
-
-  webNav.loadURI(url ? data.url(url) : "about:blank", 0, null, null, null);
-}
-
-exports.setURL = setURL;
-
-function allowContextMenu(panel, allow) {
-  if (allow) {
-    panel.setAttribute("context", "contentAreaContextMenu");
-  }
-  else {
-    panel.removeAttribute("context");
-  }
-}
-exports.allowContextMenu = allowContextMenu;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui.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': 'experimental',
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-lazyRequire(this, './ui/button/action', 'ActionButton');
-lazyRequire(this, './ui/button/toggle', 'ToggleButton');
-lazyRequire(this, './ui/sidebar', 'Sidebar');
-lazyRequire(this, './ui/frame', 'Frame');
-lazyRequire(this, './ui/toolbar', 'Toolbar');
-
-module.exports = Object.freeze({
-  get ActionButton() { return ActionButton; },
-  get ToggleButton() { return ToggleButton; },
-  get Sidebar() { return Sidebar; },
-  get Frame() { return Frame; },
-  get Toolbar() { return Toolbar; },
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/button/action.js
+++ /dev/null
@@ -1,114 +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',
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-const { Class } = require('../../core/heritage');
-const { merge } = require('../../util/object');
-const { Disposable } = require('../../core/disposable');
-lazyRequire(this, '../../event/core', "on", "off", "emit", "setListeners");
-const { EventTarget } = require('../../event/target');
-lazyRequire(this, '../../view/core', "getNodeView");
-
-lazyRequireModule(this, './view', "view");
-const { buttonContract, stateContract } = require('./contract');
-lazyRequire(this, '../state', "properties", "render", "state", "register",
-            "unregister", "getDerivedStateFor");
-lazyRequire(this, '../state/events', { "events": "stateEvents" });
-lazyRequire(this, './view/events', { "events": "viewEvents" });
-lazyRequireModule(this, '../../event/utils', "events");
-
-lazyRequire(this, '../../tabs/utils', "getActiveTab");
-
-lazyRequire(this, '../../self', { "id": "addonID" });
-lazyRequire(this, '../id', "identify");
-
-const buttons = new Map();
-
-const toWidgetId = id =>
-  ('action-button--' + addonID.toLowerCase()+ '-' + id).
-    replace(/[^a-z0-9_-]/g, '');
-
-const ActionButton = Class({
-  extends: EventTarget,
-  implements: [
-    properties(stateContract),
-    state(stateContract),
-    Disposable
-  ],
-  setup: function setup(options) {
-    let state = merge({
-      disabled: false
-    }, buttonContract(options));
-
-    let id = toWidgetId(options.id);
-
-    register(this, state);
-
-    // Setup listeners.
-    setListeners(this, options);
-
-    buttons.set(id, this);
-
-    view.create(merge({}, state, { id: id }));
-  },
-
-  dispose: function dispose() {
-    let id = toWidgetId(this.id);
-    buttons.delete(id);
-
-    off(this);
-
-    view.dispose(id);
-
-    unregister(this);
-  },
-
-  get id() {
-    return this.state().id;
-  },
-
-  click: function click() { view.click(toWidgetId(this.id)) }
-});
-exports.ActionButton = ActionButton;
-
-identify.define(ActionButton, ({id}) => toWidgetId(id));
-
-getNodeView.define(ActionButton, button =>
-  view.nodeFor(toWidgetId(button.id))
-);
-
-var actionButtonStateEvents = events.filter(stateEvents,
-  e => e.target instanceof ActionButton);
-
-var actionButtonViewEvents = events.filter(viewEvents,
-  e => buttons.has(e.target));
-
-var clickEvents = events.filter(actionButtonViewEvents, e => e.type === 'click');
-var updateEvents = events.filter(actionButtonViewEvents, e => e.type === 'update');
-
-on(clickEvents, 'data', ({target: id, window}) => {
-  let button = buttons.get(id);
-  let state = getDerivedStateFor(button, getActiveTab(window));
-
-  emit(button, 'click', state);
-});
-
-on(updateEvents, 'data', ({target: id, window}) => {
-  render(buttons.get(id), window);
-});
-
-on(actionButtonStateEvents, 'data', ({target, window, state}) => {
-  let id = toWidgetId(target.id);
-  view.setIcon(id, window, state.icon);
-  view.setLabel(id, window, state.label);
-  view.setDisabled(id, window, state.disabled);
-  view.setBadge(id, window, state.badge, state.badgeColor);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/button/contract.js
+++ /dev/null
@@ -1,73 +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 { contract } = require('../../util/contract');
-lazyRequire(this, '../../url', "isLocalURL");
-lazyRequire(this, '../../lang/type', "isNil", "isObject", "isString");
-const { required, either, string, boolean, object, number } = require('../../deprecated/api-utils');
-const { merge } = require('../../util/object');
-const { freeze } = Object;
-
-const isIconSet = (icons) =>
-  Object.keys(icons).
-    every(size => String(size >>> 0) === size && isLocalURL(icons[size]));
-
-var iconSet = {
-  is: either(object, string),
-  map: v => isObject(v) ? freeze(merge({}, v)) : v,
-  ok: v => (isString(v) && isLocalURL(v)) || (isObject(v) && isIconSet(v)),
-  msg: 'The option "icon" must be a local URL or an object with ' +
-    'numeric keys / local URL values pair.'
-}
-
-var id = {
-  is: string,
-  ok: v => /^[a-z-_][a-z0-9-_]*$/i.test(v),
-  msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' +
-        'underscores are allowed).'
-};
-
-var label = {
-  is: string,
-  ok: v => isNil(v) || v.trim().length > 0,
-  msg: 'The option "label" must be a non empty string'
-}
-
-var badge = {
-  is: either(string, number),
-  msg: 'The option "badge" must be a string or a number'
-}
-
-var badgeColor = {
-  is: string,
-  msg: 'The option "badgeColor" must be a string'
-}
-
-var stateContract = contract({
-  label: label,
-  icon: iconSet,
-  disabled: boolean,
-  badge: badge,
-  badgeColor: badgeColor
-});
-
-exports.stateContract = stateContract;
-
-var buttonContract = contract(merge({}, stateContract.rules, {
-  id: required(id),
-  label: required(label),
-  icon: required(iconSet)
-}));
-
-exports.buttonContract = buttonContract;
-
-exports.toggleStateContract = contract(merge({
-  checked: boolean
-}, stateContract.rules));
-
-exports.toggleButtonContract = contract(merge({
-  checked: boolean
-}, buttonContract.rules));
-
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/button/toggle.js
+++ /dev/null
@@ -1,127 +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',
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-const { Class } = require('../../core/heritage');
-lazyRequire(this, '../../util/object', "merge");
-const { Disposable } = require('../../core/disposable');
-lazyRequire(this, '../../event/core', "on", "off", "emit", "setListeners");
-const { EventTarget } = require('../../event/target');
-lazyRequire(this, '../../view/core', "getNodeView");
-
-lazyRequireModule(this, "./view", "view");
-const { toggleButtonContract, toggleStateContract } = require('./contract');
-lazyRequire(this, '../state', "properties", "render", "state", "register", "unregister",
-            "setStateFor", "getStateFor", "getDerivedStateFor");
-lazyRequire(this, '../state/events', { "events": "stateEvents" });
-lazyRequire(this, './view/events', { "events": "viewEvents" });
-lazyRequireModule(this, '../../event/utils', "events");
-
-lazyRequire(this, '../../tabs/utils', "getActiveTab");
-
-lazyRequire(this, '../../self', { "id": "addonID" });
-lazyRequire(this, '../id', "identify");
-
-const buttons = new Map();
-
-const toWidgetId = id =>
-  ('toggle-button--' + addonID.toLowerCase()+ '-' + id).
-    replace(/[^a-z0-9_-]/g, '');
-
-const ToggleButton = Class({
-  extends: EventTarget,
-  implements: [
-    properties(toggleStateContract),
-    state(toggleStateContract),
-    Disposable
-  ],
-  setup: function setup(options) {
-    let state = merge({
-      disabled: false,
-      checked: false
-    }, toggleButtonContract(options));
-
-    let id = toWidgetId(options.id);
-
-    register(this, state);
-
-    // Setup listeners.
-    setListeners(this, options);
-
-    buttons.set(id, this);
-
-    view.create(merge({ type: 'checkbox' }, state, { id: id }));
-  },
-
-  dispose: function dispose() {
-    let id = toWidgetId(this.id);
-    buttons.delete(id);
-
-    off(this);
-
-    view.dispose(id);
-
-    unregister(this);
-  },
-
-  get id() {
-    return this.state().id;
-  },
-
-  click: function click() {
-    return view.click(toWidgetId(this.id));
-  }
-});
-exports.ToggleButton = ToggleButton;
-
-identify.define(ToggleButton, ({id}) => toWidgetId(id));
-
-getNodeView.define(ToggleButton, button =>
-  view.nodeFor(toWidgetId(button.id))
-);
-
-var toggleButtonStateEvents = events.filter(stateEvents,
-  e => e.target instanceof ToggleButton);
-
-var toggleButtonViewEvents = events.filter(viewEvents,
-  e => buttons.has(e.target));
-
-var clickEvents = events.filter(toggleButtonViewEvents, e => e.type === 'click');
-var updateEvents = events.filter(toggleButtonViewEvents, e => e.type === 'update');
-
-on(toggleButtonStateEvents, 'data', ({target, window, state}) => {
-  let id = toWidgetId(target.id);
-
-  view.setIcon(id, window, state.icon);
-  view.setLabel(id, window, state.label);
-  view.setDisabled(id, window, state.disabled);
-  view.setChecked(id, window, state.checked);
-  view.setBadge(id, window, state.badge, state.badgeColor);
-});
-
-on(clickEvents, 'data', ({target: id, window, checked }) => {
-  let button = buttons.get(id);
-  let windowState = getStateFor(button, window);
-
-  let newWindowState = merge({}, windowState, { checked: checked });
-
-  setStateFor(button, window, newWindowState);
-
-  let state = getDerivedStateFor(button, getActiveTab(window));
-
-  emit(button, 'click', state);
-
-  emit(button, 'change', state);
-});
-
-on(updateEvents, 'data', ({target: id, window}) => {
-  render(buttons.get(id), window);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/button/view.js
+++ /dev/null
@@ -1,251 +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',
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-const { Cu } = require('chrome');
-lazyRequire(this, '../../event/core', "on", "off", "emit");
-
-lazyRequire(this, 'sdk/self', "data");
-
-lazyRequire(this, '../../lang/type', "isObject", "isNil");
-
-lazyRequire(this, '../../window/utils', "getMostRecentBrowserWindow");
-lazyRequire(this, '../../private-browsing/utils', "ignoreWindow");
-const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
-
-lazyRequire(this, './view/events', { "events": "viewEvents" });
-
-const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-
-const views = new Map();
-const customizedWindows = new WeakMap();
-
-const buttonListener = {
-  onCustomizeStart: window => {
-    for (let [id, view] of views) {
-      setIcon(id, window, view.icon);
-      setLabel(id, window, view.label);
-    }
-
-    customizedWindows.set(window, true);
-  },
-  onCustomizeEnd: window => {
-    customizedWindows.delete(window);
-
-    for (let [id, ] of views) {
-      let placement = CustomizableUI.getPlacementOfWidget(id);
-
-      if (placement)
-        emit(viewEvents, 'data', { type: 'update', target: id, window: window });
-    }
-  },
-  onWidgetAfterDOMChange: (node, nextNode, container) => {
-    let { id } = node;
-    let view = views.get(id);
-    let window = node.ownerGlobal;
-
-    if (view) {
-      emit(viewEvents, 'data', { type: 'update', target: id, window: window });
-    }
-  }
-};
-
-CustomizableUI.addListener(buttonListener);
-
-require('../../system/unload').when( _ =>
-  CustomizableUI.removeListener(buttonListener)
-);
-
-function getNode(id, window) {
-  let view = views.get(id);
-  return view && view.nodes.get(window);
-};
-
-function isInToolbar(id) {
-  let placement = CustomizableUI.getPlacementOfWidget(id);
-
-  return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
-}
-
-
-function getImage(icon, isInToolbar, pixelRatio) {
-  let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
-  let bestSize = 0;
-  let image = icon;
-
-  if (isObject(icon)) {
-    for (let size of Object.keys(icon)) {
-      size = +size;
-      let offset = targetSize - size;
-
-      if (offset === 0) {
-        bestSize = size;
-        break;
-      }
-
-      let delta = Math.abs(offset) - Math.abs(targetSize - bestSize);
-
-      if (delta < 0)
-        bestSize = size;
-    }
-
-    image = icon[bestSize];
-  }
-
-  if (image.indexOf('./') === 0)
-    return data.url(image.substr(2));
-
-  return image;
-}
-
-function nodeFor(id, window=getMostRecentBrowserWindow()) {
-  return customizedWindows.has(window) ? null : getNode(id, window);
-};
-exports.nodeFor = nodeFor;
-
-function create(options) {
-  let { id, label, icon, type, badge } = options;
-
-  if (views.has(id))
-    throw new Error('The ID "' + id + '" seems already used.');
-
-  CustomizableUI.createWidget({
-    id: id,
-    type: 'custom',
-    removable: true,
-    defaultArea: AREA_NAVBAR,
-    allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
-
-    onBuild: function(document) {
-      let window = document.defaultView;
-
-      let node = document.createElementNS(XUL_NS, 'toolbarbutton');
-
-      let image = getImage(icon, true, window.devicePixelRatio);
-
-      node.setAttribute('id', this.id);
-      node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button');
-      node.setAttribute('type', type);
-      node.setAttribute('label', label);
-      node.setAttribute('tooltiptext', label);
-      node.setAttribute('image', image);
-      node.setAttribute('constrain-size', 'true');
-
-      if (!views.get(id)) {
-        views.set(id, {
-          nodes: new WeakMap(),
-        });
-      }
-
-      let view = views.get(id);
-      Object.assign(view, {
-        area: this.currentArea,
-        icon: icon,
-        label: label
-      });
-
-      if (ignoreWindow(window))
-        node.style.display = 'none';
-      else
-        view.nodes.set(window, node);
-
-      node.addEventListener('command', function(event) {
-        if (views.has(id)) {
-          emit(viewEvents, 'data', {
-            type: 'click',
-            target: id,
-            window: event.view,
-            checked: node.checked
-          });
-        }
-      });
-
-      return node;
-    }
-  });
-};
-exports.create = create;
-
-function dispose(id) {
-  if (!views.has(id)) return;
-
-  views.delete(id);
-  CustomizableUI.destroyWidget(id);
-}
-exports.dispose = dispose;
-
-function setIcon(id, window, icon) {
-  let node = getNode(id, window);
-
-  if (node) {
-    icon = customizedWindows.has(window) ? views.get(id).icon : icon;
-    let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
-
-    node.setAttribute('image', image);
-  }
-}
-exports.setIcon = setIcon;
-
-function setLabel(id, window, label) {
-  let node = nodeFor(id, window);
-
-  if (node) {
-    node.setAttribute('label', label);
-    node.setAttribute('tooltiptext', label);
-  }
-}
-exports.setLabel = setLabel;
-
-function setDisabled(id, window, disabled) {
-  let node = nodeFor(id, window);
-
-  if (node)
-    node.disabled = disabled;
-}
-exports.setDisabled = setDisabled;
-
-function setChecked(id, window, checked) {
-  let node = nodeFor(id, window);
-
-  if (node)
-    node.checked = checked;
-}
-exports.setChecked = setChecked;
-
-function setBadge(id, window, badge, color) {
-  let node = nodeFor(id, window);
-
-  if (node) {
-    // `Array.from` is needed to handle unicode symbol properly:
-    // '𝐀𝐁'.length is 4 where Array.from('𝐀𝐁').length is 2
-    let text = badge == null
-                  ? ''
-                  : Array.from(String(badge)).slice(0, 4).join('');
-
-    node.setAttribute('badge', text);
-
-    let badgeNode = node.ownerDocument.getAnonymousElementByAttribute(node,
-                                        'class', 'toolbarbutton-badge');
-
-    if (badgeNode)
-      badgeNode.style.backgroundColor = color == null ? '' : color;
-  }
-}
-exports.setBadge = setBadge;
-
-function click(id) {
-  let node = nodeFor(id);
-
-  if (node)
-    node.click();
-}
-exports.click = click;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/button/view/events.js
+++ /dev/null
@@ -1,18 +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',
-  'engines': {
-    'Firefox': '*',
-    'SeaMonkey': '*',
-    'Thunderbird': '*'
-  }
-};
-
-var channel = {};
-
-exports.events = channel;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/component.js
+++ /dev/null
@@ -1,182 +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";
-
-// Internal properties not exposed to the public.
-const cache = Symbol("component/cache");
-const writer = Symbol("component/writer");
-const isFirstWrite = Symbol("component/writer/first-write?");
-const currentState = Symbol("component/state/current");
-const pendingState = Symbol("component/state/pending");
-const isWriting = Symbol("component/writing?");
-
-const isntNull = x => x !== null;
-
-const Component = function(options, children) {
-  this[currentState] = null;
-  this[pendingState] = null;
-  this[writer] = null;
-  this[cache] = null;
-  this[isFirstWrite] = true;
-
-  this[Component.construct](options, children);
-}
-Component.Component = Component;
-// Constructs component.
-Component.construct = Symbol("component/construct");
-// Called with `options` and `children` and must return
-// initial state back.
-Component.initial = Symbol("component/initial");
-
-// Function patches current `state` with a given update.
-Component.patch = Symbol("component/patch");
-// Function that replaces current `state` with a passed state.
-Component.reset = Symbol("component/reset");
-
-// Function that must return render tree from passed state.
-Component.render = Symbol("component/render");
-
-// Path of the component with in the mount point.
-Component.path = Symbol("component/path");
-
-Component.isMounted = component => !!component[writer];
-Component.isWriting = component => !!component[isWriting];
-
-// Internal method that mounts component to a writer.
-// Mounts component to a writer.
-Component.mount = (component, write) => {
-  if (Component.isMounted(component)) {
-    throw Error("Can not mount already mounted component");
-  }
-
-  component[writer] = write;
-  Component.write(component);
-
-  if (component[Component.mounted]) {
-    component[Component.mounted]();
-  }
-}
-
-// Unmounts component from a writer.
-Component.unmount = (component) => {
-  if (Component.isMounted(component)) {
-    component[writer] = null;
-    if (component[Component.unmounted]) {
-      component[Component.unmounted]();
-    }
-  } else {
-    console.warn("Unmounting component that is not mounted is redundant");
-  }
-};
- // Method invoked once after inital write occurs.
-Component.mounted = Symbol("component/mounted");
-// Internal method that unmounts component from the writer.
-Component.unmounted = Symbol("component/unmounted");
-// Function that must return true if component is changed
-Component.isUpdated = Symbol("component/updated?");
-Component.update = Symbol("component/update");
-Component.updated = Symbol("component/updated");
-
-const writeChild = base => (child, index) => Component.write(child, base, index)
-Component.write = (component, base, index) => {
-  if (component === null) {
-    return component;
-  }
-
-  if (!(component instanceof Component)) {
-    const path = base ? `${base}${component.key || index}/` : `/`;
-    return Object.assign({}, component, {
-      [Component.path]: path,
-      children: component.children && component.children.
-                                        map(writeChild(path)).
-                                        filter(isntNull)
-    });
-  }
-
-  component[isWriting] = true;
-
-  try {
-
-    const current = component[currentState];
-    const pending = component[pendingState] || current;
-    const isUpdated = component[Component.isUpdated];
-    const isInitial = component[isFirstWrite];
-
-    if (isUpdated(current, pending) || isInitial) {
-      if (!isInitial && component[Component.update]) {
-        component[Component.update](pending, current)
-      }
-
-      // Note: [Component.update] could have caused more updates so can't use
-      // `pending` as `component[pendingState]` may have changed.
-      component[currentState] = component[pendingState] || current;
-      component[pendingState] = null;
-
-      const tree = component[Component.render](component[currentState]);
-      component[cache] = Component.write(tree, base, index);
-      if (component[writer]) {
-        component[writer].call(null, component[cache]);
-      }
-
-      if (!isInitial && component[Component.updated]) {
-        component[Component.updated](current, pending);
-      }
-    }
-
-    component[isFirstWrite] = false;
-
-    return component[cache];
-  } finally {
-    component[isWriting] = false;
-  }
-};
-
-Component.prototype = Object.freeze({
-  constructor: Component,
-
-  [Component.mounted]: null,
-  [Component.unmounted]: null,
-  [Component.update]: null,
-  [Component.updated]: null,
-
-  get state() {
-    return this[pendingState] || this[currentState];
-  },
-
-
-  [Component.construct](settings, items) {
-    const initial = this[Component.initial];
-    const base = initial(settings, items);
-    const options = Object.assign(Object.create(null), base.options, settings);
-    const children = base.children || items || null;
-    const state = Object.assign(Object.create(null), base, {options, children});
-    this[currentState] = state;
-
-    if (this.setup) {
-      this.setup(state);
-    }
-  },
-  [Component.initial](options, children) {
-    return Object.create(null);
-  },
-  [Component.patch](update) {
-    this[Component.reset](Object.assign({}, this.state, update));
-  },
-  [Component.reset](state) {
-    this[pendingState] = state;
-    if (Component.isMounted(this) && !Component.isWriting(this)) {
-      Component.write(this);
-    }
-  },
-
-  [Component.isUpdated](before, after) {
-    return before != after
-  },
-
-  [Component.render](state) {
-    throw Error("Component must implement [Component.render] member");
-  }
-});
-
-module.exports = Component;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/frame.js
+++ /dev/null
@@ -1,15 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Frame } = require("./frame/model");
-
-exports.Frame = Frame;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/frame/model.js
+++ /dev/null
@@ -1,154 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Class } = require("../../core/heritage");
-const { EventTarget } = require("../../event/target");
-lazyRequire(this, "../../event/core", "emit", "off", "setListeners");
-const { Reactor, foldp, send, merges } = require("../../event/utils");
-const { Disposable } = require("../../core/disposable");
-const { OutputPort } = require("../../output/system");
-lazyRequire(this, "../id", "identify");
-const { pairs, object, each } = require("../../util/sequence");
-lazyRequire(this, "diffpatcher/index", "patch", "diff");
-lazyRequire(this, "../../url", "isLocalURL");
-const { compose } = require("../../lang/functional");
-const { contract } = require("../../util/contract");
-const { id: addonID, data: { url: resolve }} = require("../../self");
-const { Frames } = require("../../input/frame");
-require("./view");
-
-
-const output = new OutputPort({ id: "frame-change" });
-const mailbox = new OutputPort({ id: "frame-mailbox" });
-const input = Frames;
-
-
-const makeID = url =>
-  ("frame-" + addonID + "-" + url).
-    split("/").join("-").
-    split(".").join("-").
-    replace(/[^A-Za-z0-9_\-]/g, "");
-
-const validate = contract({
-  name: {
-    is: ["string", "undefined"],
-    ok: x => /^[a-z][a-z0-9-_]+$/i.test(x),
-    msg: "The `option.name` must be a valid alphanumeric string (hyphens and " +
-         "underscores are allowed) starting with letter."
-  },
-  url: {
-    map: x => x.toString(),
-    is: ["string"],
-    ok: x => isLocalURL(x),
-    msg: "The `options.url` must be a valid local URI."
-  }
-});
-
-const Source = function({id, ownerID}) {
-  this.id = id;
-  this.ownerID = ownerID;
-};
-Source.postMessage = ({id, ownerID}, data, origin) => {
-  send(mailbox, object([id, {
-    inbox: {
-      target: {id: id, ownerID: ownerID},
-      timeStamp: Date.now(),
-      data: data,
-      origin: origin
-    }
-  }]));
-};
-Source.prototype.postMessage = function(data, origin) {
-  Source.postMessage(this, data, origin);
-};
-
-const Message = function({type, data, source, origin, timeStamp}) {
-  this.type = type;
-  this.data = data;
-  this.origin = origin;
-  this.timeStamp = timeStamp;
-  this.source = new Source(source);
-};
-
-
-const frames = new Map();
-const sources = new Map();
-
-const Frame = Class({
-  extends: EventTarget,
-  implements: [Disposable, Source],
-  initialize: function(params={}) {
-    const options = validate(params);
-    const id = makeID(options.name || options.url);
-
-    if (frames.has(id))
-      throw Error("Frame with this id already exists: " + id);
-
-    const initial = { id: id, url: resolve(options.url) };
-    this.id = id;
-
-    setListeners(this, params);
-
-    frames.set(this.id, this);
-
-    send(output, object([id, initial]));
-  },
-  get url() {
-    const state = reactor.value[this.id];
-    return state && state.url;
-  },
-  destroy: function() {
-    send(output, object([this.id, null]));
-    frames.delete(this.id);
-    off(this);
-  },
-  // `JSON.stringify` serializes objects based of the return
-  // value of this method. For convinienc we provide this method
-  // to serialize actual state data.
-  toJSON: function() {
-    return { id: this.id, url: this.url };
-  }
-});
-identify.define(Frame, frame => frame.id);
-
-exports.Frame = Frame;
-
-const reactor = new Reactor({
-  onStep: (present, past) => {
-    const delta = diff(past, present);
-
-    each(([id, update]) => {
-      const frame = frames.get(id);
-      if (update) {
-        if (!past[id])
-          emit(frame, "register");
-
-        if (update.outbox)
-          emit(frame, "message", new Message(present[id].outbox));
-
-        each(([ownerID, state]) => {
-          const readyState = state ? state.readyState : "detach";
-          const type = readyState === "loading" ? "attach" :
-                       readyState === "interactive" ? "ready" :
-                       readyState === "complete" ? "load" :
-                       readyState;
-
-          // TODO: Cache `Source` instances somewhere to preserve
-          // identity.
-          emit(frame, type, {type: type,
-                             source: new Source({id: id, ownerID: ownerID})});
-        }, pairs(update.owners));
-      }
-    }, pairs(delta));
-  }
-});
-reactor.run(input);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/frame/view.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <script>
-      // HACK: This is not an ideal way to deliver chrome messages
-      // to an inner frame content but seems only way that would
-      // make `event.source` this (outer frame) window.
-      window.onmessage = function(event) {
-        var frame = document.querySelector("iframe");
-        var content = frame.contentWindow;
-        // If message is posted from chrome it has no `event.source`.
-        if (event.source === null)
-          content.postMessage(event.data, "*");
-      };
-    </script>
-  </head>
-  <body style="overflow: hidden"></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/frame/view.js
+++ /dev/null
@@ -1,145 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Cu, Ci } = require("chrome");
-const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { send, Reactor } = require("../../event/utils");
-const { OutputPort } = require("../../output/system");
-lazyRequire(this, "../../util/sequence", "pairs", "keys", "object", "each");
-const { curry, compose } = require("../../lang/functional");
-lazyRequire(this, "../../window/utils", "getFrameElement", "getOuterId", "getByOuterId", "getOwnerBrowserWindow");
-lazyRequire(this, "diffpatcher/index", "patch", "diff");
-lazyRequire(this, "../../base64", "encode");
-const { Frames } = require("../../input/frame");
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html");
-
-const mailbox = new OutputPort({ id: "frame-mailbox" });
-
-const frameID = frame => frame.id.replace("outer-", "");
-const windowID = compose(getOuterId, getOwnerBrowserWindow);
-
-const getOuterFrame = (windowID, frameID) =>
-    getByOuterId(windowID).document.getElementById("outer-" + frameID);
-
-const listener = ({target, source, data, origin, timeStamp}) => {
-  // And sent received message to outbox so that frame API model
-  // will deal with it.
-  if (source && source !== target) {
-    const frame = getFrameElement(target);
-    const id = frameID(frame);
-    send(mailbox, object([id, {
-      outbox: {type: "message",
-               source: {id: id, ownerID: windowID(frame)},
-               data: data,
-               origin: origin,
-               timeStamp: timeStamp}}]));
-  }
-};
-
-// Utility function used to create frame with a given `state` and
-// inject it into given `window`.
-const registerFrame = ({id, url}) => {
-  CustomizableUI.createWidget({
-    id: id,
-    type: "custom",
-    removable: true,
-    onBuild: document => {
-      let view = document.createElementNS(XUL_NS, "toolbaritem");
-      view.setAttribute("id", id);
-      view.setAttribute("flex", 2);
-
-      let outerFrame = document.createElementNS(XUL_NS, "iframe");
-      outerFrame.setAttribute("src", OUTER_FRAME_URI);
-      outerFrame.setAttribute("id", "outer-" + id);
-      outerFrame.setAttribute("data-is-sdk-outer-frame", true);
-      outerFrame.setAttribute("type", "content");
-      outerFrame.setAttribute("transparent", true);
-      outerFrame.setAttribute("flex", 2);
-      outerFrame.setAttribute("style", "overflow: hidden;");
-      outerFrame.setAttribute("scrolling", "no");
-      outerFrame.setAttribute("disablehistory", true);
-      outerFrame.setAttribute("seamless", "seamless");
-      outerFrame.addEventListener("load", function() {
-        let doc = outerFrame.contentDocument;
-
-        let innerFrame = doc.createElementNS(HTML_NS, "iframe");
-        innerFrame.setAttribute("id", id);
-        innerFrame.setAttribute("src", url);
-        innerFrame.setAttribute("seamless", "seamless");
-        innerFrame.setAttribute("sandbox", "allow-scripts");
-        innerFrame.setAttribute("scrolling", "no");
-        innerFrame.setAttribute("data-is-sdk-inner-frame", true);
-        innerFrame.setAttribute("style", [ "border:none",
-          "position:absolute", "width:100%", "top: 0",
-          "left: 0", "overflow: hidden"].join(";"));
-
-        doc.body.appendChild(innerFrame);
-      }, {capture: true, once: true});
-
-      view.appendChild(outerFrame);
-
-      return view;
-    }
-  });
-};
-
-const unregisterFrame = CustomizableUI.destroyWidget;
-
-const deliverMessage = curry((frameID, data, windowID) => {
-  const frame = getOuterFrame(windowID, frameID);
-  const content = frame && frame.contentWindow;
-
-  if (content)
-    content.postMessage(data, content.location.origin);
-});
-
-const updateFrame = (id, {inbox, owners}, present) => {
-  if (inbox) {
-    const { data, target:{ownerID}, source } = present[id].inbox;
-    if (ownerID)
-      deliverMessage(id, data, ownerID);
-    else
-      each(deliverMessage(id, data), keys(present[id].owners));
-  }
-
-  each(setupView(id), pairs(owners));
-};
-
-const setupView = curry((frameID, [windowID, state]) => {
-  if (state && state.readyState === "loading") {
-    const frame = getOuterFrame(windowID, frameID);
-    // Setup a message listener on contentWindow.
-    frame.contentWindow.addEventListener("message", listener);
-  }
-});
-
-
-const reactor = new Reactor({
-  onStep: (present, past) => {
-    const delta = diff(past, present);
-
-    // Apply frame changes
-    each(([id, update]) => {
-      if (update === null)
-        unregisterFrame(id);
-      else if (past[id])
-        updateFrame(id, update, present);
-      else
-        registerFrame(update);
-    }, pairs(delta));
-  },
-  onEnd: state => each(unregisterFrame, keys(state))
-});
-reactor.run(Frames);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/id.js
+++ /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';
-
-module.metadata = {
-  'stability': 'experimental'
-};
-
-const method = require('../../method/core');
-lazyRequire(this, '../util/uuid', "uuid");
-
-// NOTE: use lang/functional memoize when it is updated to use WeakMap
-function memoize(f) {
-  const memo = new WeakMap();
-
-  return function memoizer(o) {
-    let key = o;
-    if (!memo.has(key))
-      memo.set(key, f.apply(this, arguments));
-    return memo.get(key);
-  };
-}
-
-var identify = method('identify');
-identify.define(Object, memoize(function() { return uuid(); }));
-exports.identify = identify;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar.js
+++ /dev/null
@@ -1,304 +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',
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Class } = require('../core/heritage');
-const { merge } = require('../util/object');
-const { Disposable } = require('../core/disposable');
-lazyRequire(this, '../event/core', "off", "emit", "setListeners");
-const { EventTarget } = require('../event/target');
-lazyRequire(this, '../url', "URL");
-lazyRequire(this, '../self', { "id": "addonID" }, "data");
-lazyRequire(this, '../deprecated/window-utils', 'WindowTracker');
-lazyRequire(this, './sidebar/utils', "isShowing");
-lazyRequire(this, '../window/utils', "isBrowser", "getMostRecentBrowserWindow", "windows", "isWindowPrivate");
-const { ns } = require('../core/namespace');
-lazyRequire(this, '../util/array', { "remove": "removeFromArray" });
-lazyRequire(this, './sidebar/actions', "show", "hide", "toggle");
-lazyRequire(this, '../deprecated/sync-worker', "Worker");
-const { contract: sidebarContract } = require('./sidebar/contract');
-lazyRequire(this, './sidebar/view', "create", "dispose", "updateTitle", "updateURL", "isSidebarShowing", "showSidebar", "hideSidebar");
-lazyRequire(this, '../core/promise', "defer");
-lazyRequire(this, './sidebar/namespace', "models", "views", "viewsFor", "modelFor");
-lazyRequire(this, '../url', "isLocalURL");
-const { ensure } = require('../system/unload');
-lazyRequire(this, './id', "identify");
-lazyRequire(this, '../util/uuid', "uuid");
-lazyRequire(this, '../view/core', "viewFor");
-
-const resolveURL = (url) => url ? data.url(url) : url;
-
-const sidebarNS = ns();
-
-const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
-
-const Sidebar = Class({
-  implements: [ Disposable ],
-  extends: EventTarget,
-  setup: function(options) {
-    // inital validation for the model information
-    let model = sidebarContract(options);
-
-    // save the model information
-    models.set(this, model);
-
-    // generate an id if one was not provided
-    model.id = model.id || addonID + '-' + uuid();
-
-    // further validation for the title and url
-    validateTitleAndURLCombo({}, this.title, this.url);
-
-    const self = this;
-    const internals = sidebarNS(self);
-    const windowNS = internals.windowNS = ns();
-
-    // see bug https://bugzilla.mozilla.org/show_bug.cgi?id=886148
-    ensure(this, 'destroy');
-
-    setListeners(this, options);
-
-    let bars = [];
-    internals.tracker = WindowTracker({
-      onTrack: function(window) {
-        if (!isBrowser(window))
-          return;
-
-        let sidebar = window.document.getElementById('sidebar');
-        let sidebarBox = window.document.getElementById('sidebar-box');
-
-        let bar = create(window, {
-          id: self.id,
-          title: self.title,
-          sidebarurl: self.url
-        });
-        bars.push(bar);
-        windowNS(window).bar = bar;
-
-        bar.addEventListener('command', function() {
-          if (isSidebarShowing(window, self)) {
-            hideSidebar(window, self).catch(() => {});
-            return;
-          }
-
-          showSidebar(window, self);
-        });
-
-        function onSidebarLoad() {
-          // check if the sidebar is ready
-          let isReady = sidebar.docShell && sidebar.contentDocument;
-          if (!isReady)
-            return;
-
-          // check if it is a web panel
-          let panelBrowser = sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID);
-          if (!panelBrowser) {
-            bar.removeAttribute('checked');
-            return;
-          }
-
-          let sbTitle = window.document.getElementById('sidebar-title');
-          function onWebPanelSidebarCreated() {
-            if (panelBrowser.contentWindow.location != resolveURL(model.url) ||
-                sbTitle.value != model.title) {
-              return;
-            }
-
-            let worker = windowNS(window).worker = Worker({
-              window: panelBrowser.contentWindow,
-              injectInDocument: true
-            });
-
-            function onWebPanelSidebarUnload() {
-              windowNS(window).onWebPanelSidebarUnload = null;
-
-              // uncheck the associated menuitem
-              bar.setAttribute('checked', 'false');
-
-              emit(self, 'hide', {});
-              emit(self, 'detach', worker);
-              windowNS(window).worker = null;
-            }
-            windowNS(window).onWebPanelSidebarUnload = onWebPanelSidebarUnload;
-            panelBrowser.contentWindow.addEventListener('unload', onWebPanelSidebarUnload, true);
-
-            // check the associated menuitem
-            bar.setAttribute('checked', 'true');
-
-            function onWebPanelSidebarReady() {
-              panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', onWebPanelSidebarReady);
-              windowNS(window).onWebPanelSidebarReady = null;
-
-              emit(self, 'ready', worker);
-            }
-            windowNS(window).onWebPanelSidebarReady = onWebPanelSidebarReady;
-            panelBrowser.contentWindow.addEventListener('DOMContentLoaded', onWebPanelSidebarReady);
-
-            function onWebPanelSidebarLoad() {
-              panelBrowser.contentWindow.removeEventListener('load', onWebPanelSidebarLoad, true);
-              windowNS(window).onWebPanelSidebarLoad = null;
-
-              // TODO: decide if returning worker is acceptable..
-              //emit(self, 'show', { worker: worker });
-              emit(self, 'show', {});
-            }
-            windowNS(window).onWebPanelSidebarLoad = onWebPanelSidebarLoad;
-            panelBrowser.contentWindow.addEventListener('load', onWebPanelSidebarLoad, true);
-
-            emit(self, 'attach', worker);
-          }
-          windowNS(window).onWebPanelSidebarCreated = onWebPanelSidebarCreated;
-          panelBrowser.addEventListener('DOMWindowCreated', onWebPanelSidebarCreated, true);
-        }
-        windowNS(window).onSidebarLoad = onSidebarLoad;
-        sidebar.addEventListener('load', onSidebarLoad, true); // removed properly
-      },
-      onUntrack: function(window) {
-        if (!isBrowser(window))
-          return;
-
-        // hide the sidebar if it is showing
-        hideSidebar(window, self).catch(() => {});
-
-        // kill the menu item
-        let { bar } = windowNS(window);
-        if (bar) {
-          removeFromArray(viewsFor(self), bar);
-          dispose(bar);
-        }
-
-        // kill listeners
-        let sidebar = window.document.getElementById('sidebar');
-
-        if (windowNS(window).onSidebarLoad) {
-          sidebar && sidebar.removeEventListener('load', windowNS(window).onSidebarLoad, true)
-          windowNS(window).onSidebarLoad = null;
-        }
-
-        let panelBrowser = sidebar && sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID);
-        if (windowNS(window).onWebPanelSidebarCreated) {
-          panelBrowser && panelBrowser.removeEventListener('DOMWindowCreated', windowNS(window).onWebPanelSidebarCreated, true);
-          windowNS(window).onWebPanelSidebarCreated = null;
-        }
-
-        if (windowNS(window).onWebPanelSidebarReady) {
-          panelBrowser && panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', windowNS(window).onWebPanelSidebarReady);
-          windowNS(window).onWebPanelSidebarReady = null;
-        }
-
-        if (windowNS(window).onWebPanelSidebarLoad) {
-          panelBrowser && panelBrowser.contentWindow.removeEventListener('load', windowNS(window).onWebPanelSidebarLoad, true);
-          windowNS(window).onWebPanelSidebarLoad = null;
-        }
-
-        if (windowNS(window).onWebPanelSidebarUnload) {
-          panelBrowser && panelBrowser.contentWindow.removeEventListener('unload', windowNS(window).onWebPanelSidebarUnload, true);
-          windowNS(window).onWebPanelSidebarUnload();
-        }
-      }
-    });
-
-    views.set(this, bars);
-  },
-  get id() {
-    return (modelFor(this) || {}).id;
-  },
-  get title() {
-    return (modelFor(this) || {}).title;
-  },
-  set title(v) {
-    // destroyed?
-    if (!modelFor(this))
-      return;
-    // validation
-    if (typeof v != 'string')
-      throw Error('title must be a string');
-    validateTitleAndURLCombo(this, v, this.url);
-    // do update
-    updateTitle(this, v);
-    return modelFor(this).title = v;
-  },
-  get url() {
-    return (modelFor(this) || {}).url;
-  },
-  set url(v) {
-    // destroyed?
-    if (!modelFor(this))
-      return;
-
-    // validation
-    if (!isLocalURL(v))
-      throw Error('the url must be a valid local url');
-
-    validateTitleAndURLCombo(this, this.title, v);
-
-    // do update
-    updateURL(this, v);
-    modelFor(this).url = v;
-  },
-  show: function(window) {
-    return showSidebar(viewFor(window), this);
-  },
-  hide: function(window) {
-    return hideSidebar(viewFor(window), this);
-  },
-  dispose: function() {
-    const internals = sidebarNS(this);
-
-    off(this);
-
-    // stop tracking windows
-    if (internals.tracker) {
-      internals.tracker.unload();
-    }
-
-    internals.tracker = null;
-    internals.windowNS = null;
-
-    views.delete(this);
-    models.delete(this);
-  }
-});
-exports.Sidebar = Sidebar;
-
-function validateTitleAndURLCombo(sidebar, title, url) {
-  url = resolveURL(url);
-
-  if (sidebar.title == title && sidebar.url == url) {
-    return false;
-  }
-
-  for (let window of windows(null, { includePrivate: true })) {
-    let sidebar = window.document.querySelector('menuitem[sidebarurl="' + url + '"][label="' + title + '"]');
-    if (sidebar) {
-      throw Error('The provided title and url combination is invalid (already used).');
-    }
-  }
-
-  return false;
-}
-
-isShowing.define(Sidebar, isSidebarShowing.bind(null, null));
-show.define(Sidebar, showSidebar.bind(null, null));
-hide.define(Sidebar, hideSidebar.bind(null, null));
-
-identify.define(Sidebar, function(sidebar) {
-  return sidebar.id;
-});
-
-function toggleSidebar(window, sidebar) {
-  // TODO: make sure this is not private
-  window = window || getMostRecentBrowserWindow();
-  if (isSidebarShowing(window, sidebar)) {
-    return hideSidebar(window, sidebar);
-  }
-  return showSidebar(window, sidebar);
-}
-toggle.define(Sidebar, toggleSidebar.bind(null, null));
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar/actions.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';
-
-const method = require('../../../method/core');
-
-exports.show = method('show');
-exports.hide = method('hide');
-exports.toggle = method('toggle');
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar/contract.js
+++ /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 { contract } = require('../../util/contract');
-const { isValidURI, URL, isLocalURL } = require('../../url');
-const { isNil, isObject, isString } = require('../../lang/type');
-
-exports.contract = contract({
-  id: {
-  	is: [ 'string', 'undefined' ],
-  	ok: v => /^[a-z0-9-_]+$/i.test(v),
-    msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' +
-         'underscores are allowed).'
-  },
-  title: {
-  	is: [ 'string' ],
-  	ok: v => v.length
-  },
-  url: {
-    is: [ 'string' ],
-    ok: v => isLocalURL(v),
-    map: v => v.toString(),
-    msg: 'The option "url" must be a valid local URI.'
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar/namespace.js
+++ /dev/null
@@ -1,15 +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 models = exports.models = new WeakMap();
-const views = exports.views = new WeakMap();
-exports.buttons = new WeakMap();
-
-exports.viewsFor = function viewsFor(sidebar) {
-  return views.get(sidebar);
-};
-exports.modelFor = function modelFor(sidebar) {
-  return models.get(sidebar);
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar/utils.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 method = require('../../../method/core');
-
-exports.isShowing = method('isShowing');
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/sidebar/view.js
+++ /dev/null
@@ -1,214 +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',
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-lazyRequire(this, './namespace', "models", "buttons", "views", "viewsFor", "modelFor");
-lazyRequire(this, '../../window/utils', "isBrowser", "getMostRecentBrowserWindow", "windows", "isWindowPrivate");
-lazyRequire(this, '../state', "setStateFor");
-lazyRequire(this, '../../core/promise', "defer");
-lazyRequire(this, '../../self', "isPrivateBrowsingSupported", "data");
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
-
-const resolveURL = (url) => url ? data.url(url) : url;
-
-function create(window, details) {
-  let id = makeID(details.id);
-  let { document } = window;
-
-  if (document.getElementById(id))
-    throw new Error('The ID "' + details.id + '" seems already used.');
-
-  let menuitem = document.createElementNS(XUL_NS, 'menuitem');
-  menuitem.setAttribute('id', id);
-  menuitem.setAttribute('label', details.title);
-  menuitem.setAttribute('sidebarurl', resolveURL(details.sidebarurl));
-  menuitem.setAttribute('checked', 'false');
-  menuitem.setAttribute('type', 'checkbox');
-  menuitem.setAttribute('group', 'sidebar');
-  menuitem.setAttribute('autoCheck', 'false');
-
-  document.getElementById('viewSidebarMenu').appendChild(menuitem);
-
-  return menuitem;
-}
-exports.create = create;
-
-function dispose(menuitem) {
-  menuitem.remove();
-}
-exports.dispose = dispose;
-
-function updateTitle(sidebar, title) {
-  let button = buttons.get(sidebar);
-
-  for (let window of windows(null, { includePrivate: true })) {
-  	let { document } = window;
-
-    // update the button
-    if (button) {
-      setStateFor(button, window, { label: title });
-    }
-
-    // update the menuitem
-    let mi = document.getElementById(makeID(sidebar.id));
-    if (mi) {
-      mi.setAttribute('label', title)
-    }
-
-    // update sidebar, if showing
-    if (isSidebarShowing(window, sidebar)) {
-      document.getElementById('sidebar-title').setAttribute('value', title);
-    }
-  }
-}
-exports.updateTitle = updateTitle;
-
-function updateURL(sidebar, url) {
-  let eleID = makeID(sidebar.id);
-
-  url = resolveURL(url);
-
-  for (let window of windows(null, { includePrivate: true })) {
-    // update the menuitem
-    let mi = window.document.getElementById(eleID);
-    if (mi) {
-      mi.setAttribute('sidebarurl', url)
-    }
-
-    // update sidebar, if showing
-    if (isSidebarShowing(window, sidebar)) {
-      showSidebar(window, sidebar, url);
-    }
-  }
-}
-exports.updateURL = updateURL;
-
-function isSidebarShowing(window, sidebar) {
-  let win = window || getMostRecentBrowserWindow();
-
-  // make sure there is a window
-  if (!win) {
-    return false;
-  }
-
-  // make sure there is a sidebar for the window
-  let sb = win.document.getElementById('sidebar');
-  let sidebarTitle = win.document.getElementById('sidebar-title');
-  if (!(sb && sidebarTitle)) {
-    return false;
-  }
-
-  // checks if the sidebar box is hidden
-  let sbb = win.document.getElementById('sidebar-box');
-  if (!sbb || sbb.hidden) {
-    return false;
-  }
-
-  if (sidebarTitle.value == modelFor(sidebar).title) {
-    let url = resolveURL(modelFor(sidebar).url);
-
-    // checks if the sidebar is loading
-    if (win.gWebPanelURI == url) {
-      return true;
-    }
-
-    // checks if the sidebar loaded already
-    let ele = sb.contentDocument && sb.contentDocument.getElementById(WEB_PANEL_BROWSER_ID);
-    if (!ele) {
-      return false;
-    }
-
-    if (ele.getAttribute('cachedurl') == url) {
-      return true;
-    }
-
-    if (ele && ele.contentWindow && ele.contentWindow.location == url) {
-      return true;
-    }
-  }
-
-  // default
-  return false;
-}
-exports.isSidebarShowing = isSidebarShowing;
-
-function showSidebar(window, sidebar, newURL) {
-  window = window || getMostRecentBrowserWindow();
-
-  let { promise, resolve, reject } = defer();
-  let model = modelFor(sidebar);
-
-  if (!newURL && isSidebarShowing(window, sidebar)) {
-    resolve({});
-  }
-  else if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
-    reject(Error('You cannot show a sidebar on private windows'));
-  }
-  else {
-    sidebar.once('show', resolve);
-
-    let menuitem = window.document.getElementById(makeID(model.id));
-    menuitem.setAttribute('checked', true);
-
-    window.openWebPanel(model.title, resolveURL(newURL || model.url));
-  }
-
-  return promise;
-}
-exports.showSidebar = showSidebar;
-
-
-function hideSidebar(window, sidebar) {
-  window = window || getMostRecentBrowserWindow();
-
-  let { promise, resolve, reject } = defer();
-
-  if (!isSidebarShowing(window, sidebar)) {
-    reject(Error('The sidebar is already hidden'));
-  }
-  else {
-    sidebar.once('hide', resolve);
-
-    // Below was taken from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#4775
-    // the code for window.todggleSideBar()..
-    let { document } = window;
-    let sidebarEle = document.getElementById('sidebar');
-    let sidebarTitle = document.getElementById('sidebar-title');
-    let sidebarBox = document.getElementById('sidebar-box');
-    let sidebarSplitter = document.getElementById('sidebar-splitter');
-    let commandID = sidebarBox.getAttribute('sidebarcommand');
-    let sidebarBroadcaster = document.getElementById(commandID);
-
-    sidebarBox.hidden = true;
-    sidebarSplitter.hidden = true;
-
-    sidebarEle.setAttribute('src', 'about:blank');
-    //sidebarEle.docShell.createAboutBlankContentViewer(null);
-
-    sidebarBroadcaster.removeAttribute('checked');
-    sidebarBox.setAttribute('sidebarcommand', '');
-    sidebarTitle.value = '';
-    sidebarBox.hidden = true;
-    sidebarSplitter.hidden = true;
-
-    // TODO: perhaps this isn't necessary if the window is not most recent?
-    window.gBrowser.selectedBrowser.focus();
-  }
-
-  return promise;
-}
-exports.hideSidebar = hideSidebar;
-
-function makeID(id) {
-  return 'jetpack-sidebar-' + id;
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/state.js
+++ /dev/null
@@ -1,239 +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';
-
-// The Button module currently supports only Firefox.
-// See: https://bugzilla.mozilla.org/show_bug.cgi?id=jetpack-panel-apps
-module.metadata = {
-  'stability': 'experimental',
-  'engines': {
-    'Firefox': '*',
-    'SeaMonkey': '*',
-    'Thunderbird': '*'
-  }
-};
-
-const { Ci } = require('chrome');
-
-const events = require('../event/utils');
-const { events: browserEvents } = require('../browser/events');
-const { events: tabEvents } = require('../tab/events');
-const { events: stateEvents } = require('./state/events');
-
-lazyRequire(this, '../window/utils', "windows", "isInteractive", "getFocusedBrowser");
-lazyRequire(this, '../tabs/utils', "getActiveTab", "getOwnerWindow");
-
-lazyRequire(this, '../private-browsing/utils', "ignoreWindow");
-
-const { freeze } = Object;
-const { merge } = require('../util/object');
-lazyRequire(this, '../event/core', "on", "off", "emit");
-
-lazyRequire(this, '../lang/weak-set', "add", "remove", "has", "clear", "iterator");
-lazyRequire(this, '../lang/type', "isNil");
-
-lazyRequire(this, '../view/core', "viewFor");
-
-const components = new WeakMap();
-
-const ERR_UNREGISTERED = 'The state cannot be set or get. ' +
-  'The object may be not be registered, or may already have been unloaded.';
-
-const ERR_INVALID_TARGET = 'The state cannot be set or get for this target.' +
-  'Only window, tab and registered component are valid targets.';
-
-const isWindow = thing => thing instanceof Ci.nsIDOMWindow;
-const isTab = thing => thing.tagName && thing.tagName.toLowerCase() === 'tab';
-const isActiveTab = thing => isTab(thing) && thing === getActiveTab(getOwnerWindow(thing));
-const isEnumerable = window => !ignoreWindow(window);
-const browsers = _ =>
-  windows('navigator:browser', { includePrivate: true }).filter(isInteractive);
-const getMostRecentTab = _ => getActiveTab(getFocusedBrowser());
-
-function getStateFor(component, target) {
-  if (!isRegistered(component))
-    throw new Error(ERR_UNREGISTERED);
-
-  if (!components.has(component))
-    return null;
-
-  let states = components.get(component);
-
-  if (target) {
-    if (isTab(target) || isWindow(target) || target === component)
-      return states.get(target) || null;
-    else
-      throw new Error(ERR_INVALID_TARGET);
-  }
-
-  return null;
-}
-exports.getStateFor = getStateFor;
-
-function getDerivedStateFor(component, target) {
-  if (!isRegistered(component))
-    throw new Error(ERR_UNREGISTERED);
-
-  if (!components.has(component))
-    return null;
-
-  let states = components.get(component);
-
-  let componentState = states.get(component);
-  let windowState = null;
-  let tabState = null;
-
-  if (target) {
-    // has a target
-    if (isTab(target)) {
-      windowState = states.get(getOwnerWindow(target), null);
-
-      if (states.has(target)) {
-        // we have a tab state
-        tabState = states.get(target);
-      }
-    }
-    else if (isWindow(target) && states.has(target)) {
-      // we have a window state
-      windowState = states.get(target);
-    }
-  }
-
-  return freeze(merge({}, componentState, windowState, tabState));
-}
-exports.getDerivedStateFor = getDerivedStateFor;
-
-function setStateFor(component, target, state) {
-  if (!isRegistered(component))
-    throw new Error(ERR_UNREGISTERED);
-
-  let isComponentState = target === component;
-  let targetWindows = isWindow(target) ? [target] :
-                      isActiveTab(target) ? [getOwnerWindow(target)] :
-                      isComponentState ? browsers() :
-                      isTab(target) ? [] :
-                      null;
-
-  if (!targetWindows)
-    throw new Error(ERR_INVALID_TARGET);
-
-  // initialize the state's map
-  if (!components.has(component))
-    components.set(component, new WeakMap());
-
-  let states = components.get(component);
-
-  if (state === null && !isComponentState) // component state can't be deleted
-    states.delete(target);
-  else {
-    let base = isComponentState ? states.get(target) : null;
-    states.set(target, freeze(merge({}, base, state)));
-  }
-
-  render(component, targetWindows);
-}
-exports.setStateFor = setStateFor;
-
-function render(component, targetWindows) {
-  targetWindows = targetWindows ? [].concat(targetWindows) : browsers();
-
-  for (let window of targetWindows.filter(isEnumerable)) {
-    let tabState = getDerivedStateFor(component, getActiveTab(window));
-
-    emit(stateEvents, 'data', {
-      type: 'render',
-      target: component,
-      window: window,
-      state: tabState
-    });
-
-  }
-}
-exports.render = render;
-
-function properties(contract) {
-  let { rules } = contract;
-  let descriptor = Object.keys(rules).reduce(function(descriptor, name) {
-    descriptor[name] = {
-      get: function() { return getDerivedStateFor(this)[name] },
-      set: function(value) {
-        let changed = {};
-        changed[name] = value;
-
-        setStateFor(this, this, contract(changed));
-      }
-    }
-    return descriptor;
-  }, {});
-
-  return Object.create(Object.prototype, descriptor);
-}
-exports.properties = properties;
-
-function state(contract) {
-  return {
-    state: function state(target, state) {
-      let nativeTarget = target === 'window' ? getFocusedBrowser()
-                          : target === 'tab' ? getMostRecentTab()
-                          : target === this ? null
-                          : viewFor(target);
-
-      if (!nativeTarget && target !== this && !isNil(target))
-        throw new Error(ERR_INVALID_TARGET);
-
-      target = nativeTarget || target;
-
-      // jquery style
-      return arguments.length < 2
-        ? getDerivedStateFor(this, target)
-        : setStateFor(this, target, contract(state))
-    }
-  }
-}
-exports.state = state;
-
-const register = (component, state) => {
-  add(components, component);
-  setStateFor(component, component, state);
-}
-exports.register = register;
-
-const unregister = component => {
-  remove(components, component);
-}
-exports.unregister = unregister;
-
-const isRegistered = component => has(components, component);
-exports.isRegistered = isRegistered;
-
-var tabSelect = events.filter(tabEvents, e => e.type === 'TabSelect');
-var tabClose = events.filter(tabEvents, e => e.type === 'TabClose');
-var windowOpen = events.filter(browserEvents, e => e.type === 'load');
-var windowClose = events.filter(browserEvents, e => e.type === 'close');
-
-var close = events.merge([tabClose, windowClose]);
-var activate = events.merge([windowOpen, tabSelect]);
-
-on(activate, 'data', ({target}) => {
-  let [window, tab] = isWindow(target)
-                        ? [target, getActiveTab(target)]
-                        : [getOwnerWindow(target), target];
-
-  if (ignoreWindow(window)) return;
-
-  for (let component of iterator(components)) {
-    emit(stateEvents, 'data', {
-      type: 'render',
-      target: component,
-      window: window,
-      state: getDerivedStateFor(component, tab)
-    });
-  }
-});
-
-on(close, 'data', function({target}) {
-  for (let component of iterator(components)) {
-    components.get(component).delete(target);
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/state/events.js
+++ /dev/null
@@ -1,18 +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',
-  'engines': {
-    'Firefox': '*',
-    'SeaMonkey': '*',
-    'Thunderbird': '*'
-  }
-};
-
-var channel = {};
-
-exports.events = channel;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/toolbar.js
+++ /dev/null
@@ -1,16 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Toolbar } = require("./toolbar/model");
-require("./toolbar/view");
-
-exports.Toolbar = Toolbar;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/toolbar/model.js
+++ /dev/null
@@ -1,151 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Class } = require("../../core/heritage");
-const { EventTarget } = require("../../event/target");
-const { off, setListeners, emit } = require("../../event/core");
-const { Reactor, foldp, merges, send } = require("../../event/utils");
-const { Disposable } = require("../../core/disposable");
-const { InputPort } = require("../../input/system");
-const { OutputPort } = require("../../output/system");
-const { identify } = require("../id");
-const { pairs, object, map, each } = require("../../util/sequence");
-const { patch, diff } = require("diffpatcher/index");
-const { contract } = require("../../util/contract");
-const { id: addonID } = require("../../self");
-
-// Input state is accumulated from the input received form the toolbar
-// view code & local output. Merging local output reflects local state
-// changes without complete roundloop.
-const input = foldp(patch, {}, new InputPort({ id: "toolbar-changed" }));
-const output = new OutputPort({ id: "toolbar-change" });
-
-// Takes toolbar title and normalizes is to an
-// identifier, also prefixes with add-on id.
-const titleToId = title =>
-  ("toolbar-" + addonID + "-" + title).
-    toLowerCase().
-    replace(/\s/g, "-").
-    replace(/[^A-Za-z0-9_\-]/g, "");
-
-const validate = contract({
-  title: {
-    is: ["string"],
-    ok: x => x.length > 0,
-    msg: "The `option.title` string must be provided"
-  },
-  items: {
-    is:["undefined", "object", "array"],
-    msg: "The `options.items` must be iterable sequence of items"
-  },
-  hidden: {
-    is: ["boolean", "undefined"],
-    msg: "The `options.hidden` must be boolean"
-  }
-});
-
-// Toolbars is a mapping between `toolbar.id` & `toolbar` instances,
-// which is used to find intstance for dispatching events.
-var toolbars = new Map();
-
-const Toolbar = Class({
-  extends: EventTarget,
-  implements: [Disposable],
-  initialize: function(params={}) {
-    const options = validate(params);
-    const id = titleToId(options.title);
-
-    if (toolbars.has(id))
-      throw Error("Toolbar with this id already exists: " + id);
-
-    // Set of the items in the toolbar isn't mutable, as a matter of fact
-    // it just defines desired set of items, actual set is under users
-    // control. Conver test to an array and freeze to make sure users won't
-    // try mess with it.
-    const items = Object.freeze(options.items ? [...options.items] : []);
-
-    const initial = {
-      id: id,
-      title: options.title,
-      // By default toolbars are visible when add-on is installed, unless
-      // add-on authors decides it should be hidden. From that point on
-      // user is in control.
-      collapsed: !!options.hidden,
-      // In terms of state only identifiers of items matter.
-      items: items.map(identify)
-    };
-
-    this.id = id;
-    this.items = items;
-
-    toolbars.set(id, this);
-    setListeners(this, params);
-
-    // Send initial state to the host so it can reflect it
-    // into a user interface.
-    send(output, object([id, initial]));
-  },
-
-  get title() {
-    const state = reactor.value[this.id];
-    return state && state.title;
-  },
-  get hidden() {
-    const state = reactor.value[this.id];
-    return state && state.collapsed;
-  },
-
-  destroy: function() {
-    send(output, object([this.id, null]));
-  },
-  // `JSON.stringify` serializes objects based of the return
-  // value of this method. For convinienc we provide this method
-  // to serialize actual state data. Note: items will also be
-  // serialized so they should probably implement `toJSON`.
-  toJSON: function() {
-    return {
-      id: this.id,
-      title: this.title,
-      hidden: this.hidden,
-      items: this.items
-    };
-  }
-});
-exports.Toolbar = Toolbar;
-identify.define(Toolbar, toolbar => toolbar.id);
-
-const dispose = toolbar => {
-  toolbars.delete(toolbar.id);
-  emit(toolbar, "detach");
-  off(toolbar);
-};
-
-const reactor = new Reactor({
-  onStep: (present, past) => {
-    const delta = diff(past, present);
-
-    each(([id, update]) => {
-      const toolbar = toolbars.get(id);
-
-      // Remove
-      if (!update)
-        dispose(toolbar);
-      // Add
-      else if (!past[id])
-        emit(toolbar, "attach");
-      // Update
-      else
-        emit(toolbar, update.collapsed ? "hide" : "show", toolbar);
-    }, pairs(delta));
-  }
-});
-reactor.run(input);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/ui/toolbar/view.js
+++ /dev/null
@@ -1,248 +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",
-  "engines": {
-    "Firefox": "> 28"
-  }
-};
-
-const { Cu } = require("chrome");
-const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { subscribe, send, Reactor, foldp, lift, merges } = require("../../event/utils");
-const { InputPort } = require("../../input/system");
-const { OutputPort } = require("../../output/system");
-const { Interactive } = require("../../input/browser");
-const { CustomizationInput } = require("../../input/customizable-ui");
-const { pairs, map, isEmpty, object,
-        each, keys, values } = require("../../util/sequence");
-const { curry, flip } = require("../../lang/functional");
-lazyRequire(this, "diffpatcher/index", "patch", "diff");
-const prefs = require("../../preferences/service");
-lazyRequire(this, "../../window/utils", "getByOuterId");
-lazyRequire(this, '../../private-browsing/utils', "ignoreWindow");
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const PREF_ROOT = "extensions.sdk-toolbar-collapsed.";
-
-
-// There are two output ports one for publishing changes that occured
-// and the other for change requests. Later is synchronous and is only
-// consumed here. Note: it needs to be synchronous to avoid race conditions
-// when `collapsed` attribute changes are caused by user interaction and
-// toolbar is destroyed between the ticks.
-const output = new OutputPort({ id: "toolbar-changed" });
-const syncoutput = new OutputPort({ id: "toolbar-change", sync: true });
-
-// Merge disptached changes and recevied changes from models to keep state up to
-// date.
-const Toolbars = foldp(patch, {}, merges([new InputPort({ id: "toolbar-changed" }),
-                                          new InputPort({ id: "toolbar-change" })]));
-const State = lift((toolbars, windows, customizable) =>
-  ({windows: windows, toolbars: toolbars, customizable: customizable}),
-  Toolbars, Interactive, new CustomizationInput());
-
-// Shared event handler that makes `event.target.parent` collapsed.
-// Used as toolbar's close buttons click handler.
-const collapseToolbar = event => {
-  const toolbar = event.target.parentNode;
-  toolbar.collapsed = true;
-};
-
-const parseAttribute = x =>
-  x === "true" ? true :
-  x === "false" ? false :
-  x === "" ? null :
-  x;
-
-// Shared mutation observer that is used to observe `toolbar` node's
-// attribute mutations. Mutations are aggregated in the `delta` hash
-// and send to `ToolbarStateChanged` channel to let model know state
-// has changed.
-const attributesChanged = mutations => {
-  const delta = mutations.reduce((changes, {attributeName, target}) => {
-    const id = target.id;
-    const field = attributeName === "toolbarname" ? "title" : attributeName;
-    let change = changes[id] || (changes[id] = {});
-    change[field] = parseAttribute(target.getAttribute(attributeName));
-    return changes;
-  }, {});
-
-  // Calculate what are the updates from the current state and if there are
-  // any send them.
-  const updates = diff(reactor.value, patch(reactor.value, delta));
-
-  if (!isEmpty(pairs(updates))) {
-    // TODO: Consider sending sync to make sure that there won't be a new
-    // update doing a delete in the meantime.
-    send(syncoutput, updates);
-  }
-};
-
-
-// Utility function creates `toolbar` with a "close" button and returns
-// it back. In addition it set's up a listener and observer to communicate
-// state changes.
-const addView = curry((options, {document, window}) => {
-  if (ignoreWindow(window))
-    return;
-
-  let view = document.createElementNS(XUL_NS, "toolbar");
-  view.setAttribute("id", options.id);
-  view.setAttribute("collapsed", options.collapsed);
-  view.setAttribute("toolbarname", options.title);
-  view.setAttribute("pack", "end");
-  view.setAttribute("customizable", "false");
-  view.setAttribute("style", "padding: 2px 0; max-height: 40px;");
-  view.setAttribute("mode", "icons");
-  view.setAttribute("iconsize", "small");
-  view.setAttribute("context", "toolbar-context-menu");
-  view.setAttribute("class", "chromeclass-toolbar");
-
-  let label = document.createElementNS(XUL_NS, "label");
-  label.setAttribute("value", options.title);
-  label.setAttribute("collapsed", "true");
-  view.appendChild(label);
-
-  let closeButton = document.createElementNS(XUL_NS, "toolbarbutton");
-  closeButton.setAttribute("id", "close-" + options.id);
-  closeButton.setAttribute("class", "close-icon");
-  closeButton.setAttribute("customizable", false);
-  closeButton.addEventListener("command", collapseToolbar);
-
-  view.appendChild(closeButton);
-
-  // In order to have a close button not costumizable, aligned on the right,
-  // leaving the customizable capabilities of Australis, we need to create
-  // a toolbar inside a toolbar.
-  // This is should be a temporary hack, we should have a proper XBL for toolbar
-  // instead. See:
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=982005
-  let toolbar = document.createElementNS(XUL_NS, "toolbar");
-  toolbar.setAttribute("id", "inner-" + options.id);
-  toolbar.setAttribute("defaultset", options.items.join(","));
-  toolbar.setAttribute("customizable", "true");
-  toolbar.setAttribute("style", "-moz-appearance: none; overflow: hidden; border: 0;");
-  toolbar.setAttribute("mode", "icons");
-  toolbar.setAttribute("iconsize", "small");
-  toolbar.setAttribute("context", "toolbar-context-menu");
-  toolbar.setAttribute("flex", "1");
-
-  view.insertBefore(toolbar, closeButton);
-
-  const observer = new document.defaultView.MutationObserver(attributesChanged);
-  observer.observe(view, { attributes: true,
-                           attributeFilter: ["collapsed", "toolbarname"] });
-
-  const toolbox = document.getElementById("navigator-toolbox");
-  toolbox.appendChild(view);
-});
-const viewAdd = curry(flip(addView));
-
-const removeView = curry((id, {document}) => {
-  const view = document.getElementById(id);
-  if (view) view.remove();
-});
-
-const updateView = curry((id, {title, collapsed, isCustomizing}, {document}) => {
-  const view = document.getElementById(id);
-
-  if (!view)
-    return;
-
-  if (title)
-    view.setAttribute("toolbarname", title);
-
-  if (collapsed !== void(0))
-    view.setAttribute("collapsed", Boolean(collapsed));
-
-  if (isCustomizing !== void(0)) {
-    view.querySelector("label").collapsed = !isCustomizing;
-    view.querySelector("toolbar").style.visibility = isCustomizing
-                                                ? "hidden" : "visible";
-  }
-});
-
-const viewUpdate = curry(flip(updateView));
-
-// Utility function used to register toolbar into CustomizableUI.
-const registerToolbar = state => {
-  // If it's first additon register toolbar as customizableUI component.
-  CustomizableUI.registerArea("inner-" + state.id, {
-    type: CustomizableUI.TYPE_TOOLBAR,
-    legacy: true,
-    defaultPlacements: [...state.items]
-  });
-};
-// Utility function used to unregister toolbar from the CustomizableUI.
-const unregisterToolbar = CustomizableUI.unregisterArea;
-
-const reactor = new Reactor({
-  onStep: (present, past) => {
-    const delta = diff(past, present);
-
-    each(([id, update]) => {
-      // If update is `null` toolbar is removed, in such case
-      // we unregister toolbar and remove it from each window
-      // it was added to.
-      if (update === null) {
-        unregisterToolbar("inner-" + id);
-        each(removeView(id), values(past.windows));
-
-        send(output, object([id, null]));
-      }
-      else if (past.toolbars[id]) {
-        // If `collapsed` state for toolbar was updated, persist
-        // it for a future sessions.
-        if (update.collapsed !== void(0))
-          prefs.set(PREF_ROOT + id, update.collapsed);
-
-        // Reflect update in each window it was added to.
-        each(updateView(id, update), values(past.windows));
-
-        send(output, object([id, update]));
-      }
-      // Hack: Mutation observers are invoked async, which means that if
-      // client does `hide(toolbar)` & then `toolbar.destroy()` by the
-      // time we'll get update for `collapsed` toolbar will be removed.
-      // For now we check if `update.id` is present which will be undefined
-      // in such cases.
-      else if (update.id) {
-        // If it is a new toolbar we create initial state by overriding
-        // `collapsed` filed with value persisted in previous sessions.
-        const state = patch(update, {
-          collapsed: prefs.get(PREF_ROOT + id, update.collapsed),
-        });
-
-        // Register toolbar and add it each window known in the past
-        // (note that new windows if any will be handled in loop below).
-        registerToolbar(state);
-        each(addView(state), values(past.windows));
-
-        send(output, object([state.id, state]));
-      }
-    }, pairs(delta.toolbars));
-
-    // Add views to every window that was added.
-    each(window => {
-      if (window)
-        each(viewAdd(window), values(past.toolbars));
-    }, values(delta.windows));
-
-    each(([id, isCustomizing]) => {
-      each(viewUpdate(getByOuterId(id), {isCustomizing: !!isCustomizing}),
-        keys(present.toolbars));
-
-    }, pairs(delta.customizable))
-  },
-  onEnd: state => {
-    each(id => {
-      unregisterToolbar("inner-" + id);
-      each(removeView(id), values(state.windows));
-    }, keys(state.toolbars));
-  }
-});
-reactor.run(State);