Merge f-t to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 09 May 2015 14:36:54 -0700
changeset 274540 77d92f6d76797fbbb80819a13ff4dbd6147aa328
parent 274484 66a17a1af78f2a533b4ba8eeb0139a011a3e3583 (current diff)
parent 274539 5177b647d87a212c4d2485c1df17df4234196923 (diff)
child 274545 e8362616653bb51c1fd7b4c3123033112448f979
child 274553 371cbdcc9562ebef9938430a2ada358280a9273a
child 274559 8ab431cf4a279a935353233d9d208a99551b03e2
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone40.0a1
first release with
nightly linux32
77d92f6d7679 / 40.0a1 / 20150510030207 / files
nightly linux64
77d92f6d7679 / 40.0a1 / 20150510030207 / files
nightly mac
77d92f6d7679 / 40.0a1 / 20150510030207 / files
nightly win32
77d92f6d7679 / 40.0a1 / 20150510030207 / files
nightly win64
77d92f6d7679 / 40.0a1 / 20150510030207 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge f-t to m-c, a=merge
addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper
addon-sdk/source/examples/annotator/README.md
addon-sdk/source/examples/annotator/data/annotation/annotation.html
addon-sdk/source/examples/annotator/data/annotation/annotation.js
addon-sdk/source/examples/annotator/data/editor/annotation-editor.html
addon-sdk/source/examples/annotator/data/editor/annotation-editor.js
addon-sdk/source/examples/annotator/data/jquery-1.4.2.min.js
addon-sdk/source/examples/annotator/data/list/annotation-list.css
addon-sdk/source/examples/annotator/data/list/annotation-list.html
addon-sdk/source/examples/annotator/data/list/annotation-list.js
addon-sdk/source/examples/annotator/data/matcher.js
addon-sdk/source/examples/annotator/data/selector.js
addon-sdk/source/examples/annotator/data/widget/pencil-off.png
addon-sdk/source/examples/annotator/data/widget/pencil-on.png
addon-sdk/source/examples/annotator/data/widget/widget.js
addon-sdk/source/examples/annotator/lib/main.js
addon-sdk/source/examples/annotator/package.json
addon-sdk/source/examples/annotator/tests/test-main.js
addon-sdk/source/examples/library-detector/README.md
addon-sdk/source/examples/library-detector/data/icons/closure.ico
addon-sdk/source/examples/library-detector/data/icons/jquery.ico
addon-sdk/source/examples/library-detector/data/icons/jquery_ui.ico
addon-sdk/source/examples/library-detector/data/icons/modernizr.ico
addon-sdk/source/examples/library-detector/data/icons/mootools.png
addon-sdk/source/examples/library-detector/data/icons/yui.ico
addon-sdk/source/examples/library-detector/data/library-detector.js
addon-sdk/source/examples/library-detector/data/panel.html
addon-sdk/source/examples/library-detector/data/widget.html
addon-sdk/source/examples/library-detector/lib/main.js
addon-sdk/source/examples/library-detector/package.json
addon-sdk/source/examples/library-detector/test/test-main.js
addon-sdk/source/lib/sdk/deprecated/cortex.js
addon-sdk/source/lib/sdk/deprecated/errors.js
addon-sdk/source/lib/sdk/deprecated/events.js
addon-sdk/source/lib/sdk/deprecated/light-traits.js
addon-sdk/source/lib/sdk/deprecated/list.js
addon-sdk/source/lib/sdk/deprecated/symbiont.js
addon-sdk/source/lib/sdk/deprecated/traits-worker.js
addon-sdk/source/lib/sdk/deprecated/traits.js
addon-sdk/source/lib/sdk/deprecated/traits/core.js
addon-sdk/source/lib/sdk/input/window.js
addon-sdk/source/lib/sdk/test/tmp-file.js
addon-sdk/source/lib/sdk/widget.js
addon-sdk/source/lib/sdk/windows/dom.js
addon-sdk/source/lib/sdk/windows/tabs-firefox.js
addon-sdk/source/test/addons/symbiont/data/test-trusted-document.html
addon-sdk/source/test/addons/symbiont/main.js
addon-sdk/source/test/addons/symbiont/package.json
addon-sdk/source/test/fixtures/test-content-symbiont.js
addon-sdk/source/test/test-content-loader.js
addon-sdk/source/test/test-content-symbiont.js
addon-sdk/source/test/test-cortex.js
addon-sdk/source/test/test-deprecated-list.js
addon-sdk/source/test/test-errors.js
addon-sdk/source/test/test-events.js
addon-sdk/source/test/test-light-traits.js
addon-sdk/source/test/test-tmp-file.js
addon-sdk/source/test/test-tmp-file.txt
addon-sdk/source/test/test-traits-core.js
addon-sdk/source/test/test-traits.js
addon-sdk/source/test/test-widget.js
addon-sdk/source/test/traits/descriptor-tests.js
addon-sdk/source/test/traits/inheritance-tests.js
addon-sdk/source/test/traits/object-tests.js
browser/components/pocket/jar.mn
browser/components/pocket/main.js
browser/components/pocket/panels/css/normalize.css
browser/components/pocket/panels/css/saved.css
browser/components/pocket/panels/img/pocketsignup_devices@1x.png
browser/components/pocket/panels/img/pocketsignup_devices@2x.png
browser/components/pocket/panels/img/pocketsignup_hero@1x.png
browser/components/pocket/panels/img/pocketsignup_hero@2x.png
browser/components/pocket/panels/js/dictionary.js
browser/components/pocket/panels/js/messages.js
browser/components/pocket/panels/js/saved.js
browser/components/pocket/panels/js/signup.js
browser/components/pocket/panels/js/tmpl.js
browser/components/pocket/panels/js/vendor/jquery.tokeninput.min.js
browser/components/pocket/panels/tmpl/saved_shell.handlebars
browser/components/pocket/pktApi.js
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -24,26 +24,18 @@ EXTRA_JS_MODULES.sdk.system += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk":
     EXTRA_JS_MODULES.commonjs.method.test += [
         'source/lib/method/test/browser.js',
         'source/lib/method/test/common.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.deprecated += [
         'source/lib/sdk/deprecated/api-utils.js',
-        'source/lib/sdk/deprecated/cortex.js',
-        'source/lib/sdk/deprecated/errors.js',
-        'source/lib/sdk/deprecated/events.js',
-        'source/lib/sdk/deprecated/light-traits.js',
-        'source/lib/sdk/deprecated/list.js',
         'source/lib/sdk/deprecated/memory.js',
-        'source/lib/sdk/deprecated/symbiont.js',
         'source/lib/sdk/deprecated/sync-worker.js',
-        'source/lib/sdk/deprecated/traits-worker.js',
-        'source/lib/sdk/deprecated/traits.js',
         'source/lib/sdk/deprecated/unit-test-finder.js',
         'source/lib/sdk/deprecated/unit-test.js',
         'source/lib/sdk/deprecated/window-utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.frame += [
         'source/lib/sdk/frame/hidden-frame.js',
         'source/lib/sdk/frame/utils.js',
@@ -86,17 +78,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
     EXTRA_JS_MODULES.commonjs.sdk.test += [
         'source/lib/sdk/test/assert.js',
         'source/lib/sdk/test/harness.js',
         'source/lib/sdk/test/httpd.js',
         'source/lib/sdk/test/loader.js',
         'source/lib/sdk/test/memory.js',
         'source/lib/sdk/test/options.js',
         'source/lib/sdk/test/runner.js',
-        'source/lib/sdk/test/tmp-file.js',
         'source/lib/sdk/test/utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.ui += [
         'source/lib/sdk/ui/component.js',
         'source/lib/sdk/ui/frame.js',
         'source/lib/sdk/ui/id.js',
         'source/lib/sdk/ui/sidebar.js',
@@ -123,22 +114,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
         'source/lib/sdk/window/browser.js',
         'source/lib/sdk/window/events.js',
         'source/lib/sdk/window/helpers.js',
         'source/lib/sdk/window/namespace.js',
         'source/lib/sdk/window/utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.windows += [
-        'source/lib/sdk/windows/dom.js',
         'source/lib/sdk/windows/fennec.js',
         'source/lib/sdk/windows/firefox.js',
         'source/lib/sdk/windows/observer.js',
         'source/lib/sdk/windows/tabs-fennec.js',
-        'source/lib/sdk/windows/tabs-firefox.js',
     ]
 
 EXTRA_JS_MODULES.commonjs += [
     'source/lib/index.js',
     'source/lib/test.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.dev += [
@@ -178,20 +167,32 @@ EXTRA_JS_MODULES.commonjs.diffpatcher.te
 EXTRA_JS_MODULES.commonjs.framescript += [
     'source/lib/framescript/content.jsm',
     'source/lib/framescript/context-menu.js',
     'source/lib/framescript/FrameScriptManager.jsm',
     'source/lib/framescript/manager.js',
     'source/lib/framescript/util.js',
 ]
 
+EXTRA_JS_MODULES.commonjs['jetpack-id'] += [
+    'source/lib/jetpack-id/index.js',
+]
+
 EXTRA_JS_MODULES.commonjs.method += [
     'source/lib/method/core.js',
 ]
 
+EXTRA_JS_MODULES.commonjs['mozilla-toolkit-versioning'] += [
+    'source/lib/mozilla-toolkit-versioning/index.js',
+]
+
+EXTRA_JS_MODULES.commonjs['mozilla-toolkit-versioning'].lib += [
+    'source/lib/mozilla-toolkit-versioning/lib/utils.js',
+]
+
 EXTRA_JS_MODULES.commonjs.node += [
     'source/lib/node/os.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk += [
     'source/lib/sdk/base64.js',
     'source/lib/sdk/clipboard.js',
     'source/lib/sdk/context-menu.js',
@@ -213,17 +214,16 @@ EXTRA_JS_MODULES.commonjs.sdk += [
     'source/lib/sdk/simple-prefs.js',
     'source/lib/sdk/simple-storage.js',
     'source/lib/sdk/system.js',
     'source/lib/sdk/tabs.js',
     'source/lib/sdk/test.js',
     'source/lib/sdk/timers.js',
     'source/lib/sdk/ui.js',
     'source/lib/sdk/url.js',
-    'source/lib/sdk/widget.js',
     'source/lib/sdk/windows.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.addon += [
     'source/lib/sdk/addon/bootstrap.js',
     'source/lib/sdk/addon/events.js',
     'source/lib/sdk/addon/host.js',
     'source/lib/sdk/addon/installer.js',
@@ -272,20 +272,16 @@ EXTRA_JS_MODULES.commonjs.sdk.core += [
     'source/lib/sdk/core/promise.js',
     'source/lib/sdk/core/reference.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.deprecated.events += [
     'source/lib/sdk/deprecated/events/assembler.js',
 ]
 
-EXTRA_JS_MODULES.commonjs.sdk.deprecated.traits += [
-    'source/lib/sdk/deprecated/traits/core.js',
-]
-
 EXTRA_JS_MODULES.commonjs.sdk.dom += [
     'source/lib/sdk/dom/events.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.dom.events += [
     'source/lib/sdk/dom/events/keys.js',
 ]
 
@@ -301,17 +297,16 @@ EXTRA_JS_MODULES.commonjs.sdk.fs += [
     'source/lib/sdk/fs/path.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.input += [
     'source/lib/sdk/input/browser.js',
     'source/lib/sdk/input/customizable-ui.js',
     'source/lib/sdk/input/frame.js',
     'source/lib/sdk/input/system.js',
-    'source/lib/sdk/input/window.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.io += [
     'source/lib/sdk/io/buffer.js',
     'source/lib/sdk/io/byte-streams.js',
     'source/lib/sdk/io/data.js',
     'source/lib/sdk/io/file.js',
     'source/lib/sdk/io/fs.js',
--- a/addon-sdk/source/.gitignore
+++ b/addon-sdk/source/.gitignore
@@ -4,17 +4,33 @@ testdocs.tgz
 jetpack-sdk-docs.tgz
 .test_tmp/
 doc/dev-guide/
 doc/index.html
 doc/modules/
 doc/status.md5
 packages/*
 node_modules
+cache
 
 # Python
 *.pyc
 
 # OSX
 *.DS_Store
 
 # Windows
 *Thumbs.db
+
+# Ignore subtrees
+
+# git@github.com:jsantell/jetpack-id.git
+lib/jetpack-id/*
+!lib/jetpack-id/index.js
+!lib/jetpack-id/package.json
+
+# git@github.com:jsantell/mozilla-toolkit-versioning.git
+lib/mozilla-toolkit-versioning/*
+!lib/mozilla-toolkit-versioning/index.js
+!lib/mozilla-toolkit-versioning/lib
+lib/mozilla-toolkit-versioning/lib/*
+!lib/mozilla-toolkit-versioning/lib/*.js
+!lib/mozilla-toolkit-versioning/package.json
--- a/addon-sdk/source/.jpmignore
+++ b/addon-sdk/source/.jpmignore
@@ -3,15 +3,16 @@ mapping.json
 CONTRIBUTING.md
 @addon-sdk.xpi
 .*
 app-extension/
 bin/
 modules/
 node_modules/
 examples/
+cache/
 
 # Python
 python-lib/
 *.pyc
 
 # Windows
 *Thumbs.db
--- a/addon-sdk/source/.travis.yml
+++ b/addon-sdk/source/.travis.yml
@@ -1,24 +1,26 @@
 sudo: false
 language: node_js
 node_js:
-  - "iojs"
   - "0.10"
 
+env:
+  - JPM_FX_DEBUG=0
+  - JPM_FX_DEBUG=1
+
 notifications:
   irc: "irc.mozilla.org#jetpack"
 
+cache:
+  directories:
+  - cache
+
 before_install:
   - "export DISPLAY=:99.0"
-  - "sh -e /etc/init.d/xvfb start"
   - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR"
 
 before_script:
-  - npm install mozilla-download -g
-  - npm install jpm -g
-  - cd ..
-  - mozilla-download --branch nightly -c prerelease --host ftp.mozilla.org firefox
+  - npm install fx-download -g
+  - npm install gulp -g
+  - bash bin/fx-download.sh
   - export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox
   - cd $TRAVIS_BUILD_DIR
-
-script:
-  - npm test
--- a/addon-sdk/source/CONTRIBUTING.md
+++ b/addon-sdk/source/CONTRIBUTING.md
@@ -1,43 +1,43 @@
 ##  Overview
 
 - Changes should follow the [design guidelines], as well as the [coding style guide]
-- All changes must be accompanied by tests
-- In order to land, changes must have been reviewed by one of the Jetpack reviewers
-- Changes should have additional API review when needed
-- Changes should have additional review from a Mozilla platform domain-expert when needed
+- All changes need tests
+- In order to land, changes need a review by one of the Jetpack reviewers
+- Changes may need an API review
+- Changes may need a review from a Mozilla platform domain-expert
 
 If you have questions, ask in [#jetpack on IRC][jetpack irc channel] or on the [Jetpack mailing list].
 
 ## How to Make Code Contributions
 
-If you'd like to contribute the Jetpack project, follow these steps:
+To write code for the Jetpack project, follow these steps:
 
-1. Look for your issue in the list of [bugs already filed][open bugs]. If you want to contribute, but don't already know what you want to do, we keep a list of [good first bugs].
-2. If no bug exists, [submit one][submit bug].
+1. Look for your issue in the list of [bugs already filed][open bugs]. If you don't already know what you want to do, we keep a list of [good first bugs].
+2. If no bug exists, [make one][make bug].
 3. Get the code: get a [GitHub][GitHub] account, fork the [Add-on SDK repo][Add-on SDK repo], and clone it to your machine.
 4. Make your changes. Changes should follow the [design guidelines] as well as the [coding style guide].
 5. Write tests: [unit testing introduction][test intro], [unit testing API][test API].
 6. Submit a pull request with the changes and a title in the form of `Bug XXX - description`.
 7. Make sure that [Travis CI](https://travis-ci.org/mozilla/addon-sdk/branches) tests are passing for your branch.
 8. Copy the pull request link from GitHub and paste it in as an attachment to the bug.
 9. Each pull request should ideally contain only one commit, so squash the commits if necessary.
 10. Flag the attachment for code review from one of the Jetpack reviewers listed below. This step is optional, but could speed things up.
 11. Address any issues mentioned in the review.
 
-Finally, once review is approved, a team member will do the merging
+Finally, once the review is positive, a team member will do the merging
 
 ## Good First Bugs
 
 There is a list of [good first bugs here][good first bugs].
 
 ## Reviewers
 
-All changes must be reviewed by someone on the Jetpack review crew:
+All changes need a review by someone on the Jetpack review crew:
 
 - [@mossop]
 - [@gozala]
 - [@ZER0]
 - [@erikvold]
 - [@jsantell]
 - [@zombie]
 
@@ -45,17 +45,17 @@ For review of Mozilla platform usage and
 [@0c0w3], or [@mossop] to find the domain expert.
 
 For API and developer ergonomics review, ask [@gozala].
 
 [design guidelines]:https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines
 [jetpack irc channel]:irc://irc.mozilla.org/#jetpack
 [Jetpack mailing list]:http://groups.google.com/group/mozilla-labs-jetpack
 [open bugs]:https://bugzilla.mozilla.org/buglist.cgi?quicksearch=product%3ASDK
-[submit bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general
+[make bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general
 [test intro]:https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing
 [test API]:https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert
 [coding style guide]:https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
 [Add-on SDK repo]:https://github.com/mozilla/addon-sdk
 [GitHub]:https://github.com/
 [good first bugs]:https://bugzilla.mozilla.org/buglist.cgi?list_id=7345714&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&query_based_on=jetpack-good-1st-bugs&status_whiteboard_type=allwordssubstr&query_format=advanced&status_whiteboard=[good%20first%20bug]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&product=Add-on%20SDK&known_name=jetpack-good-1st-bugs
 
 [@mossop]:https://github.com/mossop/
--- a/addon-sdk/source/README.md
+++ b/addon-sdk/source/README.md
@@ -1,31 +1,32 @@
 # Mozilla Add-on SDK [![Build Status](https://travis-ci.org/mozilla/addon-sdk.png)](https://travis-ci.org/mozilla/addon-sdk)
 
 Using the Add-on SDK you can create Firefox add-ons using standard Web technologies: JavaScript, HTML, and CSS. The SDK includes JavaScript APIs which you can use to create add-ons, and tools for creating, running, testing, and packaging add-ons.
 
 If you find a problem, please [report the bug here](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK).
 
 ## Developing Add-ons
 
-These resources should provide some help:
+These resources offer some help:
 
 * [Add-on SDK Documentation](https://developer.mozilla.org/en-US/Add-ons/SDK)
 * [Community Developed Modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules)
 * [Jetpack FAQ](https://wiki.mozilla.org/Jetpack/FAQ)
 * [StackOverflow Questions](http://stackoverflow.com/questions/tagged/firefox-addon-sdk)
 * [Mailing List](https://wiki.mozilla.org/Jetpack#Mailing_list)
 * #jetpack on irc.mozilla.org
 
 ## Contributing Code
 
-Please read these two guides if you wish to contribute some patches to the addon-sdk:
+Please read these two guides if you wish to make some patches to the addon-sdk:
 
 * [Contribute Guide](https://github.com/mozilla/addon-sdk/blob/master/CONTRIBUTING.md)
 * [Style Guide](https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide)
 
 ## Issues
 
 We use [bugzilla](https://bugzilla.mozilla.org/) as our issue tracker, here are some useful links:
 
 * [File a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK)
 * [Open bugs](https://bugzilla.mozilla.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&product=Add-on%20SDK&query_format=advanced&order=priority)
 * [Good first bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+first+bug]&&resolution=---&product=Add-on+SDK)
+* [Good next bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+next+bug]&&resolution=---&product=Add-on+SDK)
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/fx-download.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ "$JPM_FX_DEBUG" = "1" ]; then
+  fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox --debug
+else
+  fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox
+fi
old mode 100644
new mode 100755
--- a/addon-sdk/source/bin/jpm-test.js
+++ b/addon-sdk/source/bin/jpm-test.js
@@ -6,23 +6,27 @@
 var Promise = require("promise");
 var Mocha = require("mocha");
 var mocha = new Mocha({
   ui: "bdd",
   reporter: "spec",
   timeout: 900000
 });
 
+var isDebug = require("./node-scripts/utils").isDebug;
+
 exports.run = function(type) {
   return new Promise(function(resolve) {
     type = type || "";
     [
-      (/^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
-      (/^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
+      (!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
+      (!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
       (/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
+      (!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"),
+      (!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"),
     ].sort().forEach(function(filepath) {
       filepath && mocha.addFile(filepath);
     })
 
     mocha.run(function(failures) {
       resolve(failures);
     });
   });
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/apply-patch.js
@@ -0,0 +1,64 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var path = require("path");
+var cp = require("child_process");
+var fs = require("fs");
+var Promise = require("promise");
+var patcher = require("patch-editor");
+var readParam = require("./utils").readParam;
+
+var isKeeper = /\/addon-sdk\/source/;
+
+function apply(options) {
+  return clean(options).then(function() {
+    return new Promise(function(resolve) {
+      var patch = path.resolve(readParam("patch"));
+      var proc = cp.spawn("git", ["apply", patch]);
+      proc.stdout.pipe(process.stdout);
+      proc.stderr.pipe(process.stderr);
+      proc.on("close", resolve);
+    });
+  });
+}
+exports.apply = apply;
+
+function clean(options) {
+  return new Promise(function(resolve) {
+    var patch = path.resolve(readParam("patch"));
+    if (!patch) {
+      throw new Error("no --patch was provided.");
+    }
+    console.log("Cleaning patch " + patch);
+
+    patcher.getChunks({ patch: patch }).then(function(chunks) {
+      var keepers = [];
+
+      for (var i = chunks.length - 1; i >= 0; i--) {
+        var chunk = chunks[i];
+        var files = chunk.getFilesChanged();
+
+        // check if the file changed is related to the addon-sdk/source directory
+        var keepIt = files.map(function(file) {
+          return (isKeeper.test(file));
+        }).reduce(function(prev, curr) {
+          return prev || curr;
+        }, false);
+
+        if (keepIt) {
+          keepers.push(chunk);
+        }
+      }
+
+      var contents = "\n" + keepers.join("\n") + "\n";
+      contents = contents.replace(/\/addon-sdk\/source/g, "");
+
+      fs.writeFileSync(patch, contents, { encoding: "utf8" });
+
+      console.log("Done cleaning patch.");
+    }).then(resolve).catch(console.error);
+  });
+}
+exports.clean = clean;
--- a/addon-sdk/source/bin/node-scripts/test.addons.js
+++ b/addon-sdk/source/bin/node-scripts/test.addons.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var utils = require("./utils");
 var path = require("path");
 var fs = require("fs");
 var jpm = utils.run;
 var readParam = utils.readParam;
+var isDebug = utils.isDebug;
 
 var addonsPath = path.join(__dirname, "..", "..", "test", "addons");
 
 var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
 var filterPattern = readParam("filter");
 
 describe("jpm test sdk addons", function () {
   fs.readdirSync(addonsPath)
@@ -35,14 +36,22 @@ describe("jpm test sdk addons", function
   });
 });
 
 function fileFilter(root, file) {
   var matcher = filterPattern && new RegExp(filterPattern);
   if (/^(l10n-properties|simple-prefs|page-mod-debugger)/.test(file)) {
     return false;
   }
+
+  // filter additional add-ons when using debug builds
+  if (isDebug) {
+    if (/^(chrome|e10s)/.test(file)) {
+      return false;
+    }
+  }
+
   if (matcher && !matcher.test(file)) {
     return false;
   }
   var stat = fs.statSync(path.join(root, file))
   return (stat && stat.isDirectory());
 }
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/test.docs.js
@@ -0,0 +1,145 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var createHash = require('crypto').createHash;
+var fs = require("fs");
+var fsExtra = require("fs-extra")
+var path = require("path");
+var Promise = require("promise");
+var chai = require("chai");
+var expect = chai.expect;
+var teacher = require("teacher");
+
+var rootURI = path.join(__dirname, "..", "..");
+
+// get a list of words that fail spell check but are still acceptable
+var NEW_WORDS = fs.readFileSync(path.join(__dirname, "words.txt")).toString().trim().split("\n");
+
+var CACHE_PATH = path.join(__dirname, "..", "..", "cache", "spellchecks.json");
+
+var CACHE = {};
+
+try {
+  CACHE = JSON.parse(fs.readFileSync(CACHE_PATH).toString());
+}
+catch (e) {}
+
+function md5(str) {
+  return createHash("md5").update(str).digest("utf8");
+}
+
+function addCacheHash(hash) {
+  CACHE[hash] = true;
+  fsExtra.ensureFileSync(CACHE_PATH);
+  fsExtra.writeJSONSync(CACHE_PATH, CACHE);
+}
+
+describe("Spell Checking", function () {
+  it("Spellcheck CONTRIBUTING.md", function (done) {
+   var readme = path.join(rootURI, "CONTRIBUTING.md");
+
+    fs.readFile(readme, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var hash = md5(text);
+
+      // skip this test if we know we have done the
+      // exact same test with positive results before
+      if (CACHE[hash]) {
+        expect(CACHE[hash]).to.be.equal(true);
+        return done();
+      }
+
+      teacher.check(text, function(err, data) {
+        expect(err).to.be.equal(null);
+
+        var results = data || [];
+        results = results.filter(function(result) {
+          if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
+            return false;
+          }
+
+          // ignore anything that starts with a dash
+          if (result.string[0] == "-") {
+            return false;
+          }
+
+          if (!(new RegExp(result.string)).test(text)) {
+            return false;
+          }
+
+          return true;
+        })
+
+        if (results.length > 0) {
+          console.log(results);
+        }
+        else {
+          addCacheHash(hash);
+        }
+
+        expect(results.length).to.be.equal(0);
+
+        setTimeout(done, 500);
+      });
+    });
+  });
+
+  it("Spellcheck README.md", function (done) {
+   var readme = path.join(rootURI, "README.md");
+
+    fs.readFile(readme, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var hash = md5(text);
+
+      // skip this test if we know we have done the
+      // exact same test with positive results before
+      if (CACHE[hash]) {
+        expect(CACHE[hash]).to.be.equal(true);
+        return done();
+      }
+
+      teacher.check(text, function(err, data) {
+        expect(err).to.be.equal(null);
+
+        var results = data || [];
+        results = results.filter(function(result) {
+          if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
+            return false;
+          }
+
+          // ignore anything that starts with a dash
+          if (result.string[0] == "-") {
+            return false;
+          }
+
+          // ignore anything that we don't find in the original text,
+          // for some reason "bootstrap.js" becomes "bootstrapjs".
+          if (!(new RegExp(result.string)).test(text)) {
+            return false;
+          }
+
+          return true;
+        })
+
+        if (results.length > 0) {
+          console.log(results);
+        }
+        else {
+          addCacheHash(hash);
+        }
+
+        expect(results.length).to.be.equal(0);
+
+        done();
+      });
+    });
+  });
+});
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/test.ini.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var fs = require("fs");
+var path = require("path");
+var Promise = require("promise");
+var chai = require("chai");
+var expect = chai.expect;
+var ini = require("./update-ini");
+
+var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
+
+describe("Checking ini files", function () {
+
+  it("Check test/addons/jetpack-addon.ini", function (done) {
+
+    fs.readFile(addonINI, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var expected = "";
+
+      ini.makeAddonIniContent()
+      .then(function(contents) {
+        expected = contents;
+
+        setTimeout(function end() {
+          expect(expected.trim()).to.be.equal(text.trim());
+          done();
+        });
+      });
+    });
+
+  });
+
+});
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/update-ini.js
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var path = require("path");
+var cp = require("child_process");
+var fs = require("fs");
+var Promise = require("promise");
+var parser = require("ini-parser");
+
+var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
+var addonsDir = path.resolve("./test/addons/");
+
+function updateAddonINI() {
+  return new Promise(function(resolve) {
+    console.log("Start updating " + addonINI);
+
+    makeAddonIniContent().
+    then(function(contents) {
+      fs.writeFileSync(addonINI, contents, { encoding: "utf8" });
+      console.log("Done updating " + addonINI);
+      resolve();
+    });
+  })
+}
+exports.updateAddonINI = updateAddonINI;
+
+function makeAddonIniContent() {
+  return new Promise(function(resolve) {
+    var data = parser.parse(fs.readFileSync(addonINI, { encoding: "utf8" }).toString());
+    var result = {};
+
+    fs.readdir(addonsDir, function(err, files) {
+      var folders = files.filter(function(file) {
+        return fs.statSync(path.resolve(addonsDir, file)).isDirectory();
+      }).sort();
+
+      folders.forEach(function(folder) {
+        var oldData = data[folder + ".xpi"];
+        result[folder] = oldData ? oldData : {};
+      });
+
+      // build ini file
+      var contents = [];
+      Object.keys(result).sort().forEach(function(key) {
+        contents.push("[" + key + ".xpi]");
+        Object.keys(result[key]).forEach(function(dataKey) {
+          contents.push(dataKey + " = " + result[key][dataKey]);
+        });
+      });
+      contents = contents.join("\n") + "\n";
+
+      return resolve(contents);
+    });
+  });
+}
+exports.makeAddonIniContent = makeAddonIniContent;
--- a/addon-sdk/source/bin/node-scripts/utils.js
+++ b/addon-sdk/source/bin/node-scripts/utils.js
@@ -12,53 +12,84 @@ var chai = require("chai");
 var expect = chai.expect;
 var assert = chai.assert;
 var DEFAULT_PROCESS = process;
 
 var sdk = path.join(__dirname, "..", "..");
 var prefsPath = path.join(sdk, "test", "preferences", "test-preferences.js");
 var e10sPrefsPath = path.join(sdk, "test", "preferences", "test-e10s-preferences.js");
 
+var OUTPUT_FILTERS = [
+  /[^\n\r]+WARNING\: NS_ENSURE_SUCCESS\(rv, rv\) failed[^\n]+\n\r?/
+];
+
+var isDebug = (process.env["JPM_FX_DEBUG"] == "1");
+exports.isDebug = isDebug;
+
 function spawn (cmd, options) {
   options = options || {};
   var env = _.extend({}, options.env, process.env);
+
+  if (isDebug) {
+    env["MOZ_QUIET"] = 1;
+  }
+
   var e10s = options.e10s || false;
 
   return child_process.spawn("node", [
-    jpm, cmd, "-v",
+    jpm, cmd, "-v", "--tbpl",
     "--prefs", e10s ? e10sPrefsPath : prefsPath,
     "-o", sdk,
     "-f", options.filter || ""
   ], {
     cwd: options.cwd || tmpOutputDir,
     env: env
   });
 }
 exports.spawn = spawn;
 
 function run (cmd, options, p) {
   return new Promise(function(resolve) {
     var output = [];
+
     var proc = spawn(cmd, options);
     proc.stderr.pipe(process.stderr);
     proc.stdout.on("data", function (data) {
+      for (var i = OUTPUT_FILTERS.length - 1; i >= 0; i--) {
+        if (OUTPUT_FILTERS[i].test(data)) {
+          return null;
+        }
+      }
       output.push(data);
+      return null;
     });
+
     if (p) {
       proc.stdout.pipe(p.stdout);
     }
+    else {
+      proc.stdout.on("data", function (data) {
+        data = (data || "") + "";
+        if (/TEST-/.test(data)) {
+          DEFAULT_PROCESS.stdout.write(data.replace(/[\s\n]+$/, "") + "\n");
+        }
+      });
+    }
+
     proc.on("close", function(code) {
       var out = output.join("");
+      var buildDisplayed = /Build \d+/.test(out);
       var noTests = /No tests were run/.test(out);
       var hasSuccess = /All tests passed!/.test(out);
       var hasFailure = /There were test failures\.\.\./.test(out);
       if (noTests || hasFailure || !hasSuccess || code != 0) {
         DEFAULT_PROCESS.stdout.write(out);
       }
       expect(code).to.equal(hasFailure ? 1 : 0);
+      expect(buildDisplayed).to.equal(true);
       expect(hasFailure).to.equal(false);
       expect(hasSuccess).to.equal(true);
       expect(noTests).to.equal(false);
       resolve();
     });
   });
 }
 exports.run = run;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/words.txt
@@ -0,0 +1,12 @@
+addon-sdk
+github
+stackoverflow
+bugzilla
+irc
+erikvold
+jsantell
+mossop
+gozala
+zer0
+autonome
+0c0w3
--- a/addon-sdk/source/examples/actor-repl/package.json
+++ b/addon-sdk/source/examples/actor-repl/package.json
@@ -1,10 +1,10 @@
 {
   "name": "actor-repl",
   "id": "@actor-repl",
   "title": "Actor REPL",
   "description": "Actor REPL",
   "version": "0.0.1",
   "author": "Irakli Gozalishvili",
   "main": "./index.js",
-  "license": "MPL 2.0"
+  "license": "MPL-2.0"
 }
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/README.md
+++ /dev/null
@@ -1,46 +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/. -->
-
-This add-on enables users to add notes, or annotations, to Web pages.
-
-Usage
------
-
-To switch the annotator on, left-click the pencil icon in the Add-on Bar. The
-icon should turn yellow: this indicates that the annotator is active. To switch
-it off, click it again. Switching it on/off only stops you from entering
-annotations: existing annotations are still displayed.
-
-When the annotator is active and the user moves the mouse over a page element
-that can be annotated, the annotator highlights that elements by giving it a
-yellow background.
-
-If the user clicks on a highlighted element the add-on opens a dialog for the
-user to enter the annotation. When the user hits <return> the annotation is
-saved.
-
-Elements which have been annotated are displayed with a yellow border: when the
-user moves the mouse over one of these elements, the add-on displays the
-annotation associated with that element.
-
-To view all annotations in a list, right-click the pencil icon.
-
-The add-on is deactivated in private browsing mode, meaning that new annotations
-can't be created although existing ones are still shown. On exiting private
-browsing the add-on returns to its previous activation state.
-
-Known Issues/Limitations
-------------------------
-
-It is not possible to delete annotations, or to edit them after creating them,
-but it would be simple to add this.
-
-When right-clicking the annotator icon the add-on bar's context-menu is shown:
-this is tracked by
-[bug 626326](https://bugzilla.mozilla.org/show_bug.cgi?id=626326).
-
-The list of annotations should be anchored to the widget. The annotation
-editor, and the annotation itself, should be anchored to the element which is
-annotated. The will be done when the implementation of panel-anchoring is
-extended.
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/annotation/annotation.html
+++ /dev/null
@@ -1,31 +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/. -->
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-    <title>Annotation</title>
-    <style type="text/css" media="all">
-
-body {
-        font: 100% arial, helvetica, sans-serif;
-    }
-
-div {
-        text-align:left;
-    }
-
-</style>
-
-</head>
-
-<body>
-
-<div id = "annotation">
-</div>
-
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/annotation/annotation.js
+++ /dev/null
@@ -1,11 +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/. */
-
-/*
-Initialize annotation content.
-*/
-
-self.on('message', function(message) {
-  $('#annotation').text(message);
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/editor/annotation-editor.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-  <title>Annotation</title>
-  <style type="text/css" media="all">
-  body, html {
-    font: 100% arial, helvetica, sans-serif;
-    padding: 0;
-    margin: 0;
-    position: fixed;
-  }
-  textarea {
-    width: 100%;
-    height: 100%;
-    margin: 10px;
-    padding: 0;
-    color: inherit !important;
-    font: inherit !important;
-    background: transparent;
-    border: none;
-  }
-  </style>
-
-</head>
-
-<body>
-
-<textarea rows='10' cols='20' id='annotation-box'>
-</textarea>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/editor/annotation-editor.js
+++ /dev/null
@@ -1,23 +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/. */
-
-/*
-On a return key, send the content of the textArea back to the add-on,
-and zero the textArea for the next time.
-*/
-
-var textArea = document.getElementById('annotation-box');
-
-textArea.onkeyup = function(event) {
-  if (event.keyCode == 13) {
-    self.postMessage(textArea.value);
-    textArea.value = '';
-  }
-};
-
-self.on('message', function() {
-  var textArea = document.getElementById('annotation-box');
-  textArea.value = '';
-  textArea.focus();
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/jquery-1.4.2.min.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.4.2
- * http://jquery.com/
- *
- * Copyright 2010, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2010, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Sat Feb 13 22:33:48 2010 -0500
- */
-(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
-e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
-j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
-"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
-true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
-Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
-(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
-a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
-"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
-function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
-c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
-L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
-"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
-a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
-d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
-a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
-!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
-true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
-var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
-parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
-false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
-s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
-applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
-else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
-a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
-w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
-cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
-i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
-" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
-this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
-e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
-c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
-a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
-function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
-k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
-C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
-null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
-e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
-f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
-if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
-fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
-d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
-"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
-a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
-isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
-{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
-if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
-e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
-"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
-d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
-!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
-toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
-u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
-function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
-if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
-e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
-t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
-g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
-for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
-1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
-CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
-relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
-l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
-h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
-CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
-g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
-text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
-setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
-h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
-m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
-"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
-h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
-!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
-h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
-q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
-if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
-(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
-function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
-gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
-c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
-{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
-"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
-d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
-a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
-1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
-a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
-c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
-wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
-prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
-this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
-return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
-""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
-this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
-u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
-1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
-return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
-""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
-c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
-c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
-function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
-Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
-"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
-a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
-a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
-"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
-serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
-function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
-global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
-e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
-"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
-false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
-false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
-c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
-d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
-g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
-1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
-"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
-if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
-this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
-"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
-animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
-j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
-this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
-"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
-c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
-this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
-this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
-e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
-c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
-function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
-this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
-k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
-f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
-a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
-c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
-d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
-"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
-e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.css
+++ /dev/null
@@ -1,40 +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/.
-
-#annotation-list .annotation-details
-  {
-  padding: 10px;
-  margin: 10px;
-  border: solid 3px #EEE;
-  background-color: white;
-  }
-
-#annotation-list .url, .selection-text, .annotation-text
-  {
-  padding: 5px;
-  margin: 5px;
-  }
-
-#annotation-list .selection-text,#annotation-list .annotation-text
-  {
-  border: solid 1px #EEE;
-  }
-
-#annotation-list .annotation-text
-  {
-  font-style: italic;
-  }
-
-body
-  {
-  background-color: #F5F5F5;
-  font: 100% arial, helvetica, sans-serif;
-  }
-
-h1
-  {
-  font-family: georgia,serif;
-  font-size: 1.5em;
-  text-align:center;
-  }
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Saved annotations</title>
-  <link rel="stylesheet" type="text/css" href="annotation-list.css" />
-</head>
-<body>
-
-<div id="annotation-list">
-</div>
-
-<div id="template">
-  <div class="annotation-details">
-    <a class="url"></a>
-    <div class="selection-text"></div>
-    <div class="annotation-text"></div>
-  </div>
-</div>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.js
+++ /dev/null
@@ -1,31 +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/. */
-
-/*
-Construct the HTML for the annotation list.
-
-Bind a function to click events on the link that send a message back to
-the add-on code, so it can open the link in the main browser.
-*/
-
-self.on("message", function onMessage(storedAnnotations) {
-  var annotationList = $('#annotation-list');
-  annotationList.empty();
-  storedAnnotations.forEach(
-    function(storedAnnotation) {
-      var annotationHtml = $('#template .annotation-details').clone();
-      annotationHtml.find('.url').text(storedAnnotation.url)
-                                 .attr('href', storedAnnotation.url);
-      annotationHtml.find('.url').bind('click', function(event) {
-        event.stopPropagation();
-        event.preventDefault();
-        self.postMessage(storedAnnotation.url);
-      });
-      annotationHtml.find('.selection-text')
-                    .text(storedAnnotation.anchorText);
-      annotationHtml.find('.annotation-text')
-                    .text(storedAnnotation.annotationText);
-      annotationList.append(annotationHtml);
-    });
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/matcher.js
+++ /dev/null
@@ -1,50 +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/. */
-
-/*
-Locate anchors for annotations and prepare to display the annotations.
-
-For each annotation, if its URL matches this page,
-- get the ancestor whose ID matches the ID in the anchor
-- look for a <p> element whose content contains the anchor text
-
-That's considered a match. Then we:
-- highlight the anchor element
-- add an 'annotated' class to tell the selector to skip this element
-- embed the annottion text as a new attribute
-
-For all annotated elements:
-- bind 'mouseenter' and 'mouseleave' events to the element, to send 'show'
-  and 'hide' messages back to the add-on.
-*/
-
-self.on('message', function onMessage(annotations) {
-  annotations.forEach(
-    function(annotation) {
-      if(annotation.url == document.location.toString()) {
-        createAnchor(annotation);
-      }
-  });
-
-  $('.annotated').css('border', 'solid 3px yellow');
-
-  $('.annotated').bind('mouseenter', function(event) {
-    self.port.emit('show', $(this).attr('annotation'));
-    event.stopPropagation();
-    event.preventDefault();
-  });
-
-  $('.annotated').bind('mouseleave', function() {
-    self.port.emit('hide');
-  });
-});
-
-
-function createAnchor(annotation) {
-  annotationAnchorAncestor = $('#' + annotation.ancestorId)[0] || document.body;
-  annotationAnchor = $(annotationAnchorAncestor).parent().find(
-                     ':contains("' + annotation.anchorText + '")').last();
-  annotationAnchor.addClass('annotated');
-  annotationAnchor.attr('annotation', annotation.annotationText);
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/selector.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/. */
-
-/*
-The selector locates elements that are suitable for annotation and enables
-the user to select them.
-
-On 'mouseenter' events associated with <p> elements:
-- if the selector is active and the element is not already annotated
-- find the nearest ancestor which has an id attribute: this is supposed to
-make identification of this element more accurate
-- highlight the element
-- bind 'click' for the element to send a message back to the add-on, including
-all the information associated with the anchor.
-*/
-
-var matchedElement = null;
-var originalBgColor = null;
-var active = false;
-
-function resetMatchedElement() {
-  if (matchedElement) {
-    matchedElement.css('background-color', originalBgColor);
-    matchedElement.unbind('click.annotator');
-  }
-}
-
-self.on('message', function onMessage(activation) {
-  active = activation;
-  if (!active) {
-    resetMatchedElement();
-  }
-});
-
-function getInnerText(element) {
-  // jQuery.text() returns content of <script> tags, we need to ignore those
-  var list = [];
-  element.find("*").andSelf().contents()
-    .filter(function () {
-      return this.nodeType == 3 && this.parentNode.tagName != "SCRIPT";
-    })
-    .each(function () {
-      list.push(this.nodeValue);
-    });
-  return list.join("");
-}
-
-$('*').mouseenter(function() {
-  if (!active || $(this).hasClass('annotated')) {
-    return;
-  }
-  resetMatchedElement();
-  ancestor = $(this).closest("[id]");
-  matchedElement = $(this).first();
-  originalBgColor = matchedElement.css('background-color');
-  matchedElement.css('background-color', 'yellow');
-  matchedElement.bind('click.annotator', function(event) {
-    event.stopPropagation();
-    event.preventDefault();
-    self.port.emit('show',
-      [
-        document.location.toString(),
-        ancestor.attr("id"),
-        getInnerText(matchedElement)
-      ]
-   );
-  });
-});
-
-$('*').mouseout(function() {
-  resetMatchedElement();
-});
deleted file mode 100644
index b14d9619635af8d6bb04bae79ca74e67579c3fb0..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 71a609f83ff1805acecc08fc5be4e4947ad407b9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/widget/widget.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-Listen for left and right click events and send the corresponding message
-to the content script.
-*/
-
-this.addEventListener('click', function(event) {
-  if(event.button == 0 && event.shiftKey == false)
-    self.port.emit('left-click');
-
-  if(event.button == 2 || (event.button == 0 && event.shiftKey == true))
-    self.port.emit('right-click');
-    event.preventDefault();
-}, true);
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/lib/main.js
+++ /dev/null
@@ -1,266 +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/. */
-
-var widgets = require('sdk/widget');
-var pageMod = require('sdk/page-mod');
-var data = require('sdk/self').data;
-var panels = require('sdk/panel');
-var simpleStorage = require('sdk/simple-storage');
-var notifications = require("sdk/notifications");
-
-/*
-Global variables
-* Boolean to indicate whether the add-on is switched on or not
-* Array for all workers associated with the 'selector' page mod
-* Array for all workers associated with the 'matcher' page mod
-*/
-var annotatorIsOn = false;
-var selectors = [];
-var matchers = [];
-
-if (!simpleStorage.storage.annotations)
-  simpleStorage.storage.annotations = [];
-
-/*
-Update the matchers: call this whenever the set of annotations changes
-*/
-function updateMatchers() {
-  matchers.forEach(function (matcher) {
-    matcher.postMessage(simpleStorage.storage.annotations);
-  });
-}
-
-/*
-Constructor for an Annotation object
-*/
-function Annotation(annotationText, anchor) {
-  this.annotationText = annotationText;
-  this.url = anchor[0];
-  this.ancestorId = anchor[1];
-  this.anchorText = anchor[2];
-}
-
-/*
-Function to deal with a new annotation.
-Create a new annotation object, store it, and
-notify all the annotators of the change.
-*/
-function handleNewAnnotation(annotationText, anchor) {
-  var newAnnotation = new Annotation(annotationText, anchor);
-  simpleStorage.storage.annotations.push(newAnnotation);
-  updateMatchers();
-}
-
-/*
-Function to tell the selector page mod that the add-on has become (in)active
-*/
-function activateSelectors() {
-  selectors.forEach(
-    function (selector) {
-      selector.postMessage(annotatorIsOn);
-  });
-}
-
-/*
-Toggle activation: update the on/off state and notify the selectors.
-*/
-function toggleActivation() {
-  annotatorIsOn = !annotatorIsOn;
-  activateSelectors();
-  return annotatorIsOn;
-}
-
-function detachWorker(worker, workerArray) {
-  var index = workerArray.indexOf(worker);
-  if(index != -1) {
-    workerArray.splice(index, 1);
-  }
-}
-
-exports.main = function() {
-
-/*
-The widget provides a mechanism to switch the selector on or off, and to
-view the list of annotations.
-
-The selector is switched on/off with a left-click, and the list of annotations
-is displayed on a right-click.
-*/
-  var widget = widgets.Widget({
-    id: 'toggle-switch',
-    label: 'Annotator',
-    contentURL: data.url('widget/pencil-off.png'),
-    contentScriptWhen: 'ready',
-    contentScriptFile: data.url('widget/widget.js')
-  });
-
-  widget.port.on('left-click', function() {
-    console.log('activate/deactivate');
-    widget.contentURL = toggleActivation() ?
-              data.url('widget/pencil-on.png') :
-              data.url('widget/pencil-off.png');
-  });
-
-  widget.port.on('right-click', function() {
-      console.log('show annotation list');
-      annotationList.show();
-  });
-
-/*
-The selector page-mod enables the user to select page elements to annotate.
-
-It is attached to all pages but only operates if the add-on is active.
-
-The content script highlights any page elements which can be annotated. If the
-user clicks a highlighted element it sends a message to the add-on containing
-information about the element clicked, which is called the anchor of the
-annotation.
-
-When we receive this message we assign the anchor to the annotationEditor and
-display it.
-*/
-  var selector = pageMod.PageMod({
-    include: ['*'],
-    contentScriptWhen: 'ready',
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('selector.js')],
-    onAttach: function(worker) {
-      worker.postMessage(annotatorIsOn);
-      selectors.push(worker);
-      worker.port.on('show', function(data) {
-        annotationEditor.annotationAnchor = data;
-        annotationEditor.show();
-      });
-      worker.on('detach', function () {
-        detachWorker(this, selectors);
-      });
-    }
-  });
-
-/*
-The annotationEditor panel is the UI component used for creating
-new annotations. It contains a text area for the user to
-enter the annotation.
-
-When we are ready to display the editor we assign its 'anchor' property
-and call its show() method.
-
-Its content script sends the content of the text area to the add-on
-when the user presses the return key.
-
-When we receives this message we create a new annotation using the anchor
-and the text the user entered, store it, and hide the panel.
-*/
-  var annotationEditor = panels.Panel({
-    width: 220,
-    height: 220,
-    contentURL: data.url('editor/annotation-editor.html'),
-    contentScriptFile: data.url('editor/annotation-editor.js'),
-    onMessage: function(annotationText) {
-      if (annotationText)
-        handleNewAnnotation(annotationText, this.annotationAnchor);
-      annotationEditor.hide();
-    },
-    onShow: function() {
-      this.postMessage('focus');
-    }
-  });
-
-/*
-The annotationList panel is the UI component that lists all the annotations
-the user has entered.
-
-On its 'show' event we pass it the array of annotations.
-
-The content script creates the HTML elements for the annotations, and
-intercepts clicks on the links, passing them back to the add-on to open them
-in the browser.
-*/
-  var annotationList = panels.Panel({
-    width: 420,
-    height: 200,
-    contentURL: data.url('list/annotation-list.html'),
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('list/annotation-list.js')],
-    contentScriptWhen: 'ready',
-    onShow: function() {
-      this.postMessage(simpleStorage.storage.annotations);
-    },
-    onMessage: function(message) {
-      require('sdk/tabs').open(message);
-    }
-  });
-
-/*
-We listen for the OverQuota event from simple-storage.
-If it fires we just notify the user and delete the most
-recent annotations until we are back in quota.
-*/
-  simpleStorage.on("OverQuota", function () {
-    notifications.notify({
-      title: 'Storage space exceeded',
-      text: 'Removing recent annotations'});
-    while (simpleStorage.quotaUsage > 1)
-      simpleStorage.storage.annotations.pop();
-  });
-
-/*
-The matcher page-mod locates anchors on web pages and prepares for the
-annotation to be displayed.
-
-It is attached to all pages, and when it is attached we pass it the complete
-list of annotations. It looks for anchors in its page. If it finds one it
-highlights the anchor and binds mouseenter/mouseout events to 'show' and 'hide'
-messages to the add-on.
-
-When the add-on receives the 'show' message it assigns the annotation text to
-the annotation panel and shows it.
-
-Note that the matcher is active whether or not the add-on is active:
-'inactive' only means that the user can't create new add-ons, they can still
-see old ones.
-*/
-  var matcher = pageMod.PageMod({
-    include: ['*'],
-    contentScriptWhen: 'ready',
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('matcher.js')],
-    onAttach: function(worker) {
-      if(simpleStorage.storage.annotations) {
-        worker.postMessage(simpleStorage.storage.annotations);
-      }
-      worker.port.on('show', function(data) {
-        annotation.content = data;
-        annotation.show();
-      });
-      worker.port.on('hide', function() {
-        annotation.content = null;
-        annotation.hide();
-      });
-      worker.on('detach', function () {
-        detachWorker(this, matchers);
-      });
-      matchers.push(worker);
-    }
-  });
-
-/*
-The annotation panel is the UI component that displays an annotation.
-
-When we are ready to show it we assign its 'content' attribute to contain
-the annotation text, and that gets sent to the content process in onShow().
-*/
-  var annotation = panels.Panel({
-    width: 200,
-    height: 180,
-    contentURL: data.url('annotation/annotation.html'),
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('annotation/annotation.js')],
-    contentScriptWhen: 'ready',
-    onShow: function() {
-      this.postMessage(this.content);
-    }
-  });
-
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "license": "MPL 2.0",
-  "name": "annotator",
-  "contributors": [],
-  "author": "Will Bamberg",
-  "keywords": [],
-  "version": "0.1.1",
-  "id": "anonid0-annotator@jetpack",
-  "description": "Add notes to Web pages",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/tests/test-main.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";
-
-exports.testMain = function(assert) {
-  assert.pass("TODO: Write some tests.");
-};
-
-require("sdk/test").run(exports);
--- a/addon-sdk/source/examples/debug-client/package.json
+++ b/addon-sdk/source/examples/debug-client/package.json
@@ -1,10 +1,10 @@
 {
   "name": "debug-client",
   "id": "@debug-client",
   "title": "Debug client",
   "description": "Example debug client",
   "version": "0.0.1",
   "author": "Irakli Gozalishvili",
   "main": "./index.js",
-  "license": "MPL 2.0"
+  "license": "MPL-2.0"
 }
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/README.md
+++ /dev/null
@@ -1,13 +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/. -->
-
-This is a port to the SDK of the
-[Library Detector add-on](https://addons.mozilla.org/en-US/firefox/addon/library-detector/).
-The original Library Detector is written by
-[Paul Bakaus](http://paulbakaus.com/) and made available under the
-[MIT License](http://www.opensource.org/licenses/mit-license.php).
-
-It only recognizes a subset of the libraries recognized by the original,
-just to keep the SDK download package size and on-disk footprint as small
-as possible.
deleted file mode 100644
index a8c91a039c867919580e945391d8dbf0583624da..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 8df8f3893cbe881e0067cec73870c1388c70843a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 77e3bd2dd354989533e0d4be353a17461f823648..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c37d43883133d3e6e10e5893d16b2206e53fe305..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 2a5df7db5890c738f675e12720e419392594e9bf..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 06acd8a79b6eb13f0b9cdcac4d5b6cd78e6ca1e1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/library-detector.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-The code in this file is adapted from the original
-Library Detector add-on
-(https://addons.mozilla.org/en-US/firefox/addon/library-detector/) written by
-Paul Bakaus (http://paulbakaus.com/) and made available under the
-MIT License (http://www.opensource.org/licenses/mit-license.php).
-*/
-
-var LD_tests = {
-
-    'jQuery': {
-        test: function(win) {
-            var jq = win.jQuery || win.$ || win.$jq || win.$j;
-            if(jq && jq.fn && jq.fn.jquery) {
-                return { version: jq.fn.jquery };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'jQuery UI': {
-        //phonehome: 'http://jqueryui.com/phone_home',
-        test: function(win) {
-
-            var jq = win.jQuery || win.$ || win.$jq || win.$j;
-            if(jq && jq.fn && jq.fn.jquery && jq.ui) {
-
-                var plugins = 'accordion,datepicker,dialog,draggable,droppable,progressbar,resizable,selectable,slider,menu,grid,tabs'.split(','), concat = [];
-                for (var i=0; i < plugins.length; i++) { if(jq.ui[plugins[i]]) concat.push(plugins[i].substr(0,1).toUpperCase() + plugins[i].substr(1)); };
-
-                return { version: jq.ui.version, details: concat.length ? 'Plugins used: '+concat.join(',') : '' };
-            } else {
-                return false;
-            }
-
-        }
-    },
-
-    'MooTools': {
-        test: function(win) {
-            if(win.MooTools && win.MooTools.version) {
-                return { version: win.MooTools.version };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'YUI': {
-        test: function(win) {
-            if(win.YAHOO && win.YAHOO.VERSION) {
-                return { version: win.YAHOO.VERSION };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'Closure': {
-        test: function(win) {
-            if(win.goog) {
-                return { version: '2.0' };
-            }
-            return false;
-        }
-    },
-
-    'Modernizr': {
-        test: function(win) {
-            if(win.Modernizr) {
-                return { version: win.Modernizr._version };
-            }
-            return false;
-        }
-    },
-
-
-};
-
-function testLibraries() {
-  var win = unsafeWindow;
-  var libraryList = [];
-  for(var i in LD_tests) {
-    var passed = LD_tests[i].test(win);
-    if (passed) {
-      let libraryInfo = {
-        name: i,
-        version: passed.version
-      };
-      libraryList.push(libraryInfo);
-    }
-  }
-  self.postMessage(libraryList);
-}
-
-testLibraries();
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/panel.html
+++ /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/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Library detector</title>
-  <script type="text/javascript">
-    addon.on('message', function (libraryInfo) {
-      document.body.innerHTML = libraryInfo;
-    });
-  </script>
-</head>
-<body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/widget.html
+++ /dev/null
@@ -1,50 +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/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Library detector</title>
-  <style type="text/css" media="all">
-    img {
-      display: inline;
-      width: 16px;
-      height: 16px;
-    }
-  </style>
-  <script type="text/javascript">
-    var icons = {
-      'jQuery' : 'jquery.ico',
-      'jQuery UI' : 'jquery_ui.ico',
-      'MooTools' : 'mootools.png',
-      'YUI' : 'yui.ico',
-      'Closure' : 'closure.ico',
-      'Modernizr': 'modernizr.ico',
-    };
-
-    // Listen for mouse events over icons, in order to send a message up to
-    // the panel and update its content with library name and version
-    window.addEventListener('mouseover', function (event) {
-      if (event.target.tagName == 'IMG') {
-        addon.port.emit('setLibraryInfo', event.target.title);
-      }
-    }, false);
-
-    addon.port.on('update', function (libraries) {
-      // Cleanup previous content
-      document.body.innerHTML = '';
-
-      // Create new updated list of icons
-      libraries.forEach(function(library) {
-        var img = document.createElement('img');
-        img.setAttribute('src', 'icons/' + icons[library.name]);
-        img.setAttribute('title', library.name + "<br>Version: " +
-                                  library.version);
-        document.body.appendChild(img);
-      });
-    });
-  </script>
-</head>
-<body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/lib/main.js
+++ /dev/null
@@ -1,67 +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 tabs = require('sdk/tabs');
-const widgets = require('sdk/widget');
-const data = require('sdk/self').data;
-const pageMod = require('sdk/page-mod');
-const panel = require('sdk/panel');
-
-const ICON_WIDTH = 16;
-
-function updateWidgetView(tab) {
-  let widgetView = widget.getView(tab.window);
-  if (!tab.libraries) {
-    tab.libraries = [];
-  }
-  widgetView.port.emit("update", tab.libraries);
-  widgetView.width = tab.libraries.length * ICON_WIDTH;
-}
-
-var widget = widgets.Widget({
-  id: "library-detector",
-  label: "Library Detector",
-  contentURL: data.url("widget.html"),
-  panel: panel.Panel({
-    width: 240,
-    height: 60,
-    contentURL: data.url("panel.html")
-  })
-});
-
-widget.port.on('setLibraryInfo', function(libraryInfo) {
-  widget.panel.postMessage(libraryInfo);
-});
-
-pageMod.PageMod({
-  include: "*",
-  contentScriptWhen: 'end',
-  contentScriptFile: (data.url('library-detector.js')),
-  onAttach: function(worker) {
-    worker.on('message', function(libraryList) {
-      if (!worker.tab.libraries) {
-        worker.tab.libraries = [];
-      }
-      libraryList.forEach(function(library) {
-        if (worker.tab.libraries.indexOf(library) == -1) {
-          worker.tab.libraries.push(library);
-        }
-      });
-      if (worker.tab == tabs.activeTab) {
-        updateWidgetView(worker.tab);
-      }
-    });
-  }
-});
-
-tabs.on('activate', function(tab) {
-  updateWidgetView(tab);
-});
-
-/*
-For change of location
-*/
-tabs.on('ready', function(tab) {
-  tab.libraries = [];
-});
\ No newline at end of file
deleted file mode 100755
--- a/addon-sdk/source/examples/library-detector/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "name": "library-detector-sdk",
-  "license": "MPL 2.0",
-  "author": "",
-  "version": "0.1.1",
-  "title": "library-detector-sdk",
-  "id": "jid1-R4rSVNkBANnvGQ@jetpack",
-  "description": "a basic add-on",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/test/test-main.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";
-
-exports.testMain = function(assert) {
-  assert.pass("TODO: Write some tests.");
-};
-
-require("sdk/test").run(exports);
--- a/addon-sdk/source/examples/reading-data/package.json
+++ b/addon-sdk/source/examples/reading-data/package.json
@@ -1,9 +1,9 @@
 {
     "name": "reading-data",
     "description": "A demonstration of reading bundled data.",
     "keywords": [],
     "author": "Brian Warner",
     "contributors": [],
-    "license": "MPL 2.0",
+    "license": "MPL-2.0",
     "id": "reading-data-example@jetpack.mozillalabs.com"
 }
--- a/addon-sdk/source/examples/theme/package.json
+++ b/addon-sdk/source/examples/theme/package.json
@@ -1,10 +1,10 @@
 {
   "name": "theme",
   "title": "theme",
   "id": "theme@jetpack",
   "description": "How to create new theme for devtools",
   "author": "Jan Odvarko",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.0",
   "main": "lib/main"
 }
--- a/addon-sdk/source/examples/toolbar-api/package.json
+++ b/addon-sdk/source/examples/toolbar-api/package.json
@@ -1,12 +1,12 @@
 {
   "name": "toolbar-api",
   "title": "Toolbar API",
   "main": "./lib/main.js",
   "description": "a toolbar api example",
   "author": "",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.1",
   "engines": {
     "firefox": ">=27.0 <=30.0"
   }
 }
--- a/addon-sdk/source/examples/ui-button-apis/package.json
+++ b/addon-sdk/source/examples/ui-button-apis/package.json
@@ -1,10 +1,10 @@
 {
   "name": "ui-button-apis",
   "title": "Australis Button API Examples",
   "id": "ui-button-apis@mozilla.org",
   "description": "A Button API example",
   "author": "jeff@canuckistani.ca (Jeff Griffiths | @canuckistani)",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.1",
   "main": "./lib/main.js"
 }
--- a/addon-sdk/source/gulpfile.js
+++ b/addon-sdk/source/gulpfile.js
@@ -1,23 +1,44 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var gulp = require('gulp');
+var patch = require("./bin/node-scripts/apply-patch");
+var ini = require("./bin/node-scripts/update-ini");
 
 gulp.task('test', function(done) {
   require("./bin/jpm-test").run().then(done);
 });
 
 gulp.task('test:addons', function(done) {
-  require("./bin/jpm-test").run("addons").then(done);
+  require("./bin/jpm-test").run("addons").catch(console.error).then(done);
+});
+
+gulp.task('test:docs', function(done) {
+  require("./bin/jpm-test").run("docs").catch(console.error).then(done);
 });
 
 gulp.task('test:examples', function(done) {
-  require("./bin/jpm-test").run("examples").then(done);
+  require("./bin/jpm-test").run("examples").catch(console.error).then(done);
 });
 
 gulp.task('test:modules', function(done) {
-  require("./bin/jpm-test").run("modules").then(done);
+  require("./bin/jpm-test").run("modules").catch(console.error).then(done);
+});
+
+gulp.task('test:ini', function(done) {
+  test("ini").catch(console.error).then(done);
 });
 
+gulp.task('patch:clean', function(done) {
+  patch.clean().catch(console.error).then(done);
+});
+
+gulp.task('patch:apply', function(done) {
+  patch.apply().catch(console.error).then(done);
+});
+
+gulp.task('update:ini', function(done) {
+  ini.updateAddonINI().catch(console.error).then(done);
+});
--- a/addon-sdk/source/lib/dev/frame-script.js
+++ b/addon-sdk/source/lib/dev/frame-script.js
@@ -67,49 +67,54 @@ const onInMessage = (message) => {
 const onReady = event => {
   channels.clear();
 };
 
 addMessageListener("sdk/event/message", onInMessage);
 addMessageListener("sdk/port/message", onInPort);
 
 const observer = {
+  handleEvent: ({target, type}) => {
+    observer.observe(target, type);
+  },
   observe: (document, topic, data) => {
     // When frame associated with message manager is removed from document `docShell`
     // is set to `null` but observer is still kept alive. At this point accesing
     // `content.document` throws "can't access dead object" exceptions. In order to
     // avoid leaking observer and logged errors observer is going to be removed when
     // `docShell` is set to `null`.
     if (!docShell) {
       observerService.removeObserver(observer, topic);
     }
     else if (document === content.document) {
-      if (topic === "content-document-interactive") {
+      if (topic.endsWith("-document-interactive")) {
         sendAsyncMessage("sdk/event/ready", {
           type: "ready",
           readyState: document.readyState,
           uri: document.documentURI
         });
       }
-      if (topic === "content-document-loaded") {
+      if (topic.endsWith("-document-loaded")) {
         sendAsyncMessage("sdk/event/load", {
           type: "load",
           readyState: document.readyState,
           uri: document.documentURI
         });
       }
-      if (topic === "content-page-hidden") {
+      if (topic === "unload") {
         channels.clear();
         sendAsyncMessage("sdk/event/unload", {
           type: "unload",
           readyState: "uninitialized",
           uri: document.documentURI
         });
       }
     }
   }
 };
 
 observerService.addObserver(observer, "content-document-interactive", false);
 observerService.addObserver(observer, "content-document-loaded", false);
-observerService.addObserver(observer, "content-page-hidden", false);
+observerService.addObserver(observer, "chrome-document-interactive", false);
+observerService.addObserver(observer, "chrome-document-loaded", false);
+addEventListener("unload", observer, false);
 
 })(this);
--- a/addon-sdk/source/lib/dev/panel.js
+++ b/addon-sdk/source/lib/dev/panel.js
@@ -121,17 +121,17 @@ const Panel = Class({
            when(this, "load").then(getTarget);
   },
   unloaded: function() {
     const { readyState } = this;
     const isUninitialized = readyState === "uninitialized";
     return isUninitialized ? Promise.resolve(this) :
            when(this, "unload").then(getTarget);
   },
-  postMessage: function(data, ports) {
+  postMessage: function(data, ports=[]) {
     const manager = managerFor(this);
     manager.sendAsyncMessage("sdk/event/message", {
       type: "message",
       bubbles: false,
       cancelable: false,
       data: data,
       origin: this.url,
       ports: ports.map(marshal(manager))
@@ -222,21 +222,21 @@ setup.define(Panel, (panel, {window, too
 
   panel.setup({ debuggee: debuggee });
 });
 
 createView.define(Panel, (panel, document) => {
   const frame = document.createElement("iframe");
   setAttributes(frame, {
     "sandbox": "allow-scripts",
-    // It would be great if we could allow remote iframes for sandboxing
-    // panel documents in a content process, but for now platform implementation
-    // is buggy on linux so this is disabled.
-    // "remote": true,
-    "type": "content",
+    // We end up using chrome iframe with forced message manager
+    // as fixing a swapFrameLoader seemed like a giant task (see
+    // Bug 1075490).
+    "type": "chrome",
+    "forcemessagemanager": true,
     "transparent": true,
     "seamless": "seamless",
   });
   return frame;
 });
 
 dispose.define(Panel, function(panel) {
   debuggeeFor(panel).close();
--- a/addon-sdk/source/lib/dev/volcan.js
+++ b/addon-sdk/source/lib/dev/volcan.js
@@ -1,11 +1,12 @@
 /* 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/. */
+
 !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.volcan=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
 "use strict";
 
 var Client = _dereq_("../client").Client;
 
 function connect(port) {
   var client = new Client();
   return client.connect(port);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/jetpack-id/index.js
@@ -0,0 +1,53 @@
+/* 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/. */
+
+/**
+ * Takes parsed `package.json` manifest and returns
+ * valid add-on id for it.
+ */
+function getID(manifest) {
+  manifest = manifest || {};
+
+  if (manifest.id) {
+
+    if (typeof manifest.id !== "string") {
+      return null;
+    }
+
+    // If manifest.id is already valid (as domain or GUID), use it
+    if (isValidAOMName(manifest.id)) {
+      return manifest.id;
+    }
+    // Otherwise, this ID is invalid so return `null`
+    return null;
+  }
+
+  // If no `id` defined, turn `name` into a domain ID,
+  // as we transition to `name` being an id, similar to node/npm, but
+  // append a '@' to make it compatible with Firefox requirements
+  if (manifest.name) {
+
+    if (typeof manifest.name !== "string") {
+      return null;
+    }
+
+    var modifiedName = "@" + manifest.name;
+    return isValidAOMName(modifiedName) ? modifiedName : null;
+  }
+
+  // If no `id` or `name` property, return null as this manifest
+  // is invalid
+  return null;
+}
+
+module.exports = getID;
+
+/**
+ * Regex taken from XPIProvider.jsm in the Addon Manager to validate proper
+ * IDs that are able to be used.
+ * http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#209
+ */
+function isValidAOMName (s) {
+  return /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i.test(s || "");
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/jetpack-id/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "jetpack-id",
+  "version": "1.0.0",
+  "description": "Creates an ID from a Firefox Jetpack manifest",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/jsantell/jetpack-id"
+  },
+  "author": {
+    "name": "Jordan Santell",
+    "url": "http://github.com/jsantell"
+  },
+  "license": "MPL-2.0",
+  "scripts": {
+    "test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
+  },
+  "keywords": [
+    "jetpack",
+    "addon",
+    "mozilla",
+    "firefox"
+  ],
+  "devDependencies": {
+    "mocha": "*",
+    "chai": "*"
+  }
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/index.js
@@ -0,0 +1,112 @@
+/* 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/. */
+
+var versionParse = require('./lib/utils').versionParse;
+
+var COMPARATORS = ['>=', '<=', '>', '<', '=', '~', '^'];
+
+exports.parse = function (input) {
+  input = input || '';
+  input = input.trim();
+  if (!input)
+    throw new Error('`parse` argument must be a populated string.');
+
+  // Handle the "*" case
+  if (input === "*") {
+    return { min: undefined, max: undefined };
+  }
+
+  var inputs = input.split(' ');
+  var min;
+  var max;
+
+  // 1.2.3 - 2.3.4
+  if (inputs.length === 3 && inputs[1] === '-') {
+    return { min: inputs[0], max: inputs[2] };
+  }
+
+  inputs.forEach(function (input) {
+    var parsed = parseExpression(input);
+    var version = parsed.version;
+    var comparator = parsed.comparator;
+
+    // 1.2.3
+    if (inputs.length === 1 && !comparator)
+      min = max = version;
+
+    // Parse min
+    if (~comparator.indexOf('>')) {
+      if (~comparator.indexOf('='))
+        min = version; // >=1.2.3
+      else
+        min = increment(version); // >1.2.3
+    }
+    else if (~comparator.indexOf('<')) {
+      if (~comparator.indexOf('='))
+        max = version; // <=1.2.3
+      else
+        max = decrement(version); // <1.2.3
+    }
+  });
+
+  return {
+    min: min,
+    max : max
+  };
+};
+
+function parseExpression (input) {
+  for (var i = 0; i < COMPARATORS.length; i++)
+    if (~input.indexOf(COMPARATORS[i]))
+      return {
+        comparator: COMPARATORS[i],
+        version: input.substr(COMPARATORS[i].length)
+      };
+  return { version: input, comparator: '' };
+}
+
+/**
+ * Takes a version string ('1.2.3') and returns a version string
+ * that'll parse as one less than the input string ('1.2.3.-1').
+ *
+ * @param {String} vString
+ * @return {String}
+ */
+function decrement (vString) {
+  return vString + (vString.charAt(vString.length - 1) === '.' ? '' : '.') + '-1';
+}
+exports.decrement = decrement;
+
+/**
+ * Takes a version string ('1.2.3') and returns a version string
+ * that'll parse as greater than the input string by the smallest margin
+ * possible ('1.2.3.1').
+ * listed as number-A, string-B, number-C, string-D in
+ * Mozilla's Toolkit Format.
+ * https://developer.mozilla.org/en-US/docs/Toolkit_version_format
+ *
+ * @param {String} vString
+ * @return {String}
+ */
+function increment (vString) {
+  var match = versionParse(vString);
+  var a = match[1];
+  var b = match[2];
+  var c = match[3];
+  var d = match[4];
+  var lastPos = vString.length - 1;
+  var lastChar = vString.charAt(lastPos);
+
+  if (!b) {
+    return vString + (lastChar === '.' ? '' : '.') + '1';
+  }
+  if (!c) {
+    return vString + '1';
+  }
+  if (!d) {
+    return vString.substr(0, lastPos) + (++lastChar);
+  }
+  return vString.substr(0, lastPos) + String.fromCharCode(lastChar.charCodeAt(0) + 1);
+}
+exports.increment = increment;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/lib/utils.js
@@ -0,0 +1,15 @@
+/* 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/. */
+
+/**
+ * Breaks up a version string into the 4 components
+ * defined in:
+ * https://developer.mozilla.org/en-US/docs/Toolkit_version_format
+ * @params {String} val
+ * @return {String}
+ */
+function versionParse (val) {
+  return val.match(/^([0-9\.]*)([a-zA-Z]*)([0-9\.]*)([a-zA-Z]*)$/);
+}
+exports.versionParse = versionParse;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/package.json
@@ -0,0 +1,21 @@
+{
+  "name": "mozilla-toolkit-versioning",
+  "version": "0.0.2",
+  "description": "Parser for Mozilla's toolkit version format",
+  "main": "index.js",
+  "scripts": {
+    "test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jsantell/mozilla-toolkit-versioning.git"
+  },
+  "author": "Jordan Santell",
+  "license": "MIT",
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "^1.21.4",
+    "chai": "^1.9.1",
+    "mozilla-version-comparator": "^1.0.2"
+  }
+}
--- a/addon-sdk/source/lib/sdk/clipboard.js
+++ b/addon-sdk/source/lib/sdk/clipboard.js
@@ -11,17 +11,16 @@ module.metadata = {
     "Firefox": "*",
     "SeaMonkey": "*",
     "Thunderbird": "*"
   }
 };
 
 const { Cc, Ci } = require("chrome");
 const { DataURL } = require("./url");
-const errors = require("./deprecated/errors");
 const apiUtils = require("./deprecated/api-utils");
 /*
 While these data flavors resemble Internet media types, they do
 no directly map to them.
 */
 const kAllowableFlavors = [
   "text/unicode",
   "text/html",
--- a/addon-sdk/source/lib/sdk/content/content-worker.js
+++ b/addon-sdk/source/lib/sdk/content/content-worker.js
@@ -105,17 +105,17 @@ Object.freeze({
       time: pipe.emit.bind(null, "console", "time"),
       timeEnd: pipe.emit.bind(null, "console", "timeEnd")
     });
   },
 
   injectTimers: function injectTimers(exports, chromeAPI, pipe, console) {
     // wrapped functions from `'timer'` module.
     // Wrapper adds `try catch` blocks to the callbacks in order to
-    // emit `error` event on a symbiont if exception is thrown in
+    // emit `error` event if exception is thrown in
     // the Worker global scope.
     // @see http://www.w3.org/TR/workers/#workerutils
 
     // List of all living timeouts/intervals
     let _timers = Object.create(null);
 
     // Keep a reference to original timeout functions
     let {
--- a/addon-sdk/source/lib/sdk/content/content.js
+++ b/addon-sdk/source/lib/sdk/content/content.js
@@ -4,29 +4,14 @@
 "use strict";
 
 module.metadata = {
   "stability": "deprecated"
 };
 
 const { deprecateUsage } = require('../util/deprecate');
 
-Object.defineProperty(exports, "Loader", { 
-  get: function() {
-    deprecateUsage('`sdk/content/content` is deprecated. Please use `sdk/content/loader` directly.');
-    return require('./loader').Loader;
-  }
-});
-
-Object.defineProperty(exports, "Symbiont", { 
-  get: function() {
-    deprecateUsage('Both `sdk/content/content` and `sdk/deprecated/symbiont` are deprecated. ' +
-                   '`sdk/core/heritage` supersedes Symbiont for inheritance.');
-    return require('../deprecated/symbiont').Symbiont;
-  }
-});
-
-Object.defineProperty(exports, "Worker", { 
+Object.defineProperty(exports, "Worker", {
   get: function() {
     deprecateUsage('`sdk/content/content` is deprecated. Please use `sdk/content/worker` directly.');
     return require('./worker').Worker;
   }
 });
--- a/addon-sdk/source/lib/sdk/content/loader.js
+++ b/addon-sdk/source/lib/sdk/content/loader.js
@@ -1,30 +1,28 @@
 /* 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 { EventEmitter } = require('../deprecated/events');
 const { isValidURI, isLocalURL, URL } = require('../url');
-const file = require('../io/file');
 const { contract } = require('../util/contract');
 const { isString, isNil, instanceOf } = require('../lang/type');
 const { validateOptions,
   string, array, object, either, required } = require('../deprecated/api-utils');
 
 const isJSONable = (value) => {
   try {
     JSON.parse(JSON.stringify(value));
-  } catch (e) {
+  }
+  catch (e) {
     return false;
   }
   return true;
 };
 
 const isValidScriptFile = (value) =>
   (isString(value) || instanceOf(value, URL)) && isLocalURL(value);
 
@@ -70,107 +68,9 @@ function validate(suspect, validation) v
   { $: validation }
 ).$
 
 function Allow(script) ({
   get script() script,
   set script(value) script = !!value
 })
 
-/**
- * Trait is intended to be used in some composition. It provides set of core
- * properties and bounded validations to them. Trait is useful for all the
- * compositions providing high level APIs for interaction with content.
- * Property changes emit `"propertyChange"` events on instances.
- */
-const Loader = EventEmitter.compose({
-  /**
-   * Permissions for the content, with the following keys:
-   * @property {Object} [allow = { script: true }]
-   * @property {Boolean} [allow.script = true]
-   *    Whether or not to execute script in the content.  Defaults to true.
-   */
-  get allow() this._allow || (this._allow = Allow(true)),
-  set allow(value) this.allow.script = value && value.script,
-  _allow: null,
-  /**
-   * The content to load. Either a string of HTML or a URL.
-   * @type {String}
-   */
-  get contentURL() this._contentURL,
-  set contentURL(value) {
-    value = validate(value, valid.contentURL);
-    if (this._contentURL != value) {
-      this._emit('propertyChange', {
-        contentURL: this._contentURL = value
-      });
-    }
-  },
-  _contentURL: null,
-  /**
-   * When to load the content scripts.
-   * Possible values are "end" (default), which loads them once all page
-   * contents have been loaded, "ready", which loads them once DOM nodes are
-   * ready (ie like DOMContentLoaded event), and "start", which loads them once
-   * the `window` object for the page has been created, but before any scripts
-   * specified by the page have been loaded.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {'start'|'ready'|'end'}
-   */
-  get contentScriptWhen() this._contentScriptWhen,
-  set contentScriptWhen(value) {
-    value = validate(value, valid.contentScriptWhen);
-    if (value !== this._contentScriptWhen) {
-      this._emit('propertyChange', {
-        contentScriptWhen: this._contentScriptWhen = value
-      });
-    }
-  },
-  _contentScriptWhen: 'end',
-  /**
-   * Options avalaible from the content script as `self.options`.
-   * The value of options can be of any type (object, array, string, etc.)
-   * but only jsonable values will be available as frozen objects from the
-   * content script.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {Object}
-   */
-  get contentScriptOptions() this._contentScriptOptions,
-  set contentScriptOptions(value) this._contentScriptOptions = value,
-  _contentScriptOptions: null,
-  /**
-   * The URLs of content scripts.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {String[]}
-   */
-  get contentScriptFile() this._contentScriptFile,
-  set contentScriptFile(value) {
-    value = validate(value, valid.contentScriptFile);
-    if (value != this._contentScriptFile) {
-      this._emit('propertyChange', {
-        contentScriptFile: this._contentScriptFile = value
-      });
-    }
-  },
-  _contentScriptFile: null,
-  /**
-   * The texts of content script.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {String|undefined}
-   */
-  get contentScript() this._contentScript,
-  set contentScript(value) {
-    value = validate(value, valid.contentScript);
-    if (value != this._contentScript) {
-      this._emit('propertyChange', {
-        contentScript: this._contentScript = value
-      });
-    }
-  },
-  _contentScript: null
-});
-exports.Loader = Loader;
-
 exports.contract = contract(valid);
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ b/addon-sdk/source/lib/sdk/content/sandbox.js
@@ -111,17 +111,17 @@ const WorkerSandbox = Class({
     this.emit = this.emit.bind(this);
     this.emitSync = this.emitSync.bind(this);
 
     // Use expanded principal for content-script if the content is a
     // regular web content for better isolation.
     // (This behavior can be turned off for now with the unsafe-content-script
     // flag to give addon developers time for making the necessary changes)
     // But prevent it when the Worker isn't used for a content script but for
-    // injecting `addon` object into a Panel, Widget, ... scope.
+    // injecting `addon` object into a Panel scope, for example.
     // That's because:
     // 1/ It is useless to use multiple domains as the worker is only used
     // to communicate with the addon,
     // 2/ By using it it would prevent the document to have access to any JS
     // value of the worker. As JS values coming from multiple domain principals
     // can't be accessed by 'mono-principals' (principal with only one domain).
     // Even if this principal is for a domain that is specified in the multiple
     // domain principal.
@@ -209,17 +209,17 @@ const WorkerSandbox = Class({
       Object.defineProperty(getUnsafeWindow(window), 'addon', {
           value: content.self,
           configurable: true
         }
       );
     }
 
     // Inject our `console` into target document if worker doesn't have a tab
-    // (e.g Panel, PageWorker, Widget).
+    // (e.g Panel, PageWorker).
     // `worker.tab` can't be used because bug 804935.
     if (!isWindowInTab(window)) {
       let win = getUnsafeWindow(window);
 
       // export our chrome console to content window, as described here:
       // https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
       let con = Cu.createObjectIn(win);
 
--- a/addon-sdk/source/lib/sdk/content/worker-child.js
+++ b/addon-sdk/source/lib/sdk/content/worker-child.js
@@ -29,16 +29,18 @@ const EVENTS = {
 const WorkerChild = Class({
   implements: [EventTarget],
 
   initialize(options) {
     merge(this, options);
     keepAlive.set(this.id, this);
 
     this.windowId = getInnerId(this.window);
+    if (this.contentScriptOptions)
+      this.contentScriptOptions = JSON.parse(this.contentScriptOptions);
 
     this.port = EventTarget();
     this.port.on('*', this.send.bind(this, 'event'));
     this.on('*', this.send.bind(this));
 
     this.observe = this.observe.bind(this);
 
     for (let topic in EVENTS)
@@ -48,41 +50,41 @@ const WorkerChild = Class({
     process.port.on('sdk/worker/message', this.receive);
 
     this.sandbox = WorkerSandbox(this, this.window);
 
     this.frozen = false;
     this.frozenMessages = [];
     this.on('pageshow', () => {
       this.frozen = false;
-      this.frozenMessages.forEach(args => this.receive(null, this.id, args));
+      this.frozenMessages.forEach(args => this.sandbox.emit(...args));
       this.frozenMessages = [];
     });
     this.on('pagehide', () => {
       this.frozen = true;
     });
   },
 
   // messages
   receive(process, id, args) {
     if (id !== this.id)
       return;
+    args = JSON.parse(args);
 
     if (this.frozen)
       this.frozenMessages.push(args);
     else
       this.sandbox.emit(...args);
 
     if (args[0] === 'detach')
       this.destroy(args[1]);
   },
 
   send(...args) {
-    args = JSON.parse(JSON.stringify(args, exceptions));
-    process.port.emit('sdk/worker/event', this.id, args);
+    process.port.emit('sdk/worker/event', this.id, JSON.stringify(args, exceptions));
   },
 
   // notifications
   observe({ type, subject }) {
     if (!this.sandbox)
       return;
 
     if (subject.defaultView && getInnerId(subject.defaultView) === this.windowId) {
@@ -126,17 +128,17 @@ function exceptions(key, value) {
   let { message, fileName, lineNumber, stack, name } = value;
   return { _errorType, message, fileName, lineNumber, stack, name };
 }
 
 // workers for windows in this tab
 let keepAlive = new Map();
 
 process.port.on('sdk/worker/create', (process, options) => {
-  options.window = getByInnerId(options.window);
+  options.window = getByInnerId(options.windowId);
   if (!options.window)
     return;
 
   let worker = new WorkerChild(options);
 });
 
 when(reason => {
   for (let worker of keepAlive.values())
--- a/addon-sdk/source/lib/sdk/content/worker.js
+++ b/addon-sdk/source/lib/sdk/content/worker.js
@@ -62,16 +62,17 @@ const Worker = Class({
     }
   },
 
   // messages
   receive(process, id, args) {
     let model = modelFor(this);
     if (id !== model.id || !model.attached)
       return;
+    args = JSON.parse(args);
     if (model.destroyed && args[0] != 'detach')
       return;
 
     if (args[0] === 'event')
       emit(this.port, ...args.slice(1))
     else
       emit(this, ...args);
   },
@@ -81,17 +82,17 @@ const Worker = Class({
     if (model.destroyed && args[0] !== 'detach')
       throw new Error(ERR_DESTROYED);
 
     if (!model.attached) {
       model.earlyEvents.push(args);
       return;
     }
 
-    processes.port.emit('sdk/worker/message', model.id, args);
+    processes.port.emit('sdk/worker/message', model.id, JSON.stringify(args));
   },
 
   // properties
   get url() {
     let { url } = modelFor(this);
     return url;
   },
 
@@ -122,25 +123,36 @@ attach.define(Worker, function(worker, w
     detach(worker);
 
   model.window = window;
   let frame = null;
   let tab = getTabForContentWindow(window.top);
   if (tab)
     frame = frames.getFrameForBrowser(getBrowserForTab(tab));
 
-  merge(model.options, {
-    id: String(uuid()),
-    window: getInnerId(window),
-    url: String(window.location)
-  });
+  function makeStringArray(arrayOrValue) {
+    if (!arrayOrValue)
+      return [];
+    return [String(v) for (v of [].concat(arrayOrValue))];
+  }
 
-  processes.port.emit('sdk/worker/create', model.options);
+  let id = String(uuid());
+  let childOptions = {
+    id,
+    windowId: getInnerId(window),
+    contentScript: makeStringArray(model.options.contentScript),
+    contentScriptFile: makeStringArray(model.options.contentScriptFile),
+    contentScriptOptions: model.options.contentScriptOptions ?
+                          JSON.stringify(model.options.contentScriptOptions) :
+                          null,
+  }
 
-  connect(worker, frame, model.options);
+  processes.port.emit('sdk/worker/create', childOptions);
+
+  connect(worker, frame, { id, url: String(window.location) });
 })
 
 connect.define(Worker, function(worker, frame, { id, url }) {
   let model = modelFor(worker);
   if (model.attached)
     detach(worker);
 
   model.id = id;
--- a/addon-sdk/source/lib/sdk/context-menu.js
+++ b/addon-sdk/source/lib/sdk/context-menu.js
@@ -444,17 +444,17 @@ let BaseItem = Class({
     return internal(this).parentMenu;
   },
 });
 
 function workerMessageReceived(process, id, args) {
   if (internal(this).id != id)
     return;
 
-  emit(this, ...args);
+  emit(this, ...JSON.parse(args));
 }
 
 // All things that have a label on the context menu extend this
 let LabelledItem = Class({
   extends: BaseItem,
   implements: [ EventTarget ],
 
   initialize: function initialize(options) {
--- a/addon-sdk/source/lib/sdk/core/promise.js
+++ b/addon-sdk/source/lib/sdk/core/promise.js
@@ -1,13 +1,11 @@
 /* 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/.
- */
-
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 /*
  * Uses `Promise.jsm` as a core implementation, with additional sugar
  * from previous implementation, with inspiration from `Q` and `when`
  *
  * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm
  * https://github.com/cujojs/when
--- a/addon-sdk/source/lib/sdk/deprecated/api-utils.js
+++ b/addon-sdk/source/lib/sdk/deprecated/api-utils.js
@@ -1,19 +1,17 @@
 /* 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";
 
-"use strict";
 module.metadata = {
   "stability": "deprecated"
 };
 
-const memory = require("./memory");
-
 const { merge } = require("../util/object");
 const { union } = require("../util/array");
 const { isNil, isRegExp } = require("../lang/type");
 
 // The possible return values of getTypeOf.
 const VALID_TYPES = [
   "array",
   "boolean",
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/cortex.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const getOwnIdentifiers = x => [...Object.getOwnPropertyNames(x),
-                                ...Object.getOwnPropertySymbols(x)];
-
-
-// `var` is being used in the module in order to make it reusable in
-// environments in which `let` and `const` is not yet supported.
-
-// Returns `object`'s property value, where `name` is a name of the property.
-function get(object, name) {
-  return object[name];
-}
-
-// Assigns `value` to the `object`'s property, where `name` is the name of the
-// property.
-function set(object, name, value) {
-  return object[name] = value;
-}
-
-/**
- * Given an `object` containing a property with the given `name`, create
- * a property descriptor that can be used to define alias/proxy properties
- * on other objects.  A change in the value of an alias will propagate
- * to the aliased property and vice versa.
- */
-function createAliasProperty(object, name) {
-  // Getting own property descriptor of an `object` for the given `name` as
-  // we are going to create proxy analog.
-  var property = Object.getOwnPropertyDescriptor(object, name);
-  var descriptor = {
-    configurable: property.configurable,
-    enumerable: property.enumerable,
-    alias: true
-  };
-
-  // If the original property has a getter and/or setter, bind a
-  // corresponding getter/setter in the alias descriptor to the original
-  // object, so the `this` object in the getter/setter is the original object
-  // rather than the alias.
-  if ("get" in property && property.get)
-    descriptor.get = property.get.bind(object);
-  if ("set" in property && property.set)
-    descriptor.set = property.set.bind(object);
-
-  // If original property was a value property.
-  if ("value" in property) {
-    // If original property is a method using it's `object` bounded copy.
-    if (typeof property.value === "function") {
-      descriptor.value = property.value.bind(object);
-      // Also preserving writability of the original property.
-      descriptor.writable = property.writable;
-    }
-
-    // If the original property was just a data property, we create proxy
-    // accessors using our custom get/set functions to propagate changes to the
-    // original `object` and vice versa.
-    else {
-      descriptor.get = get.bind(null, object, name);
-      descriptor.set = set.bind(null, object, name);
-    }
-  }
-  return descriptor;
-}
-
-// Defines property on `object` object with a name `alias` if given if not
-// defaults to `name` that represents an alias of `source[name]`. If aliased
-// property was an assessor or a method `this` pseudo-variable will be `source`
-// when invoked. If aliased property was a data property changes on any of the
-// aliases will propagate to the `source[name]` and also other way round.
-function defineAlias(source, target, name, alias) {
-  return Object.defineProperty(target, alias || name,
-                               createAliasProperty(source, name));
-}
-
-/**
- * Function takes any `object` and returns a proxy for its own public
- * properties. By default properties are considered to be public if they don't
- * start with `"_"`, but default behavior can be overridden if needed, by
- * passing array of public property `names` as a second argument. By default
- * returned object will be direct decedent of the given `object`'s prototype,
- * but this can be overridden by passing third optional argument, that will be
- * used as `prototype` instead.
- * @param {Object} object
- *    Object to create cortex for.
- * @param {String[]} [names]
- *    Optional array of public property names.
- * @param {Object} [prototype]
- *    Optional argument that will be used as `prototype` of the returned object,
- *    if not provided `Object.getPrototypeOf(object)` is used instead.
- */
-exports.Cortex = function Cortex(object, names, prototype) {
-  // Creating a cortex object from the given `prototype`, if one was not
-  // provided then `prototype` of a given `object` is used. This allows
-  // consumer to define expected behavior `instanceof`. In common case
-  // `prototype` argument can be omitted to preserve same behavior of
-  // `instanceof` as on original `object`.
-  var cortex = Object.create(prototype || Object.getPrototypeOf(object));
-  // Creating alias properties on the `cortex` object for all the own
-  // properties of the original `object` that are contained in `names` array.
-  // If `names` array is not provided then all the properties that don't
-  // start with `"_"` are aliased.
-  getOwnIdentifiers(object).forEach(function (name) {
-    if ((!names && "_" !== name.toString().charAt(0)) || (names && ~names.indexOf(name)))
-      defineAlias(object, cortex, name);
-  });
-  return cortex;
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/errors.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-function logToConsole(e) {
-  console.exception(e);
-}
-
-var catchAndLog = exports.catchAndLog = function(callback,
-                                                 defaultResponse,
-                                                 logException) {
-  if (!logException)
-    logException = logToConsole;
-
-  return function() {
-    try {
-      return callback.apply(this, arguments);
-    } catch (e) {
-      logException(e);
-      return defaultResponse;
-    }
-  };
-};
-
-exports.catchAndLogProps = function catchAndLogProps(object,
-                                                     props,
-                                                     defaultResponse,
-                                                     logException) {
-  if (typeof(props) == "string")
-    props = [props];
-  props.forEach(
-    function(property) {
-      object[property] = catchAndLog(object[property],
-                                     defaultResponse,
-                                     logException);
-    });
-};
-
-/**
- * Catch and return an exception while calling the callback.  If the callback
- * doesn't throw, return the return value of the callback in a way that makes it
- * possible to distinguish between a return value and an exception.
- *
- * This function is useful when you need to pass the result of a call across
- * a process boundary (across which exceptions don't propagate).  It probably
- * doesn't need to be factored out into this module, since it is only used by
- * a single caller, but putting it here works around bug 625560.
- */
-exports.catchAndReturn = function(callback) {
-  return function() {
-    try {
-      return { returnValue: callback.apply(this, arguments) };
-    }
-    catch (exception) {
-      return { exception: exception };
-    }
-  };
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/events.js
+++ /dev/null
@@ -1,181 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const ERROR_TYPE = 'error',
-      UNCAUGHT_ERROR = 'An error event was dispatched for which there was'
-        + ' no listener.',
-      BAD_LISTENER = 'The event listener must be a function.';
-/**
- * This object is used to create an `EventEmitter` that, useful for composing
- * objects that emit events. It implements an interface like `EventTarget` from
- * DOM Level 2, which is implemented by Node objects in implementations that
- * support the DOM Event Model.
- * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
- * @see http://nodejs.org/api.html#EventEmitter
- * @see http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/EventDispatcher.html
- */
-const eventEmitter =  {
-  /**
-   * Registers an event `listener` that is called every time events of
-   * specified `type` are emitted.
-   * @param {String} type
-   *    The type of event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   * @example
-   *      worker.on('message', function (data) {
-   *          console.log('data received: ' + data)
-   *      })
-   */
-  on: function on(type, listener) {
-    if ('function' !== typeof listener)
-      throw new Error(BAD_LISTENER);
-    let listeners = this._listeners(type);
-    if (0 > listeners.indexOf(listener))
-      listeners.push(listener);
-    // Use of `_public` is required by the legacy traits code that will go away
-    // once bug-637633 is fixed.
-    return this._public || this;
-  },
-
-  /**
-   * Registers an event `listener` that is called once the next time an event
-   * of the specified `type` is emitted.
-   * @param {String} type
-   *    The type of the event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   */
-  once: function once(type, listener) {
-    this.on(type, function selfRemovableListener() {
-      this.removeListener(type, selfRemovableListener);
-      listener.apply(this, arguments);
-    });
-  },
-
-  /**
-   * Unregister `listener` for the specified event type.
-   * @param {String} type
-   *    The type of event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   */
-  removeListener: function removeListener(type, listener) {
-    if ('function' !== typeof listener)
-      throw new Error(BAD_LISTENER);
-    let listeners = this._listeners(type),
-        index = listeners.indexOf(listener);
-    if (0 <= index)
-      listeners.splice(index, 1);
-    // Use of `_public` is required by the legacy traits code, that will go away
-    // once bug-637633 is fixed.
-    return this._public || this;
-  },
-
-  /**
-   * Hash of listeners on this EventEmitter.
-   */
-  _events: null,
-
-  /**
-   * Returns an array of listeners for the specified event `type`. This array
-   * can be manipulated, e.g. to remove listeners.
-   * @param {String} type
-   *    The type of event.
-   */
-  _listeners: function listeners(type) {
-    let events = this._events || (this._events = {});
-    return (events.hasOwnProperty(type) && events[type]) || (events[type] = []);
-  },
-
-  /**
-   * Execute each of the listeners in order with the supplied arguments.
-   * Returns `true` if listener for this event was called, `false` if there are
-   * no listeners for this event `type`.
-   *
-   * All the exceptions that are thrown by listeners during the emit
-   * are caught and can be handled by listeners of 'error' event. Thrown
-   * exceptions are passed as an argument to an 'error' event listener.
-   * If no 'error' listener is registered exception will propagate to a
-   * caller of this method.
-   *
-   * **It's recommended to have a default 'error' listener in all the complete
-   * composition that in worst case may dump errors to the console.**
-   *
-   * @param {String} type
-   *    The type of event.
-   * @params {Object|Number|String|Boolean}
-   *    Arguments that will be passed to listeners.
-   * @returns {Boolean}
-   */
-  _emit: function _emit(type, event) {
-    let args = Array.slice(arguments);
-    // Use of `_public` is required by the legacy traits code that will go away
-    // once bug-637633 is fixed.
-    args.unshift(this._public || this);
-    return this._emitOnObject.apply(this, args);
-  },
-
-  /**
-   * A version of _emit that lets you specify the object on which listeners are
-   * called.  This is a hack that is sometimes necessary when such an object
-   * (exports, for example) cannot be an EventEmitter for some reason, but other
-   * object(s) managing events for the object are EventEmitters.  Once bug
-   * 577782 is fixed, this method shouldn't be necessary.
-   *
-   * @param {object} targetObj
-   *    The object on which listeners will be called.
-   * @param {string} type
-   *    The event name.
-   * @param {value} event
-   *    The first argument to pass to listeners.
-   * @param {value} ...
-   *    More arguments to pass to listeners.
-   * @returns {boolean}
-   */
-  _emitOnObject: function _emitOnObject(targetObj, type, event /* , ... */) {
-    let listeners = this._listeners(type).slice(0);
-    // If there is no 'error' event listener then throw.
-    if (type === ERROR_TYPE && !listeners.length)
-      console.exception(event);
-    if (!listeners.length)
-      return false;
-    let params = Array.slice(arguments, 2);
-    for (let listener of listeners) {
-      try {
-        listener.apply(targetObj, params);
-      } catch(e) {
-        // Bug 726967: Ignore exceptions being throws while notifying the error
-        // in order to avoid infinite loops.
-        if (type !== ERROR_TYPE)
-          this._emit(ERROR_TYPE, e);
-        else
-          console.exception("Exception in error event listener " + e);
-      }
-    }
-    return true;
-  },
-
-  /**
-   * Removes all the event listeners for the specified event `type`.
-   * @param {String} type
-   *    The type of event.
-   */
-  _removeAllListeners: function _removeAllListeners(type) {
-    if (typeof type == "undefined") {
-      this._events = null;
-      return this;
-    }
-
-    this._listeners(type).splice(0);
-    return this;
-  }
-};
-exports.EventEmitter = require("./traits").Trait.compose(eventEmitter);
-exports.EventEmitterTrait = require('./light-traits').Trait(eventEmitter);
--- a/addon-sdk/source/lib/sdk/deprecated/events/assembler.js
+++ b/addon-sdk/source/lib/sdk/deprecated/events/assembler.js
@@ -1,20 +1,18 @@
 /* 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 { removeListener, on } = require("../../dom/events");
 
 /**
- * Trait may be used for building objects / composing traits that wish to handle
- * multiple dom events from multiple event targets in one place. Event targets
+ * Event targets
  * can be added / removed by calling `observe / ignore` methods. Composer should
  * provide array of event types it wishes to handle as property
  * `supportedEventsTypes` and function for handling all those events as
  * `handleEvent` property.
  */
 exports.DOMEventAssembler = Class({
   /**
    * Function that is supposed to handle all the supported events (that are
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/light-traits.js
+++ /dev/null
@@ -1,599 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-// `var` is being used in the module in order to make it reusable in
-// environments in which `let` is not yet supported.
-
-// Shortcut to `Object.prototype.hasOwnProperty.call`.
-// owns(object, name) would be the same as
-// Object.prototype.hasOwnProperty.call(object, name);
-var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
-
-/**
- * Whether or not given property descriptors are equivalent. They are
- * equivalent either if both are marked as 'conflict' or 'required' property
- * or if all the properties of descriptors are equal.
- * @param {Object} actual
- * @param {Object} expected
- */
-function equivalentDescriptors(actual, expected) {
-  return (actual.conflict && expected.conflict) ||
-         (actual.required && expected.required) ||
-         equalDescriptors(actual, expected);
-}
-/**
- * Whether or not given property descriptors define equal properties.
- */
-function equalDescriptors(actual, expected) {
-  return actual.get === expected.get &&
-         actual.set === expected.set &&
-         actual.value === expected.value &&
-         !!actual.enumerable === !!expected.enumerable &&
-         !!actual.configurable === !!expected.configurable &&
-         !!actual.writable === !!expected.writable;
-}
-
-// Utilities that throwing exceptions for a properties that are marked
-// as "required" or "conflict" properties.
-function throwConflictPropertyError(name) {
-  throw new Error("Remaining conflicting property: `" + name + "`");
-}
-function throwRequiredPropertyError(name) {
-  throw new Error("Missing required property: `" + name + "`");
-}
-
-/**
- * Generates custom **required** property descriptor. Descriptor contains
- * non-standard property `required` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function RequiredPropertyDescriptor(name) {
-  // Creating function by binding first argument to a property `name` on the
-  // `throwConflictPropertyError` function. Created function is used as a
-  // getter & setter of the created property descriptor. This way we ensure
-  // that we throw exception late (on property access) if object with
-  // `required` property was instantiated using built-in `Object.create`.
-  var accessor = throwRequiredPropertyError.bind(null, name);
-  return { get: accessor, set: accessor, required: true };
-}
-
-/**
- * Generates custom **conflicting** property descriptor. Descriptor contains
- * non-standard property `conflict` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function ConflictPropertyDescriptor(name) {
-  // For details see `RequiredPropertyDescriptor` since idea is same.
-  var accessor = throwConflictPropertyError.bind(null, name);
-  return { get: accessor, set: accessor, conflict: true };
-}
-
-/**
- * Tests if property is marked as `required` property.
- */
-function isRequiredProperty(object, name) {
-  return !!object[name].required;
-}
-
-/**
- * Tests if property is marked as `conflict` property.
- */
-function isConflictProperty(object, name) {
-  return !!object[name].conflict;
-}
-
-/**
- * Function tests whether or not method of the `source` object with a given
- * `name` is inherited from `Object.prototype`.
- */
-function isBuiltInMethod(name, source) {
-  var target = Object.prototype[name];
-
-  // If methods are equal then we know it's `true`.
-  return target == source ||
-  // If `source` object comes form a different sandbox `==` will evaluate
-  // to `false`, in that case we check if functions names and sources match.
-         (String(target) === String(source) && target.name === source.name);
-}
-
-/**
- * Function overrides `toString` and `constructor` methods of a given `target`
- * object with a same-named methods of a given `source` if methods of `target`
- * object are inherited / copied from `Object.prototype`.
- * @see create
- */
-function overrideBuiltInMethods(target, source) {
-  if (isBuiltInMethod("toString", target.toString)) {
-    Object.defineProperty(target, "toString",  {
-      value: source.toString,
-      configurable: true,
-      enumerable: false
-    });
-  }
-
-  if (isBuiltInMethod("constructor", target.constructor)) {
-    Object.defineProperty(target, "constructor", {
-      value: source.constructor,
-      configurable: true,
-      enumerable: false
-    });
-  }
-}
-
-/**
- * Composes new trait with the same own properties as the original trait,
- * except that all property names appearing in the first argument are replaced
- * by "required" property descriptors.
- * @param {String[]} keys
- *    Array of strings property names.
- * @param {Object} trait
- *    A trait some properties of which should be excluded.
- * @returns {Object}
- * @example
- *    var newTrait = exclude(["name", ...], trait)
- */
-function exclude(names, trait) {
-  var map = {};
-
-  Object.keys(trait).forEach(function(name) {
-
-    // If property is not excluded (the array of names does not contain it),
-    // or it is a "required" property, copy it to the property descriptor `map`
-    // that will be used for creation of resulting trait.
-    if (!~names.indexOf(name) || isRequiredProperty(trait, name))
-      map[name] = { value: trait[name], enumerable: true };
-
-    // For all the `names` in the exclude name array we create required
-    // property descriptors and copy them to the `map`.
-    else
-      map[name] = { value: RequiredPropertyDescriptor(name), enumerable: true };
-  });
-
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- * Composes new instance of `Trait` with a properties of a given `trait`,
- * except that all properties whose name is an own property of `renames` will
- * be renamed to `renames[name]` and a `"required"` property for name will be
- * added instead.
- *
- * For each renamed property, a required property is generated. If
- * the `renames` map two properties to the same name, a conflict is generated.
- * If the `renames` map a property to an existing unrenamed property, a
- * conflict is generated.
- *
- * @param {Object} renames
- *    An object whose own properties serve as a mapping from old names to new
- *    names.
- * @param {Object} trait
- *    A new trait with renamed properties.
- * @returns {Object}
- * @example
- *
- *    // Return trait with `bar` property equal to `trait.foo` and with
- *    // `foo` and `baz` "required" properties.
- *    var renamedTrait = rename({ foo: "bar", baz: null }), trait);
- *
- *    // t1 and t2 are equivalent traits
- *    var t1 = rename({a: "b"}, t);
- *    var t2 = compose(exclude(["a"], t), { a: { required: true }, b: t[a] });
- */
-function rename(renames, trait) {
-  var map = {};
-
-  // Loop over all the properties of the given `trait` and copy them to a
-  // property descriptor `map` that will be used for the creation of the
-  // resulting trait.  Also, rename properties in the `map` as specified by
-  // `renames`.
-  Object.keys(trait).forEach(function(name) {
-    var alias;
-
-    // If the property is in the `renames` map, and it isn't a "required"
-    // property (which should never need to be aliased because "required"
-    // properties never conflict), then we must try to rename it.
-    if (owns(renames, name) && !isRequiredProperty(trait, name)) {
-      alias = renames[name];
-
-      // If the `map` already has the `alias`, and it isn't a "required"
-      // property, that means the `alias` conflicts with an existing name for a
-      // provided trait (that can happen if >=2 properties are aliased to the
-      // same name). In this case we mark it as a conflicting property.
-      // Otherwise, everything is fine, and we copy property with an `alias`
-      // name.
-      if (owns(map, alias) && !map[alias].value.required) {
-        map[alias] = {
-          value: ConflictPropertyDescriptor(alias),
-          enumerable: true
-        };
-      }
-      else {
-        map[alias] = {
-          value: trait[name],
-          enumerable: true
-        };
-      }
-
-      // Regardless of whether or not the rename was successful, we check to
-      // see if the original `name` exists in the map (such a property
-      // could exist if previous another property was aliased to this `name`).
-      // If it isn't, we mark it as "required", to make sure the caller
-      // provides another value for the old name, which methods of the trait
-      // might continue to reference.
-      if (!owns(map, name)) {
-        map[name] = {
-          value: RequiredPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-    }
-
-    // Otherwise, either the property isn't in the `renames` map (thus the
-    // caller is not trying to rename it) or it is a "required" property.
-    // Either way, we don't have to alias the property, we just have to copy it
-    // to the map.
-    else {
-      // The property isn't in the map yet, so we copy it over.
-      if (!owns(map, name)) {
-        map[name] = { value: trait[name], enumerable: true };
-      }
-
-      // The property is already in the map (that means another property was
-      // aliased with this `name`, which creates a conflict if the property is
-      // not marked as "required"), so we have to mark it as a "conflict"
-      // property.
-      else if (!isRequiredProperty(trait, name)) {
-        map[name] = {
-          value: ConflictPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-    }
-  });
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- * Composes new resolved trait, with all the same properties as the original
- * `trait`, except that all properties whose name is an own property of
- * `resolutions` will be renamed to `resolutions[name]`.
- *
- * If `resolutions[name]` is `null`, the value is mapped to a property
- * descriptor that is marked as a "required" property.
- */
-function resolve(resolutions, trait) {
-    var renames = {};
-    var exclusions = [];
-
-    // Go through each mapping in `resolutions` object and distribute it either
-    // to `renames` or `exclusions`.
-    Object.keys(resolutions).forEach(function(name) {
-
-      // If `resolutions[name]` is a truthy value then it's a mapping old -> new
-      // so we copy it to `renames` map.
-      if (resolutions[name])
-        renames[name] = resolutions[name];
-
-      // Otherwise it's not a mapping but an exclusion instead in which case we
-      // add it to the `exclusions` array.
-      else
-        exclusions.push(name);
-    });
-
-    // First `exclude` **then** `rename` and order is important since
-    // `exclude` and `rename` are not associative.
-    return rename(renames, exclude(exclusions, trait));
-}
-
-/**
- * Create a Trait (a custom property descriptor map) that represents the given
- * `object`'s own properties. Property descriptor map is a "custom", because it
- * inherits from `Trait.prototype` and it's property descriptors may contain
- * two attributes that is not part of the ES5 specification:
- *
- *  - "required" (this property must be provided by another trait
- *    before an instance of this trait can be created)
- *  - "conflict" (when the trait is composed with another trait,
- *    a unique value for this property is provided by two or more traits)
- *
- * Data properties bound to the `Trait.required` singleton exported by
- * this module will be marked as "required" properties.
- *
- * @param {Object} object
- *    Map of properties to compose trait from.
- * @returns {Trait}
- *    Trait / Property descriptor map containing all the own properties of the
- *    given argument.
- */
-function trait(object) {
-  var map;
-  var trait = object;
-
-  if (!(object instanceof Trait)) {
-    // If the passed `object` is not already an instance of `Trait`, we create
-    // a property descriptor `map` containing descriptors for the own properties
-    // of the given `object`.  `map` is then used to create a `Trait` instance
-    // after all properties are mapped.  Note that we can't create a trait and
-    // then just copy properties into it since that will fail for inherited
-    // read-only properties.
-    map = {};
-
-    // Each own property of the given `object` is mapped to a data property
-    // whose value is a property descriptor.
-    Object.keys(object).forEach(function (name) {
-
-      // If property of an `object` is equal to a `Trait.required`, it means
-      // that it was marked as "required" property, in which case we map it
-      // to "required" property.
-      if (Trait.required ==
-          Object.getOwnPropertyDescriptor(object, name).value) {
-        map[name] = {
-          value: RequiredPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-      // Otherwise property is mapped to it's property descriptor.
-      else {
-        map[name] = {
-          value: Object.getOwnPropertyDescriptor(object, name),
-          enumerable: true
-        };
-      }
-    });
-
-    trait = Object.create(Trait.prototype, map);
-  }
-  return trait;
-}
-
-/**
- * Compose a property descriptor map that inherits from `Trait.prototype` and
- * contains property descriptors for all the own properties of the passed
- * traits.
- *
- * If two or more traits have own properties with the same name, the returned
- * trait will contain a "conflict" property for that name. Composition is a
- * commutative and associative operation, and the order of its arguments is
- * irrelevant.
- */
-function compose(trait1, trait2/*, ...*/) {
-  // Create a new property descriptor `map` to which all the own properties
-  // of the passed traits are copied.  This map will be used to create a `Trait`
-  // instance that will be the result of this composition.
-  var map = {};
-
-  // Properties of each passed trait are copied to the composition.
-  Array.prototype.forEach.call(arguments, function(trait) {
-    // Copying each property of the given trait.
-    Object.keys(trait).forEach(function(name) {
-
-      // If `map` already owns a property with the `name` and it is not
-      // marked "required".
-      if (owns(map, name) && !map[name].value.required) {
-
-        // If the source trait's property with the `name` is marked as
-        // "required", we do nothing, as the requirement was already resolved
-        // by a property in the `map` (because it already contains a
-        // non-required property with that `name`).  But if properties are just
-        // different, we have a name clash and we substitute it with a property
-        // that is marked "conflict".
-        if (!isRequiredProperty(trait, name) &&
-            !equivalentDescriptors(map[name].value, trait[name])
-        ) {
-          map[name] = {
-            value: ConflictPropertyDescriptor(name),
-            enumerable: true
-          };
-        }
-      }
-
-      // Otherwise, the `map` does not have an own property with the `name`, or
-      // it is marked "required".  Either way, the trait's property is copied to
-      // the map (if the property of the `map` is marked "required", it is going
-      // to be resolved by the property that is being copied).
-      else {
-        map[name] = { value: trait[name], enumerable: true };
-      }
-    });
-  });
-
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- *  `defineProperties` is like `Object.defineProperties`, except that it
- *  ensures that:
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "required" property and same named property is not
- *      found in a given `prototype`.
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "conflict" property.
- * @param {Object} object
- *    Object to define properties on.
- * @param {Object} properties
- *    Properties descriptor map.
- * @returns {Object}
- *    `object` that was passed as a first argument.
- */
-function defineProperties(object, properties) {
-
-  // Create a map into which we will copy each verified property from the given
-  // `properties` description map. We use it to verify that none of the
-  // provided properties is marked as a "conflict" property and that all
-  // "required" properties are resolved by a property of an `object`, so we
-  // can throw an exception before mutating object if that isn't the case.
-  var verifiedProperties = {};
-
-  // Coping each property from a given `properties` descriptor map to a
-  // verified map of property descriptors.
-  Object.keys(properties).forEach(function(name) {
-
-    // If property is marked as "required" property and we don't have a same
-    // named property in a given `object` we throw an exception. If `object`
-    // has same named property just skip this property since required property
-    // is was inherited and there for requirement was satisfied.
-    if (isRequiredProperty(properties, name)) {
-      if (!(name in object))
-        throwRequiredPropertyError(name);
-    }
-
-    // If property is marked as "conflict" property we throw an exception.
-    else if (isConflictProperty(properties, name)) {
-      throwConflictPropertyError(name);
-    }
-
-    // If property is not marked neither as "required" nor "conflict" property
-    // we copy it to verified properties map.
-    else {
-      verifiedProperties[name] = properties[name];
-    }
-  });
-
-  // If no exceptions were thrown yet, we know that our verified property
-  // descriptor map has no properties marked as "conflict" or "required",
-  // so we just delegate to the built-in `Object.defineProperties`.
-  return Object.defineProperties(object, verifiedProperties);
-}
-
-/**
- *  `create` is like `Object.create`, except that it ensures that:
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "required" property and same named property is not
- *      found in a given `prototype`.
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "conflict" property.
- * @param {Object} prototype
- *    prototype of the composed object
- * @param {Object} properties
- *    Properties descriptor map.
- * @returns {Object}
- *    An object that inherits form a given `prototype` and implements all the
- *    properties defined by a given `properties` descriptor map.
- */
-function create(prototype, properties) {
-
-  // Creating an instance of the given `prototype`.
-  var object = Object.create(prototype);
-
-  // Overriding `toString`, `constructor` methods if they are just inherited
-  // from `Object.prototype` with a same named methods of the `Trait.prototype`
-  // that will have more relevant behavior.
-  overrideBuiltInMethods(object, Trait.prototype);
-
-  // Trying to define given `properties` on the `object`. We use our custom
-  // `defineProperties` function instead of build-in `Object.defineProperties`
-  // that behaves exactly the same, except that it will throw if any
-  // property in the given `properties` descriptor is marked as "required" or
-  // "conflict" property.
-  return defineProperties(object, properties);
-}
-
-/**
- * Composes new trait. If two or more traits have own properties with the
- * same name, the new trait will contain a "conflict" property for that name.
- * "compose" is a commutative and associative operation, and the order of its
- * arguments is not significant.
- *
- * **Note:** Use `Trait.compose` instead of calling this function with more
- * than one argument. The multiple-argument functionality is strictly for
- * backward compatibility.
- *
- * @params {Object} trait
- *    Takes traits as an arguments
- * @returns {Object}
- *    New trait containing the combined own properties of all the traits.
- * @example
- *    var newTrait = compose(trait_1, trait_2, ..., trait_N)
- */
-function Trait(trait1, trait2) {
-
-  // If the function was called with one argument, the argument should be
-  // an object whose properties are mapped to property descriptors on a new
-  // instance of Trait, so we delegate to the trait function.
-  // If the function was called with more than one argument, those arguments
-  // should be instances of Trait or plain property descriptor maps
-  // whose properties should be mixed into a new instance of Trait,
-  // so we delegate to the compose function.
-
-  return trait2 === undefined ? trait(trait1) : compose.apply(null, arguments);
-}
-
-Object.freeze(Object.defineProperties(Trait.prototype, {
-  toString: {
-    value: function toString() {
-      return "[object " + this.constructor.name + "]";
-    }
-  },
-
-  /**
-   * `create` is like `Object.create`, except that it ensures that:
-   *    - An exception is thrown if this trait defines a property that is
-   *      marked as required property and same named property is not
-   *      found in a given `prototype`.
-   *    - An exception is thrown if this trait contains property that is
-   *      marked as "conflict" property.
-   * @param {Object}
-   *    prototype of the compared object
-   * @returns {Object}
-   *    An object with all of the properties described by the trait.
-   */
-  create: {
-    value: function createTrait(prototype) {
-      return create(undefined === prototype ? Object.prototype : prototype,
-                    this);
-    },
-    enumerable: true
-  },
-
-  /**
-   * Composes a new resolved trait, with all the same properties as the original
-   * trait, except that all properties whose name is an own property of
-   * `resolutions` will be renamed to the value of `resolutions[name]`. If
-   * `resolutions[name]` is `null`, the property is marked as "required".
-   * @param {Object} resolutions
-   *   An object whose own properties serve as a mapping from old names to new
-   *   names, or to `null` if the property should be excluded.
-   * @returns {Object}
-   *   New trait with the same own properties as the original trait but renamed.
-   */
-  resolve: {
-    value: function resolveTrait(resolutions) {
-      return resolve(resolutions, this);
-    },
-    enumerable: true
-  }
-}));
-
-/**
- * @see compose
- */
-Trait.compose = Object.freeze(compose);
-Object.freeze(compose.prototype);
-
-/**
- * Constant singleton, representing placeholder for required properties.
- * @type {Object}
- */
-Trait.required = Object.freeze(Object.create(Object.prototype, {
-  toString: {
-    value: Object.freeze(function toString() {
-      return "<Trait.required>";
-    })
-  }
-}));
-Object.freeze(Trait.required.toString.prototype);
-
-exports.Trait = Object.freeze(Trait);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/list.js
+++ /dev/null
@@ -1,125 +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 { Trait } = require('../deprecated/traits');
-
-/**
- * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/util_list
- */
-const Iterable = Trait.compose({
-  /**
-   * Hash map of key-values to iterate over.
-   * Note: That this property can be a getter if you need dynamic behavior.
-   * @type {Object}
-   */
-  _keyValueMap: Trait.required,
-  /**
-   * Custom iterator providing `Iterable`s enumeration behavior.
-   * @param {Boolean} onKeys
-   */
-  __iterator__: function __iterator__(onKeys, onKeyValue) {
-    let map = this._keyValueMap;
-    for (let key in map)
-      yield onKeyValue ? [key, map[key]] : onKeys ? key : map[key];
-  }
-});
-exports.Iterable = Iterable;
-
-/**
- * An ordered collection (also known as a sequence) disallowing duplicate
- * elements. List is composed out of `Iterable` there for it provides custom
- * enumeration behavior that is similar to array (enumerates only on the
- * elements of the list). List is a base trait and is meant to be a part of
- * composition, since all of it's API is private except length property.
- */
-const listOptions = {
-  _keyValueMap: null,
-  /**
-   * List constructor can take any number of element to populate itself.
-   * @params {Object|String|Number} element
-   * @example
-   *    List(1,2,3).length == 3 // true
-   */
-  constructor: function List() {
-    this._keyValueMap = [];
-    for (let i = 0, ii = arguments.length; i < ii; i++)
-      this._add(arguments[i]);
-  },
-  /**
-   * Number of elements in this list.
-   * @type {Number}
-   */
-  get length() this._keyValueMap.length,
-   /**
-    * Returns a string representing this list.
-    * @returns {String}
-    */
-  toString: function toString() 'List(' + this._keyValueMap + ')',
-  /**
-   * Returns `true` if this list contains the specified `element`.
-   * @param {Object|Number|String} element
-   * @returns {Boolean}
-   */
-  _has: function _has(element) 0 <= this._keyValueMap.indexOf(element),
-  /**
-   * Appends the specified `element` to the end of this list, if it doesn't
-   * contains it. Ignores the call if `element` is already contained.
-   * @param {Object|Number|String} element
-   */
-  _add: function _add(element) {
-    let list = this._keyValueMap,
-        index = list.indexOf(element);
-    if (0 > index)
-      list.push(this._public[list.length] = element);
-  },
-  /**
-   * Removes specified `element` from this list, if it contains it.
-   * Ignores the call if `element` is not contained.
-   * @param {Object|Number|String} element
-   */
-  _remove: function _remove(element) {
-    let list = this._keyValueMap,
-        index = list.indexOf(element);
-    if (0 <= index) {
-      delete this._public[list.length - 1];
-      list.splice(index, 1);
-      for (let length = list.length; index < length; index++)
-        this._public[index] = list[index];
-    }
-  },
-  /**
-   * Removes all of the elements from this list.
-   */
-  _clear: function _clear() {
-    for (let i = 0, ii = this._keyValueMap.length; i < ii; i ++)
-      delete this._public[i];
-    this._keyValueMap.splice(0);
-  },
-  /**
-   * Custom iterator providing `List`s enumeration behavior.
-   * We cant reuse `_iterator` that is defined by `Iterable` since it provides
-   * iteration in an arbitrary order.
-   * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
-   * @param {Boolean} onKeys
-   */
-  __iterator__: function __iterator__(onKeys, onKeyValue) {
-    let array = this._keyValueMap.slice(0),
-        i = -1;
-    for (let element of array)
-      yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
-  },
-};
-listOptions[Symbol.iterator] = function* iterator() {
-  let array = this._keyValueMap.slice(0);
-
-  for (let element of array)
-    yield element;
-}
-const List = Trait.resolve({ toString: null }).compose(listOptions);
-exports.List = List;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/symbiont.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const { Worker } = require('./traits-worker');
-const { Loader } = require('../content/loader');
-const hiddenFrames = require('../frame/hidden-frame');
-const { on, off } = require('../system/events');
-const unload = require('../system/unload');
-const { getDocShell } = require("../frame/utils");
-const { ignoreWindow } = require('../private-browsing/utils');
-
-// Everything coming from add-on's xpi considered an asset.
-const assetsURI = require('../self').data.url().replace(/data\/$/, "");
-
-/**
- * This trait is layered on top of `Worker` and in contrast to symbiont
- * Worker constructor requires `content` option that represents content
- * that will be loaded in the provided frame, if frame is not provided
- * Worker will create hidden one.
- */
-const Symbiont = Worker.resolve({
-    constructor: '_initWorker',
-    destroy: '_workerDestroy'
-  }).compose(Loader, {
-
-  /**
-   * The constructor requires all the options that are required by
-   * `require('content').Worker` with the difference that the `frame` option
-   * is optional. If `frame` is not provided, `contentURL` is expected.
-   * @param {Object} options
-   * @param {String} options.contentURL
-   *    URL of a content to load into `this._frame` and create worker for.
-   * @param {Element} [options.frame]
-   *    iframe element that is used to load `options.contentURL` into.
-   *    if frame is not provided hidden iframe will be created.
-   */
-  constructor: function Symbiont(options) {
-    options = options || {};
-
-    if ('contentURL' in options)
-        this.contentURL = options.contentURL;
-    if ('contentScriptWhen' in options)
-      this.contentScriptWhen = options.contentScriptWhen;
-    if ('contentScriptOptions' in options)
-      this.contentScriptOptions = options.contentScriptOptions;
-    if ('contentScriptFile' in options)
-      this.contentScriptFile = options.contentScriptFile;
-    if ('contentScript' in options)
-      this.contentScript = options.contentScript;
-    if ('allow' in options)
-      this.allow = options.allow;
-    if ('onError' in options)
-        this.on('error', options.onError);
-    if ('onMessage' in options)
-        this.on('message', options.onMessage);
-    if ('frame' in options) {
-      this._initFrame(options.frame);
-    }
-    else {
-      let self = this;
-      this._hiddenFrame = hiddenFrames.HiddenFrame({
-        onReady: function onFrame() {
-          self._initFrame(this.element);
-        },
-        onUnload: function onUnload() {
-          // Bug 751211: Remove reference to _frame when hidden frame is
-          // automatically removed on unload, otherwise we are going to face
-          // "dead object" exception
-          self.destroy();
-        }
-      });
-      hiddenFrames.add(this._hiddenFrame);
-    }
-
-    unload.ensure(this._public, "destroy");
-  },
-
-  destroy: function destroy() {
-    this._workerDestroy();
-    this._unregisterListener();
-    this._frame = null;
-    if (this._hiddenFrame) {
-      hiddenFrames.remove(this._hiddenFrame);
-      this._hiddenFrame = null;
-    }
-  },
-
-  /**
-   * XUL iframe or browser elements with attribute `type` being `content`.
-   * Used to create `ContentSymbiont` from.
-   * @type {nsIFrame|nsIBrowser}
-   */
-  _frame: null,
-
-  /**
-   * Listener to the `'frameReady"` event (emitted when `iframe` is ready).
-   * Removes listener, sets right permissions to the frame and loads content.
-   */
-  _initFrame: function _initFrame(frame) {
-    if (this._loadListener)
-      this._unregisterListener();
-
-    this._frame = frame;
-
-    if (getDocShell(frame)) {
-      this._reallyInitFrame(frame);
-    }
-    else {
-      if (this._waitForFrame) {
-        off('content-document-global-created', this._waitForFrame);
-      }
-      this._waitForFrame = this.__waitForFrame.bind(this, frame);
-      on('content-document-global-created', this._waitForFrame);
-    }
-  },
-
-  __waitForFrame: function _waitForFrame(frame, { subject: win }) {
-    if (frame.contentWindow == win) {
-      off('content-document-global-created', this._waitForFrame);
-      delete this._waitForFrame;
-      this._reallyInitFrame(frame);
-    }
-  },
-
-  _reallyInitFrame: function _reallyInitFrame(frame) {
-    getDocShell(frame).allowJavascript = this.allow.script;
-    frame.setAttribute("src", this._contentURL);
-
-    // Inject `addon` object in document if we load a document from
-    // one of our addon folder and if no content script are defined. bug 612726
-    let isDataResource =
-      typeof this._contentURL == "string" &&
-      this._contentURL.indexOf(assetsURI) == 0;
-    let hasContentScript =
-      (Array.isArray(this.contentScript) ? this.contentScript.length > 0
-                                             : !!this.contentScript) ||
-      (Array.isArray(this.contentScriptFile) ? this.contentScriptFile.length > 0
-                                             : !!this.contentScriptFile);
-    // If we have to inject `addon` we have to do it before document
-    // script execution, so during `start`:
-    this._injectInDocument = isDataResource && !hasContentScript;
-    if (this._injectInDocument)
-      this.contentScriptWhen = "start";
-
-    if ((frame.contentDocument.readyState == "complete" ||
-        (frame.contentDocument.readyState == "interactive" &&
-         this.contentScriptWhen != 'end' )) &&
-        frame.contentDocument.location == this._contentURL) {
-      // In some cases src doesn't change and document is already ready
-      // (for ex: when the user moves a widget while customizing toolbars.)
-      this._onInit();
-      return;
-    }
-
-    let self = this;
-
-    if ('start' == this.contentScriptWhen) {
-      this._loadEvent = 'start';
-      on('document-element-inserted',
-        this._loadListener = function onStart({ subject: doc }) {
-          let window = doc.defaultView;
-
-          if (ignoreWindow(window)) {
-            return;
-          }
-
-          if (window && window == frame.contentWindow) {
-            self._unregisterListener();
-            self._onInit();
-          }
-
-        });
-      return;
-    }
-
-    let eventName = 'end' == this.contentScriptWhen ? 'load' : 'DOMContentLoaded';
-    this._loadEvent = eventName;
-    frame.addEventListener(eventName,
-      this._loadListener = function _onReady(event) {
-
-        if (event.target != frame.contentDocument)
-          return;
-        self._unregisterListener();
-
-        self._onInit();
-
-      }, true);
-
-  },
-
-  /**
-   * Unregister listener that watchs for document being ready to be injected.
-   * This listener is registered in `Symbiont._initFrame`.
-   */
-  _unregisterListener: function _unregisterListener() {
-    if (this._waitForFrame) {
-      off('content-document-global-created', this._waitForFrame);
-      delete this._waitForFrame;
-    }
-
-    if (!this._loadListener)
-      return;
-    if (this._loadEvent == "start") {
-      off('document-element-inserted', this._loadListener);
-    }
-    else {
-      this._frame.removeEventListener(this._loadEvent, this._loadListener,
-                                      true);
-    }
-    this._loadListener = null;
-  },
-
-  /**
-   * Called by Symbiont itself when the frame is ready to load
-   * content scripts according to contentScriptWhen. Overloaded by Panel.
-   */
-  _onInit: function () {
-    this._initWorker({ window: this._frame.contentWindow });
-  }
-
-});
-exports.Symbiont = Symbiont;
--- a/addon-sdk/source/lib/sdk/deprecated/sync-worker.js
+++ b/addon-sdk/source/lib/sdk/deprecated/sync-worker.js
@@ -85,17 +85,17 @@ const Worker = Class({
       attach(this, options.window);
   },
 
   /**
    * Sends a message to the worker's global scope. Method takes single
    * argument, which represents data to be sent to the worker. The data may
    * be any primitive type value or `JSON`. Call of this method asynchronously
    * emits `message` event with data value in the global scope of this
-   * symbiont.
+   * worker.
    *
    * `message` event listeners can be set either by calling
    * `self.on` with a first argument string `"message"` or by
    * implementing `onMessage` function in the global scope of this worker.
    * @param {Number|String|JSON} data
    */
   postMessage: function (...data) {
     let model = modelFor(this);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits-worker.js
+++ /dev/null
@@ -1,636 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- *
- * `deprecated/traits-worker` was previously `content/worker` and kept
- * only due to `deprecated/symbiont` using it, which is necessary for
- * `widget`, until that reaches deprecation EOL.
- *
- */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const { Trait } = require('./traits');
-const { EventEmitter, EventEmitterTrait } = require('./events');
-const { Ci, Cu, Cc } = require('chrome');
-const timer = require('../timers');
-const { URL } = require('../url');
-const unload = require('../system/unload');
-const observers = require('../system/events');
-const { Cortex } = require('./cortex');
-const { sandbox, evaluate, load } = require("../loader/sandbox");
-const { merge } = require('../util/object');
-const { getInnerId } = require("../window/utils");
-const { getTabForWindow } = require('../tabs/helpers');
-const { getTabForContentWindow } = require('../tabs/utils');
-
-/* Trick the linker in order to ensure shipping these files in the XPI.
-  require('../content/content-worker.js');
-  Then, retrieve URL of these files in the XPI:
-*/
-let prefix = module.uri.split('deprecated/traits-worker.js')[0];
-const CONTENT_WORKER_URL = prefix + 'content/content-worker.js';
-
-// Fetch additional list of domains to authorize access to for each content
-// script. It is stored in manifest `metadata` field which contains
-// package.json data. This list is originaly defined by authors in
-// `permissions` attribute of their package.json addon file.
-const permissions = require('@loader/options').metadata['permissions'] || {};
-const EXPANDED_PRINCIPALS = permissions['cross-domain-content'] || [];
-
-const JS_VERSION = '1.8';
-
-const ERR_DESTROYED =
-  "Couldn't find the worker to receive this message. " +
-  "The script may not be initialized yet, or may already have been unloaded.";
-
-const ERR_FROZEN = "The page is currently hidden and can no longer be used " +
-                   "until it is visible again.";
-
-
-const WorkerSandbox = EventEmitter.compose({
-
-  /**
-   * Emit a message to the worker content sandbox
-   */
-  emit: function emit() {
-    // First ensure having a regular array
-    // (otherwise, `arguments` would be mapped to an object by `stringify`)
-    let array = Array.slice(arguments);
-    // JSON.stringify is buggy with cross-sandbox values,
-    // it may return "{}" on functions. Use a replacer to match them correctly.
-    function replacer(k, v) {
-      return typeof v === "function" ? undefined : v;
-    }
-    // Ensure having an asynchronous behavior
-    let self = this;
-    timer.setTimeout(function () {
-      self._emitToContent(JSON.stringify(array, replacer));
-    }, 0);
-  },
-
-  /**
-   * Synchronous version of `emit`.
-   * /!\ Should only be used when it is strictly mandatory /!\
-   *     Doesn't ensure passing only JSON values.
-   *     Mainly used by context-menu in order to avoid breaking it.
-   */
-  emitSync: function emitSync() {
-    let args = Array.slice(arguments);
-    return this._emitToContent(Cu.cloneInto(args, this._addonWorker._window));
-  },
-
-  /**
-   * Method called by the worker sandbox when it needs to send a message
-   */
-  _onContentEvent: function onContentEvent(args) {
-    // As `emit`, we ensure having an asynchronous behavior
-    let self = this;
-    timer.setTimeout(function () {
-      // We emit event to chrome/addon listeners
-      self._emit.apply(self, JSON.parse(args));
-    }, 0);
-  },
-
-  /**
-   * Configures sandbox and loads content scripts into it.
-   * @param {Worker} worker
-   *    content worker
-   */
-  constructor: function WorkerSandbox(worker) {
-    this._addonWorker = worker;
-
-    // Ensure that `emit` has always the right `this`
-    this.emit = this.emit.bind(this);
-    this.emitSync = this.emitSync.bind(this);
-
-    // We receive a wrapped window, that may be an xraywrapper if it's content
-    let window = worker._window;
-    let proto = window;
-
-    // Eventually use expanded principal sandbox feature, if some are given.
-    //
-    // But prevent it when the Worker isn't used for a content script but for
-    // injecting `addon` object into a Panel, Widget, ... scope.
-    // That's because:
-    // 1/ It is useless to use multiple domains as the worker is only used
-    // to communicate with the addon,
-    // 2/ By using it it would prevent the document to have access to any JS
-    // value of the worker. As JS values coming from multiple domain principals
-    // can't be accessed by "mono-principals" (principal with only one domain).
-    // Even if this principal is for a domain that is specified in the multiple
-    // domain principal.
-    let principals  = window;
-    let wantGlobalProperties = []
-    if (EXPANDED_PRINCIPALS.length > 0 && !worker._injectInDocument) {
-      principals = EXPANDED_PRINCIPALS.concat(window);
-      // We have to replace XHR constructor of the content document
-      // with a custom cross origin one, automagically added by platform code:
-      delete proto.XMLHttpRequest;
-      wantGlobalProperties.push("XMLHttpRequest");
-    }
-
-    // Create the sandbox and bind it to window in order for content scripts to
-    // have access to all standard globals (window, document, ...)
-    let content = this._sandbox = sandbox(principals, {
-      sandboxPrototype: proto,
-      wantXrays: !worker._injectInDocument,
-      wantGlobalProperties: wantGlobalProperties,
-      sameZoneAs: window,
-      metadata: {
-        SDKContentScript: true,
-        'inner-window-id': getInnerId(window)
-      }
-    });
-    // We have to ensure that window.top and window.parent are the exact same
-    // object than window object, i.e. the sandbox global object. But not
-    // always, in case of iframes, top and parent are another window object.
-    let top = window.top === window ? content : content.top;
-    let parent = window.parent === window ? content : content.parent;
-    merge(content, {
-      // We need "this === window === top" to be true in toplevel scope:
-      get window() content,
-      get top() top,
-      get parent() parent
-    });
-    // Use the Greasemonkey naming convention to provide access to the
-    // unwrapped window object so the content script can access document
-    // JavaScript values.
-    // NOTE: this functionality is experimental and may change or go away
-    // at any time!
-    //
-    // Note that because waivers aren't propagated between origins, we
-    // need the unsafeWindow getter to live in the sandbox.
-    var unsafeWindowGetter =
-      new content.Function('return window.wrappedJSObject || window;');
-    Object.defineProperty(content, 'unsafeWindow', {get: unsafeWindowGetter});
-
-
-    // Load trusted code that will inject content script API.
-    let ContentWorker = load(content, CONTENT_WORKER_URL);
-
-    // prepare a clean `self.options`
-    let options = 'contentScriptOptions' in worker ?
-      JSON.stringify( worker.contentScriptOptions ) :
-      undefined;
-
-    // Then call `inject` method and communicate with this script
-    // by trading two methods that allow to send events to the other side:
-    //   - `onEvent` called by content script
-    //   - `result.emitToContent` called by addon script
-    let chromeAPI = Cu.cloneInto({
-      timers: {
-        setTimeout: timer.setTimeout.bind(timer),
-        setInterval: timer.setInterval.bind(timer),
-        clearTimeout: timer.clearTimeout.bind(timer),
-        clearInterval: timer.clearInterval.bind(timer),
-      },
-      sandbox: {
-        evaluate: evaluate,
-      },
-    }, ContentWorker, {cloneFunctions: true});
-    let onEvent = Cu.exportFunction(this._onContentEvent.bind(this), ContentWorker);
-    let result = Cu.waiveXrays(ContentWorker).inject(content, chromeAPI, onEvent, options);
-    this._emitToContent = result;
-
-    // Handle messages send by this script:
-    let self = this;
-    // console.xxx calls
-    this.on("console", function consoleListener(kind) {
-      console[kind].apply(console, Array.slice(arguments, 1));
-    });
-
-    // self.postMessage calls
-    this.on("message", function postMessage(data) {
-      // destroyed?
-      if (self._addonWorker)
-        self._addonWorker._emit('message', data);
-    });
-
-    // self.port.emit calls
-    this.on("event", function portEmit(name, args) {
-      // destroyed?
-      if (self._addonWorker)
-        self._addonWorker._onContentScriptEvent.apply(self._addonWorker, arguments);
-    });
-
-    // unwrap, recreate and propagate async Errors thrown from content-script
-    this.on("error", function onError({instanceOfError, value}) {
-      if (self._addonWorker) {
-        let error = value;
-        if (instanceOfError) {
-          error = new Error(value.message, value.fileName, value.lineNumber);
-          error.stack = value.stack;
-          error.name = value.name;
-        }
-        self._addonWorker._emit('error', error);
-      }
-    });
-
-    // Inject `addon` global into target document if document is trusted,
-    // `addon` in document is equivalent to `self` in content script.
-    if (worker._injectInDocument) {
-      let win = window.wrappedJSObject ? window.wrappedJSObject : window;
-      Object.defineProperty(win, "addon", {
-          value: content.self,
-          configurable: true
-        }
-      );
-    }
-
-    // Inject our `console` into target document if worker doesn't have a tab
-    // (e.g Panel, PageWorker, Widget).
-    // `worker.tab` can't be used because bug 804935.
-    if (!getTabForContentWindow(window)) {
-      let win = window.wrappedJSObject ? window.wrappedJSObject : window;
-
-      // export our chrome console to content window as described here:
-      // https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
-      let con = Cu.createObjectIn(win);
-
-      let genPropDesc = function genPropDesc(fun) {
-        return { enumerable: true, configurable: true, writable: true,
-          value: console[fun] };
-      }
-
-      const properties = {
-        log: genPropDesc('log'),
-        info: genPropDesc('info'),
-        warn: genPropDesc('warn'),
-        error: genPropDesc('error'),
-        debug: genPropDesc('debug'),
-        trace: genPropDesc('trace'),
-        dir: genPropDesc('dir'),
-        group: genPropDesc('group'),
-        groupCollapsed: genPropDesc('groupCollapsed'),
-        groupEnd: genPropDesc('groupEnd'),
-        time: genPropDesc('time'),
-        timeEnd: genPropDesc('timeEnd'),
-        profile: genPropDesc('profile'),
-        profileEnd: genPropDesc('profileEnd'),
-        exception: genPropDesc('exception'),
-        assert: genPropDesc('assert'),
-        count: genPropDesc('count'),
-        table: genPropDesc('table'),
-        clear: genPropDesc('clear'),
-        dirxml: genPropDesc('dirxml'),
-        markTimeline: genPropDesc('markTimeline'),
-        timeline: genPropDesc('timeline'),
-        timelineEnd: genPropDesc('timelineEnd'),
-        timeStamp: genPropDesc('timeStamp'),
-      };
-
-      Object.defineProperties(con, properties);
-      Cu.makeObjectPropsNormal(con);
-
-      win.console = con;
-    };
-
-    // The order of `contentScriptFile` and `contentScript` evaluation is
-    // intentional, so programs can load libraries like jQuery from script URLs
-    // and use them in scripts.
-    let contentScriptFile = ('contentScriptFile' in worker) ? worker.contentScriptFile
-          : null,
-        contentScript = ('contentScript' in worker) ? worker.contentScript : null;
-
-    if (contentScriptFile) {
-      if (Array.isArray(contentScriptFile))
-        this._importScripts.apply(this, contentScriptFile);
-      else
-        this._importScripts(contentScriptFile);
-    }
-    if (contentScript) {
-      this._evaluate(
-        Array.isArray(contentScript) ? contentScript.join(';\n') : contentScript
-      );
-    }
-  },
-  destroy: function destroy() {
-    this.emitSync("detach");
-    this._sandbox = null;
-    this._addonWorker = null;
-  },
-
-  /**
-   * JavaScript sandbox where all the content scripts are evaluated.
-   * {Sandbox}
-   */
-  _sandbox: null,
-
-  /**
-   * Reference to the addon side of the worker.
-   * @type {Worker}
-   */
-  _addonWorker: null,
-
-  /**
-   * Evaluates code in the sandbox.
-   * @param {String} code
-   *    JavaScript source to evaluate.
-   * @param {String} [filename='javascript:' + code]
-   *    Name of the file
-   */
-  _evaluate: function(code, filename) {
-    try {
-      evaluate(this._sandbox, code, filename || 'javascript:' + code);
-    }
-    catch(e) {
-      this._addonWorker._emit('error', e);
-    }
-  },
-  /**
-   * Imports scripts to the sandbox by reading files under urls and
-   * evaluating its source. If exception occurs during evaluation
-   * `"error"` event is emitted on the worker.
-   * This is actually an analog to the `importScript` method in web
-   * workers but in our case it's not exposed even though content
-   * scripts may be able to do it synchronously since IO operation
-   * takes place in the UI process.
-   */
-  _importScripts: function _importScripts(url) {
-    let urls = Array.slice(arguments, 0);
-    for (let contentScriptFile of urls) {
-      try {
-        let uri = URL(contentScriptFile);
-        if (uri.scheme === 'resource')
-          load(this._sandbox, String(uri));
-        else
-          throw Error("Unsupported `contentScriptFile` url: " + String(uri));
-      }
-      catch(e) {
-        this._addonWorker._emit('error', e);
-      }
-    }
-  }
-});
-
-/**
- * Message-passing facility for communication between code running
- * in the content and add-on process.
- * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker
- */
-const Worker = EventEmitter.compose({
-  on: Trait.required,
-  _removeAllListeners: Trait.required,
-
-  // List of messages fired before worker is initialized
-  get _earlyEvents() {
-    delete this._earlyEvents;
-    this._earlyEvents = [];
-    return this._earlyEvents;
-  },
-
-  /**
-   * Sends a message to the worker's global scope. Method takes single
-   * argument, which represents data to be sent to the worker. The data may
-   * be any primitive type value or `JSON`. Call of this method asynchronously
-   * emits `message` event with data value in the global scope of this
-   * symbiont.
-   *
-   * `message` event listeners can be set either by calling
-   * `self.on` with a first argument string `"message"` or by
-   * implementing `onMessage` function in the global scope of this worker.
-   * @param {Number|String|JSON} data
-   */
-  postMessage: function (data) {
-    let args = ['message'].concat(Array.slice(arguments));
-    if (!this._inited) {
-      this._earlyEvents.push(args);
-      return;
-    }
-    processMessage.apply(this, args);
-  },
-
-  /**
-   * EventEmitter, that behaves (calls listeners) asynchronously.
-   * A way to send customized messages to / from the worker.
-   * Events from in the worker can be observed / emitted via
-   * worker.on / worker.emit.
-   */
-  get port() {
-    // We generate dynamically this attribute as it needs to be accessible
-    // before Worker.constructor gets called. (For ex: Panel)
-
-    // create an event emitter that receive and send events from/to the worker
-    this._port = EventEmitterTrait.create({
-      emit: this._emitEventToContent.bind(this)
-    });
-
-    // expose wrapped port, that exposes only public properties:
-    // We need to destroy this getter in order to be able to set the
-    // final value. We need to update only public port attribute as we never
-    // try to access port attribute from private API.
-    delete this._public.port;
-    this._public.port = Cortex(this._port);
-    // Replicate public port to the private object
-    delete this.port;
-    this.port = this._public.port;
-
-    return this._port;
-  },
-
-  /**
-   * Same object than this.port but private API.
-   * Allow access to _emit, in order to send event to port.
-   */
-  _port: null,
-
-  /**
-   * Emit a custom event to the content script,
-   * i.e. emit this event on `self.port`
-   */
-  _emitEventToContent: function () {
-    let args = ['event'].concat(Array.slice(arguments));
-    if (!this._inited) {
-      this._earlyEvents.push(args);
-      return;
-    }
-    processMessage.apply(this, args);
-  },
-
-  // Is worker connected to the content worker sandbox ?
-  _inited: false,
-
-  // Is worker being frozen? i.e related document is frozen in bfcache.
-  // Content script should not be reachable if frozen.
-  _frozen: true,
-
-  constructor: function Worker(options) {
-    options = options || {};
-
-    if ('contentScriptFile' in options)
-      this.contentScriptFile = options.contentScriptFile;
-    if ('contentScriptOptions' in options)
-      this.contentScriptOptions = options.contentScriptOptions;
-    if ('contentScript' in options)
-      this.contentScript = options.contentScript;
-
-    this._setListeners(options);
-
-    unload.ensure(this._public, "destroy");
-
-    // Ensure that worker._port is initialized for contentWorker to be able
-    // to send events during worker initialization.
-    this.port;
-
-    this._documentUnload = this._documentUnload.bind(this);
-    this._pageShow = this._pageShow.bind(this);
-    this._pageHide = this._pageHide.bind(this);
-
-    if ("window" in options) this._attach(options.window);
-  },
-
-  _setListeners: function(options) {
-    if ('onError' in options)
-      this.on('error', options.onError);
-    if ('onMessage' in options)
-      this.on('message', options.onMessage);
-    if ('onDetach' in options)
-      this.on('detach', options.onDetach);
-  },
-
-  _attach: function(window) {
-    this._window = window;
-    // Track document unload to destroy this worker.
-    // We can't watch for unload event on page's window object as it
-    // prevents bfcache from working:
-    // https://developer.mozilla.org/En/Working_with_BFCache
-    this._windowID = getInnerId(this._window);
-    observers.on("inner-window-destroyed", this._documentUnload);
-
-    // Listen to pagehide event in order to freeze the content script
-    // while the document is frozen in bfcache:
-    this._window.addEventListener("pageshow", this._pageShow, true);
-    this._window.addEventListener("pagehide", this._pageHide, true);
-
-    // will set this._contentWorker pointing to the private API:
-    this._contentWorker = WorkerSandbox(this);
-
-    // Mainly enable worker.port.emit to send event to the content worker
-    this._inited = true;
-    this._frozen = false;
-
-    // Process all events and messages that were fired before the
-    // worker was initialized.
-    this._earlyEvents.forEach((function (args) {
-      processMessage.apply(this, args);
-    }).bind(this));
-  },
-
-  _documentUnload: function _documentUnload({ subject, data }) {
-    let innerWinID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    if (innerWinID != this._windowID) return false;
-    this._workerCleanup();
-    return true;
-  },
-
-  _pageShow: function _pageShow() {
-    this._contentWorker.emitSync("pageshow");
-    this._emit("pageshow");
-    this._frozen = false;
-  },
-
-  _pageHide: function _pageHide() {
-    this._contentWorker.emitSync("pagehide");
-    this._emit("pagehide");
-    this._frozen = true;
-  },
-
-  get url() {
-    // this._window will be null after detach
-    return this._window ? this._window.document.location.href : null;
-  },
-
-  get tab() {
-    // this._window will be null after detach
-    if (this._window)
-      return getTabForWindow(this._window);
-    return null;
-  },
-
-  /**
-   * Tells content worker to unload itself and
-   * removes all the references from itself.
-   */
-  destroy: function destroy() {
-    this._workerCleanup();
-    this._inited = true;
-    this._removeAllListeners();
-  },
-
-  /**
-   * Remove all internal references to the attached document
-   * Tells _port to unload itself and removes all the references from itself.
-   */
-  _workerCleanup: function _workerCleanup() {
-    // maybe unloaded before content side is created
-    // As Symbiont call worker.constructor on document load
-    if (this._contentWorker)
-      this._contentWorker.destroy();
-    this._contentWorker = null;
-    if (this._window) {
-      this._window.removeEventListener("pageshow", this._pageShow, true);
-      this._window.removeEventListener("pagehide", this._pageHide, true);
-    }
-    this._window = null;
-    // This method may be called multiple times,
-    // avoid dispatching `detach` event more than once
-    if (this._windowID) {
-      this._windowID = null;
-      observers.off("inner-window-destroyed", this._documentUnload);
-      this._earlyEvents.length = 0;
-      this._emit("detach");
-    }
-    this._inited = false;
-  },
-
-  /**
-   * Receive an event from the content script that need to be sent to
-   * worker.port. Provide a way for composed object to catch all events.
-   */
-  _onContentScriptEvent: function _onContentScriptEvent() {
-    this._port._emit.apply(this._port, arguments);
-  },
-
-  /**
-   * Reference to the content side of the worker.
-   * @type {WorkerGlobalScope}
-   */
-  _contentWorker: null,
-
-  /**
-   * Reference to the window that is accessible from
-   * the content scripts.
-   * @type {Object}
-   */
-  _window: null,
-
-  /**
-   * Flag to enable `addon` object injection in document. (bug 612726)
-   * @type {Boolean}
-   */
-  _injectInDocument: false
-});
-
-/**
- * Fired from postMessage and _emitEventToContent, or from the _earlyMessage
- * queue when fired before the content is loaded. Sends arguments to
- * contentWorker if able
- */
-
-function processMessage () {
-  if (!this._contentWorker)
-    throw new Error(ERR_DESTROYED);
-  if (this._frozen)
-    throw new Error(ERR_FROZEN);
-
-  this._contentWorker.emit.apply(null, Array.slice(arguments));
-}
-
-exports.Worker = Worker;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits.js
+++ /dev/null
@@ -1,186 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const {
-  compose: _compose,
-  override: _override,
-  resolve: _resolve,
-  trait: _trait,
-  //create: _create,
-  required,
-} = require('./traits/core');
-
-const { getOwnPropertyIdentifiers } = require('../util/object');
-const defineProperties = Object.defineProperties;
-const freeze = Object.freeze;
-const create = Object.create;
-
-/**
- * Work around bug 608959 by defining the _create function here instead of
- * importing it from traits/core.  For docs on this function, see the create
- * function in that module.
- *
- * FIXME: remove this workaround in favor of importing the function once that
- * bug has been fixed.
- */
-function _create(proto, trait) {
-  let properties = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    let descriptor = trait[key];
-    if (descriptor.required &&
-        !Object.prototype.hasOwnProperty.call(proto, key))
-      throw new Error('Missing required property: ' + key);
-    else if (descriptor.conflict)
-      throw new Error('Remaining conflicting property: ' + key);
-    else
-      properties[key] = descriptor;
-  }
-  return Object.create(proto, properties);
-}
-
-/**
- * Placeholder for `Trait.prototype`
- */
-let TraitProto = Object.prototype;
-
-function Get(key) this[key]
-function Set(key, value) this[key] = value
-
-/**
- * Creates anonymous trait descriptor from the passed argument, unless argument
- * is a trait constructor. In later case trait's already existing properties
- * descriptor is returned.
- * This is module's internal function and is used as a gateway to a trait's
- * internal properties descriptor.
- * @param {Function} $
- *    Composed trait's constructor.
- * @returns {Object}
- *    Private trait property of the composition.
- */
-function TraitDescriptor(object)
-  (
-    'function' == typeof object &&
-    (object.prototype == TraitProto || object.prototype instanceof Trait)
-  ) ? object._trait(TraitDescriptor) : _trait(object)
-
-function Public(instance, trait) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    if (typeof key === 'string' && '_' === key.charAt(0) && '__iterator__' !== key )
-      continue;
-    let property = trait[key],
-        descriptor = {
-          configurable: property.configurable,
-          enumerable: property.enumerable
-        };
-    if (property.get)
-      descriptor.get = property.get.bind(instance);
-    if (property.set)
-      descriptor.set = property.set.bind(instance);
-    if ('value' in property) {
-      let value = property.value;
-      if ('function' === typeof value) {
-        descriptor.value = property.value.bind(instance);
-        descriptor.writable = property.writable;
-      } else {
-        descriptor.get = Get.bind(instance, key);
-        descriptor.set = Set.bind(instance, key);
-      }
-    }
-    result[key] = descriptor;
-  }
-  return result;
-}
-
-/**
- * This is private function that composes new trait with privates.
- */
-function Composition(trait) {
-  function Trait() {
-    let self = _create({}, trait);
-    self._public = create(Trait.prototype, Public(self, trait));
-    delete self._public.constructor;
-    if (Object === self.constructor)
-      self.constructor = Trait;
-    else
-      return self.constructor.apply(self, arguments) || self._public;
-    return self._public;
-  }
-  defineProperties(Trait, {
-    prototype: { value: freeze(create(TraitProto, {
-      constructor: { value: constructor, writable: true }
-    }))}, // writable is `true` to avoid getters in custom ES5
-    displayName: { value: (trait.constructor || constructor).name },
-    compose: { value: compose, enumerable: true },
-    override: { value: override, enumerable: true },
-    resolve: { value: resolve, enumerable: true },
-    required: { value: required, enumerable: true },
-    _trait: { value: function _trait(caller)
-        caller ===  TraitDescriptor ? trait : undefined
-    }
-  });
-  return freeze(Trait);
-}
-
-/**
- * Composes new trait out of itself and traits / property maps passed as an
- * arguments. If two or more traits / property maps have properties with the
- * same name, the new trait will contain a "conflict" property for that name.
- * This is a commutative and associative operation, and the order of its
- * arguments is not significant.
- * @params {Object|Function}
- *    List of Traits or property maps to create traits from.
- * @returns {Function}
- *    New trait containing the combined properties of all the traits.
- */
-function compose() {
-  let traits = Array.slice(arguments, 0);
-  traits.push(this);
-  return Composition(_compose.apply(null, traits.map(TraitDescriptor)));
-}
-
-/**
- * Composes a new trait with all of the combined properties of `this` and the
- * argument traits. In contrast to `compose`, `override` immediately resolves
- * all conflicts resulting from this composition by overriding the properties of
- * later traits. Trait priority is from left to right. I.e. the properties of
- * the leftmost trait are never overridden.
- * @params {Object} trait
- * @returns {Object}
- */
-function override() {
-  let traits = Array.slice(arguments, 0);
-  traits.push(this);
-  return Composition(_override.apply(null, traits.map(TraitDescriptor)));
-}
-
-/**
- * Composes new resolved trait, with all the same properties as this
- * trait, except that all properties whose name is an own property of
- * `resolutions` will be renamed to `resolutions[name]`. If it is
- * `resolutions[name]` is `null` value is changed into a required property
- * descriptor.
- */
-function resolve(resolutions)
-  Composition(_resolve(resolutions, TraitDescriptor(this)))
-
-/**
- * Base Trait, that all the traits are composed of.
- */
-const Trait = Composition({
-  /**
-   * Internal property holding public API of this instance.
-   */
-  _public: { value: null, configurable: true, writable: true },
-  toString: { value: function() '[object ' + this.constructor.name + ']' }
-});
-TraitProto = Trait.prototype;
-exports.Trait = Trait;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits/core.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-// Design inspired by: http://www.traitsjs.org/
-
-const { getOwnPropertyIdentifiers } = require('../../util/object');
-const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-const hasOwn = Object.prototype.hasOwnProperty;
-const _create = Object.create;
-
-function doPropertiesMatch(object1, object2, name) {
-  // If `object1` has property with the given `name`
-  return name in object1 ?
-         // then `object2` should have it with the same value.
-         name in object2 && object1[name] === object2[name] :
-         // otherwise `object2` should not have property with the given `name`.
-         !(name in object2);
-}
-
-/**
- * Compares two trait custom property descriptors if they are the same. If
- * both are `conflict` or all the properties of descriptor are equal returned
- * value will be `true`, otherwise it will be `false`.
- * @param {Object} desc1
- * @param {Object} desc2
- */
-function areSame(desc1, desc2) {
-  return ('conflict' in desc1 && desc1.conflict &&
-          'conflict' in desc2 && desc2.conflict) ||
-         (doPropertiesMatch(desc1, desc2, 'get') &&
-          doPropertiesMatch(desc1, desc2, 'set') &&
-          doPropertiesMatch(desc1, desc2, 'value') &&
-          doPropertiesMatch(desc1, desc2, 'enumerable') &&
-          doPropertiesMatch(desc1, desc2, 'required') &&
-          doPropertiesMatch(desc1, desc2, 'conflict'));
-}
-
-/**
- * Converts array to an object whose own property names represent
- * values of array.
- * @param {String[]} names
- * @returns {Object}
- * @example
- *  Map(['foo', ...]) => { foo: true, ...}
- */
-function Map(names) {
-  let map = {};
-  for (let name of names)
-    map[name] = true;
-  return map;
-}
-
-
-const ERR_CONFLICT = 'Remaining conflicting property: ',
-      ERR_REQUIRED = 'Missing required property: ';
-/**
- * Constant singleton, representing placeholder for required properties.
- * @type {Object}
- */
-const required = { toString: function()'<Trait.required>' };
-exports.required = required;
-
-/**
- * Generates custom **required** property descriptor. Descriptor contains
- * non-standard property `required` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function Required(name) {
-  function required() { throw new Error(ERR_REQUIRED + name) }
-  return {
-    get: required,
-    set: required,
-    required: true
-  };
-}
-
-/**
- * Generates custom **conflicting** property descriptor. Descriptor contains
- * non-standard property `conflict` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function Conflict(name) {
-  function conflict() { throw new Error(ERR_CONFLICT + name) }
-  return {
-    get: conflict,
-    set: conflict,
-    conflict: true
-  };
-}
-
-/**
- * Function generates custom properties descriptor of the `object`s own
- * properties. All the inherited properties are going to be ignored.
- * Properties with values matching `required` singleton will be marked as
- * 'required' properties.
- * @param {Object} object
- *    Set of properties to generate trait from.
- * @returns {Object}
- *    Properties descriptor of all of the `object`'s own properties.
- */
-function trait(properties) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(properties);
-  for (let key of keys) {
-    let descriptor = getOwnPropertyDescriptor(properties, key);
-    result[key] = (required === descriptor.value) ? Required(key) : descriptor;
-  }
-  return result;
-}
-exports.Trait = exports.trait = trait;
-
-/**
- * Composes new trait. If two or more traits have own properties with the
- * same name, the new trait will contain a 'conflict' property for that name.
- * 'compose' is a commutative and associative operation, and the order of its
- * arguments is not significant.
- *
- * @params {Object} trait
- *    Takes traits as an arguments
- * @returns {Object}
- *    New trait containing the combined own properties of all the traits.
- * @example
- *    var newTrait = compose(trait_1, trait_2, ..., trait_N);
- */
-function compose(trait1, trait2) {
-  let traits = Array.slice(arguments, 0),
-      result = {};
-  for (let trait of traits) {
-    let keys = getOwnPropertyIdentifiers(trait);
-    for (let key of keys) {
-      let descriptor = trait[key];
-      // if property already exists and it's not a requirement
-      if (hasOwn.call(result, key) && !result[key].required) {
-        if (descriptor.required)
-          continue;
-        if (!areSame(descriptor, result[key]))
-          result[key] = Conflict(key);
-      } else {
-        result[key] = descriptor;
-      }
-    }
-  }
-  return result;
-}
-exports.compose = compose;
-
-/**
- * Composes new trait with the same own properties as the original trait,
- * except that all property names appearing in the first argument are replaced
- * by 'required' property descriptors.
- * @param {String[]} keys
- *    Array of strings property names.
- * @param {Object} trait
- *    A trait some properties of which should be excluded.
- * @returns {Object}
- * @example
- *    var newTrait = exclude(['name', ...], trait)
- */
-function exclude(keys, trait) {
-  let exclusions = Map(keys),
-      result = {};
-
-  keys = getOwnPropertyIdentifiers(trait);
-
-  for (let key of keys) {
-    if (!hasOwn.call(exclusions, key) || trait[key].required)
-      result[key] = trait[key];
-    else
-      result[key] = Required(key);
-  }
-  return result;
-}
-
-/**
- * Composes a new trait with all of the combined properties of the argument
- * traits. In contrast to `compose`, `override` immediately resolves all
- * conflicts resulting from this composition by overriding the properties of
- * later traits. Trait priority is from left to right. I.e. the properties of
- * the leftmost trait are never overridden.
- * @params {Object} trait
- * @returns {Object}
- * @examples
- *    // override is associative:
- *    override(t1,t2,t3)
- *    // is equivalent to
- *    override(t1, override(t2, t3))
- *    // or
- *    to override(override(t1, t2), t3)
- *
- *    // override is not commutative:
- *    override(t1,t2)
- *    // is not equivalent to
- *    override(t2,t1)
- */
-function override() {
-  let traits = Array.slice(arguments, 0),
-      result = {};
-  for (let trait of traits) {
-    let keys = getOwnPropertyIdentifiers(trait);
-    for (let key of keys) {
-      let descriptor = trait[key];
-      if (!hasOwn.call(result, key) || result[key].required)
-        result[key] = descriptor;
-    }
-  }
-  return result;
-}
-exports.override = override;
-
-/**
- * Composes a new trait with the same properties as the original trait, except
- * that all properties whose name is an own property of map will be renamed to
- * map[name], and a 'required' property for name will be added instead.
- * @param {Object} map
- *    An object whose own properties serve as a mapping from old names to new
- *    names.
- * @param {Object} trait
- *    A trait object
- * @returns {Object}
- * @example
- *    var newTrait = rename(map, trait);
- */
-function rename(map, trait) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    // must be renamed & it's not requirement
-    if (hasOwn.call(map, key) && !trait[key].required) {
-      let alias = map[key];
-      if (hasOwn.call(result, alias) && !result[alias].required)
-        result[alias] = Conflict(alias);
-      else
-        result[alias] = trait[key];
-      if (!hasOwn.call(result, key))
-        result[key] = Required(key);
-    } else { // must not be renamed or its a requirement
-      // property is not in result trait yet
-      if (!hasOwn.call(result, key))
-        result[key] = trait[key];
-      // property is already in resulted trait & it's not requirement
-      else if (!trait[key].required)
-        result[key] = Conflict(key);
-    }
-  }
-  return result;
-}
-
-/**
-* Composes new resolved trait, with all the same properties as the original
-* trait, except that all properties whose name is an own property of
-* resolutions will be renamed to `resolutions[name]`. If it is
-* `resolutions[name]` is `null` value is changed into a required property
-* descriptor.
-* function can be implemented as `rename(map,exclude(exclusions, trait))`
-* where map is the subset of mappings from oldName to newName and exclusions
-* is an array of all the keys that map to `null`.
-* Note: it's important to **first** `exclude`, **then** `rename`, since
-* `exclude` and rename are not associative.
-* @param {Object} resolutions
-*   An object whose own properties serve as a mapping from old names to new
-*   names, or to `null` if the property should be excluded.
-* @param {Object} trait
-*   A trait object
-* @returns {Object}
-*   Resolved trait with the same own properties as the original trait.
-*/
-function resolve(resolutions, trait) {
-  let renames = {},
-      exclusions = [],
-      keys = getOwnPropertyIdentifiers(resolutions);
-  for (let key of keys) {  // pre-process renamed and excluded properties
-    if (resolutions[key])       // old name -> new name
-      renames[key] = resolutions[key];
-    else                        // name -> undefined
-      exclusions.push(key);
-  }
-  return rename(renames, exclude(exclusions, trait));
-}
-exports.resolve = resolve;
-
-/**
- * `create` is like `Object.create`, except that it ensures that:
- *    - an exception is thrown if 'trait' still contains required properties
- *    - an exception is thrown if 'trait' still contains conflicting
- *      properties
- * @param {Object}
- *    prototype of the completed object
- * @param {Object} trait
- *    trait object to be turned into a complete object
- * @returns {Object}
- *    An object with all of the properties described by the trait.
- */
-function create(proto, trait) {
-  let properties = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    let descriptor = trait[key];
-    if (descriptor.required && !hasOwn.call(proto, key))
-      throw new Error(ERR_REQUIRED + key);
-    else if (descriptor.conflict)
-      throw new Error(ERR_CONFLICT + key);
-    else
-      properties[key] = descriptor;
-  }
-  return _create(proto, properties);
-}
-exports.create = create;
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test.js
@@ -9,17 +9,17 @@ module.metadata = {
 
 const memory = require("./memory");
 const timer = require("../timers");
 const cfxArgs = require("../test/options");
 const { getTabs, closeTab, getURI, getTabId, getSelectedTab } = require("../tabs/utils");
 const { windows, isBrowser, getMostRecentBrowserWindow } = require("../window/utils");
 const { defer, all, Debugging: PromiseDebugging, resolve } = require("../core/promise");
 const { getInnerId } = require("../window/utils");
-const { cleanUI } = require("../test/utils")
+const { cleanUI } = require("../test/utils");
 
 const findAndRunTests = function findAndRunTests(options) {
   var TestFinder = require("./unit-test-finder").TestFinder;
   var finder = new TestFinder({
     filter: options.filter,
     testInProcess: options.testInProcess,
     testOutOfProcess: options.testOutOfProcess
   });
--- a/addon-sdk/source/lib/sdk/deprecated/window-utils.js
+++ b/addon-sdk/source/lib/sdk/deprecated/window-utils.js
@@ -3,23 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   'stability': 'deprecated'
 };
 
 const { Cc, Ci } = require('chrome');
-const { EventEmitter } = require('../deprecated/events');
-const { Trait } = require('../deprecated/traits');
-const { when } = require('../system/unload');
 const events = require('../system/events');
 const { getInnerId, getOuterId, windows, isDocumentLoaded, isBrowser,
         getMostRecentBrowserWindow, getMostRecentWindow } = require('../window/utils');
-const errors = require('../deprecated/errors');
 const { deprecateFunction } = require('../util/deprecate');
 const { ignoreWindow } = require('sdk/private-browsing/utils');
 const { isPrivateBrowsingSupported } = require('../self');
 
 const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
                        getService(Ci.nsIWindowWatcher);
 const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
                         getService(Ci.nsIAppShellService);
@@ -119,73 +115,53 @@ WindowTracker.prototype = {
 
   unload: function unload() {
     windowWatcher.unregisterNotification(this);
     events.off('toplevel-window-ready', this._onToplevelWindowReady);
     for (let window of getWindows())
       this._unregWindow(window);
   },
 
-  handleEvent: errors.catchAndLog(function handleEvent(event) {
-    if (event.type == 'load' && event.target) {
-      var window = event.target.defaultView;
-      if (window)
-        this._regWindow(window);
+  handleEvent: function handleEvent(event) {
+    try {
+      if (event.type == 'load' && event.target) {
+        var window = event.target.defaultView;
+        if (window)
+          this._regWindow(window);
+      }
     }
-  }),
+    catch(e) {
+      console.exception(e);
+    }
+  },
 
   _onToplevelWindowReady: function _onToplevelWindowReady({subject}) {
     let window = subject;
     // ignore private windows if they are not supported
     if (ignoreWindow(window))
       return;
     this._regWindow(window);
   },
 
-  observe: errors.catchAndLog(function observe(subject, topic, data) {
-    var window = subject.QueryInterface(Ci.nsIDOMWindow);
-    // ignore private windows if they are not supported
-    if (ignoreWindow(window))
-      return;
-    if (topic == 'domwindowclosed')
+  observe: function observe(subject, topic, data) {
+    try {
+      var window = subject.QueryInterface(Ci.nsIDOMWindow);
+      // ignore private windows if they are not supported
+      if (ignoreWindow(window))
+        return;
+      if (topic == 'domwindowclosed')
       this._unregWindow(window);
-  })
+    }
+    catch(e) {
+      console.exception(e);
+    }
+  }
 };
 exports.WindowTracker = WindowTracker;
 
-const WindowTrackerTrait = Trait.compose({
-  _onTrack: Trait.required,
-  _onUntrack: Trait.required,
-  constructor: function WindowTrackerTrait() {
-    WindowTracker({
-      onTrack: this._onTrack.bind(this),
-      onUntrack: this._onUntrack.bind(this)
-    });
-  }
-});
-exports.WindowTrackerTrait = WindowTrackerTrait;
-
-var gDocsToClose = [];
-
-function onDocUnload(event) {
-  var index = gDocsToClose.indexOf(event.target);
-  if (index == -1)
-    throw new Error('internal error: unloading document not found');
-  var document = gDocsToClose.splice(index, 1)[0];
-  // Just in case, let's remove the event listener too.
-  document.defaultView.removeEventListener('unload', onDocUnload, false);
-}
-
-onDocUnload = require('./errors').catchAndLog(onDocUnload);
-
-exports.closeOnUnload = function closeOnUnload(window) {
-  window.addEventListener('unload', onDocUnload, false);
-  gDocsToClose.push(window.document);
-};
-
 Object.defineProperties(exports, {
   activeWindow: {
     enumerable: true,
     get: function() {
       return getMostRecentWindow(null);
     },
     set: function(window) {
       try {
@@ -214,14 +190,8 @@ exports.getOuterId = deprecateFunction(g
 );
 
 exports.isBrowser = deprecateFunction(isBrowser,
   'require("window-utils").isBrowser is deprecated, ' +
   'please use require("sdk/window/utils").isBrowser instead'
 );
 
 exports.hiddenWindow = appShellService.hiddenDOMWindow;
-
-when(
-  function() {
-    gDocsToClose.slice().forEach(
-      function(doc) { doc.defaultView.close(); });
-  });
--- a/addon-sdk/source/lib/sdk/event/core.js
+++ b/addon-sdk/source/lib/sdk/event/core.js
@@ -81,45 +81,53 @@ exports.once = once;
  * @param {Object} target
  *    Event target object.
  * @param {String} type
  *    The type of event.
  * @params {Object|Number|String|Boolean} args
  *    Arguments that will be passed to listeners.
  */
 function emit (target, type, ...args) {
+  emitOnObject(target, type, target, ...args);
+}
+exports.emit = emit;
+
+/**
+ * A variant of emit that allows setting the this property for event listeners
+ */
+function emitOnObject(target, type, thisArg, ...args) {
   let all = observers(target, '*').length;
   let state = observers(target, type);
   let listeners = state.slice();
   let count = listeners.length;
   let index = 0;
 
   // If error event and there are no handlers (explicit or catch-all)
   // then print error message to the console.
   if (count === 0 && type === 'error' && all === 0)
     console.exception(args[0]);
   while (index < count) {
     try {
       let listener = listeners[index];
       // Dispatch only if listener is still registered.
       if (~state.indexOf(listener))
-        listener.apply(target, args);
+        listener.apply(thisArg, args);
     }
     catch (error) {
       // If exception is not thrown by a error listener and error listener is
       // registered emit `error` event. Otherwise dump exception to the console.
       if (type !== 'error') emit(target, 'error', error);
       else console.exception(error);
     }
     index++;
   }
    // Also emit on `"*"` so that one could listen for all events.
   if (type !== '*') emit(target, '*', type, ...args);
 }
-exports.emit = emit;
+exports.emitOnObject = emitOnObject;
 
 /**
  * Removes an event `listener` for the given event `type` on the given event
  * `target`. If no `listener` is passed removes all listeners of the given
  * `type`. If `type` is not passed removes all the listeners of the given
  * event `target`.
  * @param {Object} target
  *    The event target object.
--- a/addon-sdk/source/lib/sdk/frame/hidden-frame.js
+++ b/addon-sdk/source/lib/sdk/frame/hidden-frame.js
@@ -4,17 +4,16 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Cc, Ci } = require("chrome");
-const errors = require("../deprecated/errors");
 const { Class } = require("../core/heritage");
 const { List, addListItem, removeListItem } = require("../util/list");
 const { EventTarget } = require("../event/target");
 const { emit } = require("../event/core");
 const { create: makeFrame } = require("./utils");
 const { defer } = require("../core/promise");
 const { when: unload } = require("../system/unload");
 const { validateOptions, getTypeOf } = require("../deprecated/api-utils");
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/window.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { windows, isInteractive, isDocumentLoaded,
-        getOuterId, isTopLevel } = require("../window/utils");
-const { InputPort } = require("./system");
-const { lift, merges, foldp, keepIf, start, Input } = require("../event/utils");
-const { patch } = require("diffpatcher/index");
-const { on } = require("../event/core");
-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(null, {includePrivates: 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 opened top level window.
-const LastOpened = lift(Update, new InputPort({topic: "domwindowopened"}));
-exports.LastOpened = LastOpened;
-
-// Signal represents delta for last top level window close.
-const LastClosed = lift(Delete, 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(isTopLevel, 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(isTopLevel, 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 currently opened top level windows, updated
-// to new set any time window is opened or closed.
-const Opened = foldp(patch, opened, merges([LastOpened, LastClosed]));
-Opened[start] = initialize;
-exports.Opened = Opened;
-
-// 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;
--- a/addon-sdk/source/lib/sdk/io/file.js
+++ b/addon-sdk/source/lib/sdk/io/file.js
@@ -1,16 +1,16 @@
 /* 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"
+  "stability": "deprecated"
 };
 
 const {Cc,Ci,Cr} = require("chrome");
 const byteStreams = require("./byte-streams");
 const textStreams = require("./text-streams");
 
 // Flags passed when opening a file.  See nsprpub/pr/include/prio.h.
 const OPEN_FLAGS = {
--- a/addon-sdk/source/lib/sdk/io/fs.js
+++ b/addon-sdk/source/lib/sdk/io/fs.js
@@ -879,16 +879,17 @@ function writeFile(path, content, encodi
   }
 };
 exports.writeFile = writeFile;
 
 /**
  * The synchronous version of `fs.writeFile`.
  */
 function writeFileSync(filename, data, encoding) {
+  // TODO: Implement this in bug 1148209 https://bugzilla.mozilla.org/show_bug.cgi?id=1148209
   throw Error("Not implemented");
 };
 exports.writeFileSync = writeFileSync;
 
 
 function utimesSync(path, atime, mtime) {
   throw Error("Not implemented");
 }
--- a/addon-sdk/source/lib/sdk/io/stream.js
+++ b/addon-sdk/source/lib/sdk/io/stream.js
@@ -27,17 +27,17 @@ const ArrayBufferInputStream = CC("@mozi
 const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
                              "nsIBinaryInputStream", "setInputStream");
 const InputStreamPump = CC("@mozilla.org/network/input-stream-pump;1",
                            "nsIInputStreamPump", "init");
 
 const threadManager = Cc["@mozilla.org/thread-manager;1"].
                       getService(Ci.nsIThreadManager);
 
-const eventTarget = Cc["@mozilla.org/network/socket-transport-service;1"].
+const eventTarget = Cc["@mozilla.org/network/stream-transport-service;1"].
                     getService(Ci.nsIEventTarget);
 
 let isFunction = value => typeof(value) === "function"
 
 function accessor() {
   let map = new WeakMap();
   return function(target, value) {
     if (value)
--- a/addon-sdk/source/lib/sdk/lang/type.js
+++ b/addon-sdk/source/lib/sdk/lang/type.js
@@ -120,29 +120,27 @@ function isGenerator(aValue) {
 exports.isGenerator = isGenerator;
 
 /**
  * Returns true if `value` is an Array.
  * @examples
  *    isArray([1, 2, 3])  // true
  *    isArray({ 0: 'foo', length: 1 }) // false
  */
-var isArray = Array.isArray || function isArray(value) {
-  Object.prototype.toString.call(value) === "[object Array]";
-}
+var isArray = Array.isArray;
 exports.isArray = isArray;
 
 /**
  * Returns `true` if `value` is an Arguments object.
  * @examples
  *    (function(){ return isArguments(arguments); })(1, 2, 3); // true
  *    isArguments([1,2,3]); // false
  */
 function isArguments(value) {
-  Object.prototype.toString.call(value) === "[object Arguments]";
+  return Object.prototype.toString.call(value) === "[object Arguments]";
 }
 exports.isArguments = isArguments;
 
 let isMap = value => Object.prototype.toString.call(value) === "[object Map]"
 exports.isMap = isMap;
 
 let isSet = value => Object.prototype.toString.call(value) === "[object Set]"
 exports.isSet = isSet;
--- a/addon-sdk/source/lib/sdk/model/core.js
+++ b/addon-sdk/source/lib/sdk/model/core.js
@@ -1,13 +1,11 @@
 /* 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/.
- */
-
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { dispatcher } = require("../util/dispatcher");
 
--- a/addon-sdk/source/lib/sdk/notifications.js
+++ b/addon-sdk/source/lib/sdk/notifications.js
@@ -5,17 +5,16 @@
 "use strict";
 
 module.metadata = {
   "stability": "stable"
 };
 
 const { Cc, Ci, Cr } = require("chrome");
 const apiUtils = require("./deprecated/api-utils");
-const errors = require("./deprecated/errors");
 const { isString, isUndefined, instanceOf } = require('./lang/type');
 const { URL, isLocalURL } = require('./url');
 const { data } = require('./self');
 
 const NOTIFICATION_DIRECTIONS  = ["auto", "ltr", "rtl"];
 
 try {
   let alertServ = Cc["@mozilla.org/alerts-service;1"].
@@ -29,19 +28,25 @@ catch (err) {
   // service, e.g., if Growl is not installed on OS X.  In that case, use a
   // mock notification function that just logs to the console.
   notify = notifyUsingConsole;
 }
 
 exports.notify = function notifications_notify(options) {
   let valOpts = validateOptions(options);
   let clickObserver = !valOpts.onClick ? null : {
-    observe: function notificationClickObserved(subject, topic, data) {
-      if (topic === "alertclickcallback")
-        errors.catchAndLog(valOpts.onClick).call(exports, valOpts.data);
+    observe: (subject, topic, data) => {
+      if (topic === "alertclickcallback") {
+        try {
+          valOpts.onClick.call(exports, valOpts.data);
+        }
+        catch(e) {
+          console.exception(e);
+        }
+      }
     }
   };
   function notifyWithOpts(notifyFn) {
     let { iconURL } = valOpts;
     iconURL = iconURL && isLocalURL(iconURL) ? data.url(iconURL) : iconURL;
 
     notifyFn(iconURL, valOpts.title, valOpts.text, !!clickObserver,
              valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
--- a/addon-sdk/source/lib/sdk/page-mod.js
+++ b/addon-sdk/source/lib/sdk/page-mod.js
@@ -120,19 +120,22 @@ const PageMod = Class({
 
     function serializeRules(rules) {
       for (let rule of rules) {
         yield isRegExp(rule) ? { type: "regexp", pattern: rule.source, flags: rule.flags }
                              : { type: "string", value: rule };
       }
     }
 
-    model.childOptions = omit(model, ["include", "exclude"]);
+    model.childOptions = omit(model, ["include", "exclude", "contentScriptOptions"]);
     model.childOptions.include = [...serializeRules(model.include)];
     model.childOptions.exclude = [...serializeRules(model.exclude)];
+    model.childOptions.contentScriptOptions = model.contentScriptOptions ?
+                                              JSON.stringify(model.contentScriptOptions) :
+                                              null;
 
     processes.port.emit('sdk/page-mod/create', model.childOptions);
   },
 
   dispose: function(reason) {
     processes.port.emit('sdk/page-mod/destroy', modelFor(this).id);
     pagemods.delete(modelFor(this).id);
     workers.delete(this);
--- a/addon-sdk/source/lib/sdk/page-worker.js
+++ b/addon-sdk/source/lib/sdk/page-worker.js
@@ -22,16 +22,17 @@ const { window } = require('./addon/wind
 const { getParentWindow } = require('./window/utils');
 const { create: makeFrame, getDocShell } = require('./frame/utils');
 const { contract } = require('./util/contract');
 const { contract: loaderContract } = require('./content/loader');
 const { has } = require('./util/array');
 const { Rules } = require('./util/rules');
 const { merge } = require('./util/object');
 const { data } = require('./self');
+const { getActiveView } = require("./view/core");
 
 const views = new WeakMap();
 const workers = new WeakMap();
 const pages = new WeakMap();
 
 const readyEventNames = [
   'DOMContentLoaded',
   'document-element-inserted',
@@ -176,8 +177,10 @@ function pageFromDoc(doc) {
   if (!parentWindow) return;
 
   let frames = parentWindow.document.getElementsByTagName('iframe');
   for (let i = frames.length; i--;)
     if (frames[i].contentDocument === doc && (page = pageFor(frames[i])))
       return page;
   return null;
 }
+
+getActiveView.define(Page, viewFor);
--- a/addon-sdk/source/lib/sdk/places/contract.js
+++ b/addon-sdk/source/lib/sdk/places/contract.js
@@ -1,33 +1,31 @@
 /* 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 { EventEmitter } = require('../deprecated/events');
 const { isValidURI, URL } = require('../url');
 const { contract } = require('../util/contract');
 const { extend } = require('../util/object');
 
 // map of property validations
 const validItem = {
   id: {
     is: ['number', 'undefined', 'null'],
   },
   group: {
     is: ['object', 'number', 'undefined', 'null'],
     ok: function (value) {
-      return value && 
+      return value &&
         (value.toString && value.toString() === '[object Group]') ||
         typeof value === 'number' ||
         value.type === 'group';
     },
     msg: 'The `group` property must be a valid Group object'
   },
   index: {
     is: ['undefined', 'null', 'number'],
@@ -43,17 +41,17 @@ const validTitle = {
   title: {
     is: ['string'],
     msg: 'The `title` property must be defined.'
   }
 };
 
 const validURL = {
   url: {
-    is: ['string'], 
+    is: ['string'],
     ok: isValidURI,
     msg: 'The `url` property must be a valid URL.'
   }
 };
 
 const validTags = {
   tags: {
     is: ['object'],
--- a/addon-sdk/source/lib/sdk/remote/parent.js
+++ b/addon-sdk/source/lib/sdk/remote/parent.js
@@ -41,17 +41,17 @@ else {
 let pathMapping = Object.keys(options.paths)
                         .sort((a, b) => b.length - a.length)
                         .map(p => [p, options.paths[p]]);
 
 // Load the scripts in the child processes
 let { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm');
 let PATH = options.paths[''];
 
-const childOptions = omit(options, ['modules', 'globals']);
+const childOptions = omit(options, ['modules', 'globals', 'resolve', 'load']);
 childOptions.modules = {};
 // @l10n/data is just JSON data and can be safely sent across to the child loader
 try {
   childOptions.modules["@l10n/data"] = require("@l10n/data");
 }
 catch (e) {
   // There may be no l10n data
 }
--- a/addon-sdk/source/lib/sdk/request.js
+++ b/addon-sdk/source/lib/sdk/request.js
@@ -159,16 +159,18 @@ const Request = Class({
   }
 });
 exports.Request = Request;
 
 const Response = Class({
   initialize: function initialize(request) {
     response(this).request = request;
   },
+  // more about responseURL: https://bugzilla.mozilla.org/show_bug.cgi?id=998076
+  get url() response(this).request.responseURL,
   get text() response(this).request.responseText,
   get xml() {
     throw new Error("Sorry, the 'xml' property is no longer available. " +
                     "see bug 611042 for more information.");
   },
   get status() response(this).request.status,
   get statusText() response(this).request.statusText,
   get json() {
--- a/addon-sdk/source/lib/sdk/system.js
+++ b/addon-sdk/source/lib/sdk/system.js
@@ -4,17 +4,16 @@
 'use strict';
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, CC } = require('chrome');
 const options = require('@loader/options');
-const file = require('./io/file');
 const runtime = require("./system/runtime");
 const { when: unload } = require("./system/unload");
 
 const appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
                    getService(Ci.nsIAppStartup);
 const appInfo = Cc["@mozilla.org/xre/app-info;1"].
                 getService(Ci.nsIXULAppInfo);
 const directoryService = Cc['@mozilla.org/file/directory_service;1'].
--- a/addon-sdk/source/lib/sdk/tabs.js
+++ b/addon-sdk/source/lib/sdk/tabs.js
@@ -2,32 +2,16 @@
  * 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 { modelFor } = require("./model/core");
-const { viewFor } = require("./view/core");
-const { isTab } = require("./tabs/utils");
-
-
 if (require("./system/xul-app").is("Fennec")) {
   module.exports = require("./windows/tabs-fennec").tabs;
 }
 else {
   module.exports = require("./tabs/tabs-firefox");
 }
 
 const tabs = module.exports;
-
-// Implement `modelFor` function for the Tab instances.
-// Finds a right model by iterating over all tab models
-// and finding one that wraps given `view`.
-modelFor.when(isTab, view => {
-  for (let model of tabs) {
-    if (viewFor(model) === view)
-      return model;
-  }
-  return null;
-});
--- a/addon-sdk/source/lib/sdk/tabs/helpers.js
+++ b/addon-sdk/source/lib/sdk/tabs/helpers.js
@@ -7,35 +7,26 @@ module.metadata = {
   'stability': 'unstable'
 };
 
 
 // NOTE: This file should only export Tab instances
 
 
 const { getTabForContentWindow, getTabForBrowser: getRawTabForBrowser } = require('./utils');
-const { Tab } = require('./tab');
-const { rawTabNS } = require('./namespace');
+const { modelFor } = require('../model/core');
 
 function getTabForWindow(win) {
   let tab = getTabForContentWindow(win);
   // We were unable to find the related tab!
   if (!tab)
     return null;
 
-  return getTabForRawTab(tab) || Tab({ tab: tab });
+  return modelFor(tab);
 }
 exports.getTabForWindow = getTabForWindow;
 
-// only works on fennec atm
-function getTabForRawTab(rawTab) {
-  let tab = rawTabNS(rawTab).tab;
-  if (tab) {
-    return tab;
-  }
-  return null;
-}
-exports.getTabForRawTab = getTabForRawTab;
+exports.getTabForRawTab = modelFor;
 
 function getTabForBrowser(browser) {
-  return getTabForRawTab(getRawTabForBrowser(browser));
+  return modelFor(getRawTabForBrowser(browser));
 }
 exports.getTabForBrowser = getTabForBrowser;
--- a/addon-sdk/source/lib/sdk/tabs/observer.js
+++ b/addon-sdk/source/lib/sdk/tabs/observer.js
@@ -10,16 +10,17 @@ module.metadata = {
 const { EventTarget } = require("../event/target");
 const { emit } = require("../event/core");
 const { DOMEventAssembler } = require("../deprecated/events/assembler");
 const { Class } = require("../core/heritage");
 const { getActiveTab, getTabs } = require("./utils");
 const { browserWindowIterator } = require("../deprecated/window-utils");
 const { isBrowser, windows, getMostRecentBrowserWindow } = require("../window/utils");
 const { observer: windowObserver } = require("../windows/observer");
+const { when } = require("../system/unload");
 
 const EVENTS = {
   "TabOpen": "open",
   "TabClose": "close",
   "TabSelect": "select",
   "TabMove": "move",
   "TabPinned": "pinned",
   "TabUnpinned": "unpinned"
@@ -82,16 +83,21 @@ const Observer = Class({
       }
     });
 
     // We should synchronize state, since probably we already have at least one
     // window open.
     for (let chromeWindow of browserWindowIterator()) {
       this.observe(chromeWindow);
     }
+
+    when(_ => {
+      // Don't dispatch a deactivate event during unload.
+      this[selectedTab] = null;
+    });
   },
   /**
    * Events that are supported and emitted by the module.
    */
   supportedEventsTypes: Object.keys(EVENTS),
   /**
    * Function handles all the supported events on all the windows that are
    * observed. Method is used to proxy events to the listeners registered on
--- a/addon-sdk/source/lib/sdk/tabs/tab-fennec.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab-fennec.js
@@ -248,8 +248,13 @@ function onTabClose(event) {
 
   emit(this, EVENTS.close.name, this);
   cleanupTab(this);
 };
 
 isPrivate.implement(Tab, tab => {
   return isWindowPrivate(getTabContentWindow(tabNS(tab).tab));
 });
+
+// Implement `modelFor` function for the Tab instances.
+modelFor.when(isTab, rawTab => {
+  return rawTabNS(rawTab).tab;
+});
--- a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
@@ -1,303 +1,324 @@
- /*This Source Code Form is subject to the terms of the Mozilla Public
+/* 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 { Trait } = require("../deprecated/traits");
-const { EventEmitter } = require("../deprecated/events");
-const { defer } = require("../lang/functional");
-const { has } = require("../util/array");
-const { each } = require("../util/object");
-const { EVENTS } = require("./events");
-const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
+const { Class } = require('../core/heritage');
+const { observer } = require('./observer');
+const { observer: windowObserver } = require('../windows/observer');
+const { addListItem, removeListItem } = require('../util/list');
+const { viewFor } = require('../view/core');
+const { modelFor } = require('../model/core');
+const { emit, setListeners } = require('../event/core');
+const { EventTarget } = require('../event/target');
+const { getBrowserForTab, setTabURL, getTabId, getTabURL, getTabForBrowser,
+        getTabs, getTabTitle, setTabTitle, getIndex, closeTab, reload, move,
+        activateTab, pin, unpin, isTab } = require('./utils');
+const { isBrowser, getInnerId, isWindowPrivate } = require('../window/utils');
 const { getFaviconURIForLocation } = require("../io/data");
-const { activateTab, getOwnerWindow, getBrowserForTab, getTabTitle,
-        setTabTitle, getTabContentDocument, getTabURL, setTabURL,
-        getTabContentType, getTabId } = require('./utils');
-const { isPrivate } = require('../private-browsing/utils');
-const { isWindowPrivate } = require('../window/utils');
-const viewNS = require('../core/namespace').ns();
 const { deprecateUsage } = require('../util/deprecate');
+const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
+const { when } = require('../system/unload');
+const { ignoreWindow, isPrivate } = require('../private-browsing/utils')
+const { defer } = require('../lang/functional');
 const { getURL } = require('../url/utils');
-const { viewFor } = require('../view/core');
-const { observer } = require('./observer');
-const { remoteRequire, frames } = require('../remote/parent');
+const { frames, remoteRequire } = require('../remote/parent');
 remoteRequire('sdk/content/tab-events');
 
-// Array of the inner instances of all the wrapped tabs.
-const TABS = [];
+const modelsFor = new WeakMap();
+const viewsFor = new WeakMap();
+const destroyed = new WeakMap();
+
+const tabEvents = {};
+exports.tabEvents = tabEvents;
+
+function browser(tab) {
+  return getBrowserForTab(viewsFor.get(tab));
+}
+
+function isDestroyed(tab) {
+  return destroyed.has(tab);
+}
+
+function isClosed(tab) {
+  if (!viewsFor.has(tab))
+    return true;
+  return viewsFor.get(tab).closing;
+}
 
-/**
- * Trait used to create tab wrappers.
- */
-const TabTrait = Trait.compose(EventEmitter, {
-  on: Trait.required,
-  _emit: Trait.required,
-  /**
-   * Tab DOM element that is being wrapped.
-   */
-  _tab: null,
-  /**
-   * Window wrapper whose tab this object represents.
-   */
-  window: null,
-  constructor: function Tab(options) {
-    this._tab = options.tab;
-    // TODO: Remove this dependency
-    let window = this.window = options.window || require('../windows').BrowserWindow({ window: getOwnerWindow(this._tab) });
+const Tab = Class({
+  implements: [EventTarget],
+  initialize: function(tabElement, options = null) {
+    modelsFor.set(tabElement, this);
+    viewsFor.set(this, tabElement);
+
+    if (options) {
+      EventTarget.prototype.initialize.call(this, options);
 
-    // Setting event listener if was passed.
-    each(EVENTS, (type) => {
-      let listener = options[type.listener];
-      if (listener) {
-        this.on(type.name, options[type.listener]);
-      }
-      // window spreads this event.
-      if (!has(['ready', 'load', 'pageshow'], (type.name)))
-        window.tabs.on(type.name, this._onEvent.bind(this, type.name));
+      if (options.isPinned)
+        this.pin();
+
+      // Note that activate is defered and so will run after any open event
+      // is sent out
+      if (!options.inBackground)
+        this.activate();
+    }
+
+    getURL.implement(this, tab => tab.url);
+    isPrivate.implement(this, tab => {
+      return isWindowPrivate(viewsFor.get(tab).ownerDocument.defaultView);
     });
-
-    this.on(EVENTS.close.name, this.destroy.bind(this));
-
-    this._onContentEvent = this._onContentEvent.bind(this);
-    frames.port.on('sdk/tab/event', this._onContentEvent);
-
-    // bug 1024632 - first tab inNewWindow gets events from the synthetic 
-    // about:blank document. ignore them unless that is the actual target url.
-    this._skipBlankEvents = options.inNewWindow && options.url !== 'about:blank';
-
-    if (options.isPinned)
-      this.pin();
-
-    viewNS(this._public).tab = this._tab;
-    viewFor.implement(this._public, getTabView);
-    isPrivate.implement(this._public, tab => isWindowPrivate(getChromeTab(tab)));
-
-    // Add tabs to getURL method
-    getURL.implement(this._public, (function (obj) this._public.url).bind(this));
-
-    // Since we will have to identify tabs by a DOM elements facade function
-    // is used as constructor that collects all the instances and makes sure
-    // that they more then one wrapper is not created per tab.
-    return this;
-  },
-  destroy: function destroy() {
-    this._removeAllListeners();
-    if (this._tab) {
-      frames.port.off('sdk/tab/event', this._onContentEvent);
-      this._tab = null;
-      TABS.splice(TABS.indexOf(this), 1);
-    }
   },
 
-  /**
-   * internal message listener emits public events (ready, load and pageshow)
-   * forwarded from content frame script tab-event.js
-   */
-  _onContentEvent: function(frame, event, persisted) {
-    if (frame.frameElement !== this._browser)
+  get id() {
+    return isDestroyed(this) ? undefined : getTabId(viewsFor.get(this));
+  },
+
+  get title() {
+    return isDestroyed(this) ? undefined : getTabTitle(viewsFor.get(this));
+  },
+
+  set title(val) {
+    if (isDestroyed(this))
       return;
 
-    // bug 1024632 - skip initial events from synthetic about:blank document
-    if (this._skipBlankEvents && this.window.tabs.length === 1 && this.url === 'about:blank')
-      return;
+    setTabTitle(viewsFor.get(this), val);
+  },
 
-    // first time we don't skip blank events, disable further skipping
-    this._skipBlankEvents = false;
-
-    this._emit(event, this._public, persisted);
+  get url() {
+    return isDestroyed(this) ? undefined : getTabURL(viewsFor.get(this));
   },
 
-  /**
-   * Internal tab event router. Window will emit tab related events for all it's
-   * tabs, this listener will propagate all the events for this tab to it's
-   * listeners.
-   */
-  _onEvent: function _onEvent(type, tab) {
-    if (viewNS(tab).tab == this._tab)
-      this._emit(type, tab);
-  },
-  /**
-   * Browser DOM element where page of this tab is currently loaded.
-   */
-  get _browser() getBrowserForTab(this._tab),
-  /**
-   * Window DOM element containing this tab.
-   */
-  get _window() getOwnerWindow(this._tab),
-  /**
-   * Document object of the page that is currently loaded in this tab.
-   */
-  get _contentDocument() getTabContentDocument(this._tab),
-  /**
-   * Window object of the page that is currently loaded in this tab.
-   */
-  get _contentWindow() this._browser.contentWindow,
+  set url(val) {
+    if (isDestroyed(this))
+      return;
 
-  /**
-   * tab's document readyState, or 'uninitialized' if it doesn't even exist yet.
-   */
-  get readyState() {
-    let doc = this._contentDocument;
-    return doc && doc.readyState || 'uninitialized';
+    setTabURL(viewsFor.get(this), val);
   },
 
-  /**
-   * Unique id for the tab, actually maps to tab.linkedPanel but with some munging.
-   */
-  get id() this._tab ? getTabId(this._tab) : undefined,
-
-  /**
-   * The title of the page currently loaded in the tab.
-   * Changing this property changes an actual title.
-   * @type {String}
-   */
-  get title() this._tab ? getTabTitle(this._tab) : undefined,
-  set title(title) this._tab && setTabTitle(this._tab, title),
-
-  /**
-   * Returns the MIME type that the document loaded in the tab is being
-   * rendered as.
-   * @type {String}
-   */
-  get contentType() this._tab ? getTabContentType(this._tab) : undefined,
-
-  /**
-   * Location of the page currently loaded in this tab.
-   * Changing this property will loads page under under the specified location.
-   * @type {String}
-   */
-  get url() this._tab ? getTabURL(this._tab) : undefined,
-  set url(url) this._tab && setTabURL(this._tab, url),
-  /**
-   * URI of the favicon for the page currently loaded in this tab.
-   * @type {String}
-   */
   get favicon() {
     deprecateUsage(
       'tab.favicon is deprecated, ' +
       'please use require("sdk/places/favicon").getFavicon instead.'
     );
-    return this._tab ? getFaviconURIForLocation(this.url) : undefined
+    return isDestroyed(this) ? undefined : getFaviconURIForLocation(this.url);
+  },
+
+  get contentType() {
+    return isDestroyed(this) ? undefined : browser(this).documentContentType;
+  },
+
+  get index() {
+    return isDestroyed(this) ? undefined : getIndex(viewsFor.get(this));
   },
-  /**
-   * The CSS style for the tab
-   */
-  get style() null, // TODO
-  /**
-   * The index of the tab relative to other tabs in the application window.
-   * Changing this property will change order of the actual position of the tab.
-   * @type {Number}
-   */
-  get index()
-    this._tab ?
-    this._window.gBrowser.getBrowserIndexForDocument(this._contentDocument) :
-    undefined,
-  set index(value)
-    this._tab && this._window.gBrowser.moveTabTo(this._tab, value),
-  /**
-   * Thumbnail data URI of the page currently loaded in this tab.
-   * @type {String}
-   */
-  getThumbnail() {
-    if (!this._tab)
-      return undefined;
-    if (this._tab.getAttribute('remote')) {
-      console.error('This method is not supported with E10S');
-      return BLANK;
-    }
-    return getThumbnailURIForWindow(this._contentWindow);
+
+  set index(val) {
+    if (isDestroyed(this))
+      return;
+
+    move(viewsFor.get(this), val);
   },
-  /**
-   * Whether or not tab is pinned (Is an app-tab).
-   * @type {Boolean}
-   */
-  get isPinned() this._tab ? this._tab.pinned : undefined,
-  pin: function pin() {
-    if (!this._tab)
-      return;
-    this._window.gBrowser.pinTab(this._tab);
-  },
-  unpin: function unpin() {
-    if (!this._tab)
-      return;
-    this._window.gBrowser.unpinTab(this._tab);
+
+  get isPinned() {
+    return isDestroyed(this) ? undefined : viewsFor.get(this).pinned;
   },
 
-  /**
-   * Create a worker for this tab, first argument is options given to Worker.
-   * @type {Worker}
-   */
-  attach: function attach(options) {
-    if (!this._tab)
-      return;
-    // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
-    // TODO: fix this circular dependency
-    let { Worker } = require('./worker');
-    return Worker(options, this._contentWindow);
+  get window() {
+    if (isClosed(this))
+      return undefined;
+
+    // TODO: Remove the dependency on the windows module, see bug 792670
+    require('../windows');
+    let tabElement = viewsFor.get(this);
+    let domWindow = tabElement.ownerDocument.defaultView;
+    return modelFor(domWindow);
+  },
+
+  get readyState() {
+    // TODO: This will use CPOWs in e10s: bug 1146606
+    return isDestroyed(this) ? undefined : browser(this).contentDocument.readyState;
   },
 
-  /**
-   * Make this tab active.
-   * Please note: That this function is called asynchronous since in E10S that
-   * will be the case. Besides this function is called from a constructor where
-   * we would like to return instance before firing a 'TabActivated' event.
-   */
-  activate: defer(function activate() {
-    if (!this._tab)
+  pin: function() {
+    if (isDestroyed(this))
       return;
-    activateTab(this._tab);
-  }),
-  /**
-   * Close the tab
-   */
-  close: function close(callback) {
-    // Bug 699450: the tab may already have been detached
-    if (!this._tab || !this._tab.parentNode) {
+
+    pin(viewsFor.get(this));
+  },
+
+  unpin: function() {
+    if (isDestroyed(this))
+      return;
+
+    unpin(viewsFor.get(this));
+  },
+
+  close: function(callback) {
+    let tabElement = viewsFor.get(this);
+
+    if (isDestroyed(this) || !tabElement || !tabElement.parentNode) {
       if (callback)
         callback();
       return;
     }
-    if (callback) {
-      if (this.window.tabs.activeTab && (this.window.tabs.activeTab.id == this.id))
-        observer.once('select', callback);
-      else
-        this.once(EVENTS.close.name, callback);
-    }
-    this._window.gBrowser.removeTab(this._tab);
+
+    this.once('close', () => {
+      this.destroy();
+      if (callback)
+        callback();
+    });
+
+    closeTab(tabElement);
+  },
+
+  reload: function() {
+    if (isDestroyed(this))
+      return;
+
+    reload(viewsFor.get(this));
   },
-  /**
-   * Reload the tab
-   */
-  reload: function reload() {
-    if (!this._tab)
+
+  activate: defer(function() {
+    if (isDestroyed(this))
       return;
-    this._window.gBrowser.reloadTab(this._tab);
+
+    activateTab(viewsFor.get(this));
+  }),
+
+  getThumbnail: function() {
+    if (isDestroyed(this))
+      return BLANK;
+
+    // TODO: This is unimplemented in e10s: bug 1148601
+    if (browser(this).isRemoteBrowser) {
+      console.error('This method is not supported with E10S');
+      return BLANK;
+    }
+    return getThumbnailURIForWindow(browser(this).contentWindow);
+  },
+
+  attach: function(options) {
+    if (isDestroyed(this))
+      return;
+
+    // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
+    // TODO: fix this circular dependency
+    let { Worker } = require('./worker');
+    return Worker(options, browser(this).contentWindow);
+  },
+
+  destroy: function() {
+    if (isDestroyed(this))
+      return;
+
+    destroyed.set(this, true);
   }
 });
+exports.Tab = Tab;
 
-function getChromeTab(tab) {
-  return getOwnerWindow(viewNS(tab).tab);
+viewFor.define(Tab, tab => viewsFor.get(tab));
+
+// Returns the high-level window for this DOM window if the windows module has
+// ever been loaded otherwise returns null
+function maybeWindowFor(domWindow) {
+  try {
+    return modelFor(domWindow);
+  }
+  catch (e) {
+    return null;
+  }
 }
 
-// Implement `viewFor` polymorphic function for the Tab
-// instances.
-const getTabView = tab => viewNS(tab).tab;
+function tabEmit(tab, event, ...args) {
+  // Don't emit events for destroyed tabs
+  if (isDestroyed(tab))
+    return;
 
-function Tab(options, existingOnly) {
-  let chromeTab = options.tab;
-  for (let tab of TABS) {
-    if (chromeTab == tab._tab)
-      return tab._public;
+  // If the windows module was never loaded this will return null. We don't need
+  // to emit to the window.tabs object in this case as nothing can be listening.
+  let tabElement = viewsFor.get(tab);
+  let window = maybeWindowFor(tabElement.ownerDocument.defaultView);
+  if (window)
+    emit(window.tabs, event, tab, ...args);
+
+  emit(tabEvents, event, tab, ...args);
+  emit(tab, event, tab, ...args);
+}
+
+function windowClosed(domWindow) {
+  if (!isBrowser(domWindow))
+    return;
+
+  for (let tabElement of getTabs(domWindow)) {
+    tabEventListener("close", tabElement);
   }
-  // If called asked to return only existing wrapper,
-  // we should return null here as no matching Tab object has been found
-  if (existingOnly)
-    return null;
+}
+windowObserver.on('close', windowClosed);
+
+// Don't want to send close events after unloaded
+when(_ => {
+  windowObserver.off('close', windowClosed);
+});
+
+// Listen for tabbrowser events
+function tabEventListener(event, tabElement, ...args) {
+  let domWindow = tabElement.ownerDocument.defaultView;
+
+  if (ignoreWindow(domWindow))
+    return;
+
+  // Don't send events for tabs that are already closing
+  if (event != "close" && (tabElement.closing || !tabElement.parentNode))
+    return;
+
+  let tab = modelsFor.get(tabElement);
+  if (!tab)
+    tab = new Tab(tabElement);
+
+  let window = maybeWindowFor(domWindow);
 
-  let tab = TabTrait(options);
-  TABS.push(tab);
-  return tab._public;
+  if (event == "open") {
+    // Note, add to the window tabs first because if this is the first access to
+    // window.tabs it will be prefilling itself with everything from tabs
+    if (window)
+      addListItem(window.tabs, tab);
+    // The tabs module will take care of adding to its internal list
+  }
+  else if (event == "close") {
+    if (window)
+      removeListItem(window.tabs, tab);
+    // The tabs module will take care of removing from its internal list
+  }
+  else if (event == "ready" || event == "load") {
+    // Ignore load events from before browser windows have fully loaded, these
+    // are for about:blank in the initial tab
+    if (isBrowser(domWindow) && !domWindow.gBrowserInit.delayedStartupFinished)
+      return;
+  }
+
+  tabEmit(tab, event, ...args);
+
+  // The tab object shouldn't be reachable after closed
+  if (event == "close") {
+    viewsFor.delete(tab);
+    modelsFor.delete(tabElement);
+  }
 }
-Tab.prototype = TabTrait.prototype;
-exports.Tab = Tab;
+observer.on('*', tabEventListener);
+
+// Listen for tab events from content
+frames.port.on('sdk/tab/event', (frame, event, ...args) => {
+  if (!frame.isTab)
+    return;
+
+  let tabElement = getTabForBrowser(frame.frameElement);
+  if (!tabElement)
+    return;
+
+  tabEventListener(event, tabElement, ...args);
+});
+
+// Implement `modelFor` function for the Tab instances..
+modelFor.when(isTab, view => {
+  return modelsFor.get(view);
+});
--- a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
@@ -1,68 +1,134 @@
 /* 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';
+"use strict";
 
-// TODO: BUG 792670 - remove dependency below
-const { browserWindows: windows } = require('../windows');
-const { tabs } = require('../windows/tabs-firefox');
+const { Class } = require('../core/heritage');
+const { Tab, tabEvents } = require('./tab');
+const { EventTarget } = require('../event/target');
+const { emit, setListeners } = require('../event/core');
+const { pipe } = require('../event/utils');
+const { observer: windowObserver } = require('../windows/observer');
+const { List, addListItem, removeListItem } = require('../util/list');
+const { modelFor } = require('../model/core');
+const { viewFor } = require('../view/core');
+const { getTabs, getSelectedTab } = require('./utils');
+const { getMostRecentBrowserWindow, isBrowser } = require('../window/utils');
+const { Options } = require('./common');
 const { isPrivate } = require('../private-browsing');
-const { isWindowPBSupported } = require('../private-browsing/utils')
+const { ignoreWindow, isWindowPBSupported } = require('../private-browsing/utils')
 const { isPrivateBrowsingSupported } = require('sdk/self');
 
 const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
 
-function newTabWindow(options) {
-  // `tabs` option is under review and may be removed.
-  return windows.open({
-    tabs: [ options ],
-    isPrivate: options.isPrivate
-  });
-}
+const Tabs = Class({
+  implements: [EventTarget],
+  extends: List,
+  initialize: function() {
+    List.prototype.initialize.call(this);
+
+    // We must do the list manipulation here where the object is extensible
+    this.on("open", tab => {
+      addListItem(this, tab);
+    });
+
+    this.on("close", tab => {
+      removeListItem(this, tab);
+    });
+  },
 
-Object.defineProperties(tabs, {
-  open: { value: function open(options) {
-    if (options.inNewWindow) {
-        newTabWindow(options);
-        return undefined;
+  get activeTab() {
+    let activeDomWin = getMostRecentBrowserWindow();
+    if (!activeDomWin)
+      return null;
+    return modelFor(getSelectedTab(activeDomWin));
+  },
+
+  open: function(options) {
+    options = Options(options);
+
+    // TODO: Remove the dependency on the windows module: bug 792670
+    let windows = require('../windows').browserWindows;
+    let activeWindow = windows.activeWindow;
+
+    let privateState = supportPrivateTabs && options.isPrivate;
+    // When no isPrivate option was passed use the private state of the active
+    // window
+    if (activeWindow && privateState === undefined)
+      privateState = isPrivate(activeWindow);
+
+    function getWindow(privateState) {
+      for (let window of windows) {
+        if (privateState === isPrivate(window)) {
+          return window;
+        }
+      }
+      return null;
     }
 
-    let activeWindow = windows.activeWindow;
-    let privateState = (supportPrivateTabs && (options.isPrivate || isPrivate(activeWindow))) || false;
+    function openNewWindowWithTab() {
+      windows.open({
+        url: options.url,
+        isPrivate: privateState,
+        onOpen: function(newWindow) {
+          let tab = newWindow.tabs[0];
+          setListeners(tab, options);
+
+          if (options.isPinned)
+            tab.pin();
+
+          // We don't emit the open event for the first tab in a new window so
+          // do it now the listeners are attached
+          emit(tab, "open", tab);
+        }
+      });
+    }
+
+    if (options.inNewWindow)
+      return openNewWindowWithTab();
 
     // if the active window is in the state that we need then use it
-    if (activeWindow && (!supportPrivateTabs || privateState === isPrivate(activeWindow))) {
-      activeWindow.tabs.open(options);
-    }
-    else {
-      // find a window in the state that we need
-      let window = getWindow(privateState);
-      if (window) {
-        window.tabs.open(options);
-      }
-      // open a window in the state that we need
-      else {
-        newTabWindow(options);
-      }
-    }
+    if (activeWindow && (privateState === isPrivate(activeWindow)))
+      return activeWindow.tabs.open(options);
 
-    return undefined;
-  }}
+    // find a window in the state that we need
+    let window = getWindow(privateState);
+    if (window)
+      return window.tabs.open(options);
+
+    return openNewWindowWithTab();
+  }
 });
 
-function getWindow(privateState) {
-  for (let window of windows) {
-    if (privateState === isPrivate(window)) {
-      return window;
-    }
-  }
-  return null;
+const allTabs = new Tabs();
+// Export a new object with allTabs as the prototype, otherwise allTabs becomes
+// frozen and addListItem and removeListItem don't work correctly.
+module.exports = Object.create(allTabs);
+pipe(tabEvents, module.exports);
+
+function addWindowTab(window, tabElement) {
+  let tab = new Tab(tabElement);
+  if (window)
+    addListItem(window.tabs, tab);
+  addListItem(allTabs, tab);
 }
 
-// Workaround for bug 674195. Freezing objects from other compartments fail,
-// so we use `Object.freeze` from the same component as objects
-// `hasOwnProperty`. Since `hasOwnProperty` here will be from other component
-// we override it to support our workaround.
-module.exports = Object.create(tabs, {
-  isPrototypeOf: { value: Object.prototype.isPrototypeOf }
+// Find tabs in already open windows
+for (let tabElement of getTabs())
+  addWindowTab(null, tabElement);
+
+// Detect tabs in new windows
+windowObserver.on('open', domWindow => {
+  if (!isBrowser(domWindow) || ignoreWindow(domWindow))
+    return;
+
+  let window = null;
+  try {
+    modelFor(domWindow);
+  }
+  catch (e) { }
+
+  for (let tabElement of getTabs(domWindow)) {
+    addWindowTab(window, tabElement);
+  }
 });
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ b/addon-sdk/source/lib/sdk/tabs/utils.js
@@ -208,24 +208,35 @@ function getTabId(tab) {
 exports.getTabId = getTabId;
 
 function getTabForId(id) {
   return getTabs().find(tab => getTabId(tab) === id) || null;
 }
 exports.getTabForId = getTabForId;
 
 function getTabTitle(tab) {
-  return getBrowserForTab(tab).contentDocument.title || tab.label || "";
+  return getBrowserForTab(tab).contentTitle || tab.label || "";
 }
 exports.getTabTitle = getTabTitle;
 
 function setTabTitle(tab, title) {
   title = String(title);
-  if (tab.browser)
+  if (tab.browser) {
+    // Fennec
     tab.browser.contentDocument.title = title;
+  }
+  else {
+    let browser = getBrowserForTab(tab);
+    // Note that we aren't actually setting the document title in e10s, just
+    // the title the browser thinks the content has
+    if (browser.isRemoteBrowser)
+      browser._contentTitle = title;
+    else
+      browser.contentDocument.title = title;
+  }
   tab.label = String(title);
 }
 exports.setTabTitle = setTabTitle;
 
 function getTabContentDocument(tab) {
   return getBrowserForTab(tab).contentDocument;
 }
 exports.getTabContentDocument = getTabContentDocument;
@@ -245,27 +256,23 @@ exports.getAllTabContentWindows = getAll
 
 // gets the tab containing the provided window
 function getTabForContentWindow(window) {
   return getTabs().find(tab => getTabContentWindow(tab) === window.top) || null;
 }
 exports.getTabForContentWindow = getTabForContentWindow;
 
 function getTabURL(tab) {
-  if (tab.browser) // fennec
-    return String(tab.browser.currentURI.spec);
   return String(getBrowserForTab(tab).currentURI.spec);
 }
 exports.getTabURL = getTabURL;
 
 function setTabURL(tab, url) {
-  url = String(url);
-  if (tab.browser)
-    return tab.browser.loadURI(url);
-  return getBrowserForTab(tab).loadURI(url);
+  let browser = getBrowserForTab(tab);
+  browser.loadURI(String(url));
 }
 // "TabOpen" event is fired when it's still "about:blank" is loaded in the
 // changing `location` property of the `contentDocument` has no effect since
 // seems to be either ignored or overridden by internal listener, there for
 // location change is enqueued for the next turn of event loop.
 exports.setTabURL = defer(setTabURL);
 
 function getTabContentType(tab) {
@@ -313,30 +320,25 @@ function unpin(tab) {
   if (gBrowser) gBrowser.unpinTab(tab);
 }
 exports.unpin = unpin;
 
 function isPinned(tab) !!tab.pinned
 exports.isPinned = isPinned;
 
 function reload(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // Firefox
-  if (gBrowser) gBrowser.unpinTab(tab);
-  // Fennec
-  else if (tab.browser) tab.browser.reload();
+  getBrowserForTab(tab).reload();
 }
 exports.reload = reload
 
 function getIndex(tab) {
   let gBrowser = getTabBrowserForTab(tab);
   // Firefox
   if (gBrowser) {
-    let document = getBrowserForTab(tab).contentDocument;
-    return gBrowser.getBrowserIndexForDocument(document);
+    return tab._tPos;
   }
   // Fennec
   else {
     let window = getWindowHoldingTab(tab)
     let tabs = window.BrowserApp.tabs;
     for (let i = tabs.length; i >= 0; i--)
       if (tabs[i] === tab) return i;
   }
--- a/addon-sdk/source/lib/sdk/test/harness.js
+++ b/addon-sdk/source/lib/sdk/test/harness.js
@@ -434,16 +434,22 @@ var POINTLESS_ERRORS = [
   '[JavaScript Warning: "Duplicate resource declaration for',
   'file: "chrome://browser/content/',
   'file: "chrome://global/content/',
   '[JavaScript Warning: "The character encoding of a framed document was ' +
     'not declared.',
   'file: "chrome://browser/skin/'
 ];
 
+// These are messages that will cause a test to fail if logged through the
+// console service
+var IMPORTANT_ERRORS = [
+  'Sending message that cannot be cloned. Are you trying to send an XPCOM object?',
+];
+
 var consoleListener = {
   registered: false,
 
   register: function() {
     if (this.registered)
       return;
     cService.registerListener(this);
     this.registered = true;
@@ -458,16 +464,20 @@ var consoleListener = {
 
   errorsLogged: 0,
 
   observe: function(object) {
     if (!(object instanceof Ci.nsIScriptError))
       return;
     this.errorsLogged++;
     var message = object.QueryInterface(Ci.nsIConsoleMessage).message;
+    if (IMPORTANT_ERRORS.find(msg => message.indexOf(msg) >= 0)) {
+      testConsole.error(message);
+      return;
+    }
     var pointless = [err for (err of POINTLESS_ERRORS)
                          if (message.indexOf(err) >= 0)];
     if (pointless.length == 0 && message)
       testConsole.log(message);
   }
 };
 
 function TestRunnerConsole(base, options) {
@@ -592,18 +602,18 @@ var runTests = exports.runTests = functi
     passed: 0,
     failed: 0,
     testRuns: []
   };
 
   try {
     consoleListener.register();
     print("Running tests on " + system.name + " " + system.version +
-          "/Gecko " + system.platformVersion + " (" +
-          system.id + ") under " +
+          "/Gecko " + system.platformVersion + " (Build " +
+          system.build + ") (" + system.id + ") under " +
           system.platform + "/" + system.architecture + ".\n");
 
     if (options.parseable)
       testConsole = new TestRunnerTinderboxConsole(new PlainTextConsole(), options);
     else
       testConsole = new TestRunnerConsole(new PlainTextConsole(), options);
 
     loader = Loader(module, {
--- a/addon-sdk/source/lib/sdk/test/httpd.js
+++ b/addon-sdk/source/lib/sdk/test/httpd.js
@@ -1,6 +1,6 @@
 /* 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/. */
+ * 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/. */
 
 throw new Error(`This file was removed. A copy can be obtained from:
   https://github.com/mozilla/addon-sdk/blob/master/test/lib/httpd.js`);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/tmp-file.js
+++ /dev/null
@@ -1,82 +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, Cu } = require("chrome");
-
-const system = require("sdk/system");
-const file = require("sdk/io/file");
-const unload = require("sdk/system/unload");
-
-// Retrieve the path to the OS temporary directory:
-const tmpDir = require("sdk/system").pathFor("TmpD");
-
-const { Services } = Cu.import("resource://gre/modules/Services.jsm");
-
-// List of all tmp file created
-let files = [];
-
-// Remove all tmp files on addon disabling
-unload.when(function () {
-  files.forEach(function (path){
-    // Catch exception in order to avoid leaking following files
-    try {
-      if (file.exists(path))
-        file.remove(path);
-    }
-    catch(e) {
-      console.exception(e);
-    }
-  });
-});
-
-// Utility function that synchronously reads local resource from the given
-// `uri` and returns content string. Read in binary mode.
-function readBinaryURI(uri) {
-  let ioservice = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
-  let channel = ioservice.newChannel2(uri,
-                                      "UTF-8",
-                                      null,
-                                      null,      // aLoadingNode
-                                      Services.scriptSecurityManager.getSystemPrincipal(),
-                                      null,      // aTriggeringPrincipal
-                                      Ci.nsILoadInfo.SEC_NORMAL,
-                                      Ci.nsIContentPolicy.TYPE_OTHER);
-  let stream = Cc["@mozilla.org/binaryinputstream;1"].
-               createInstance(Ci.nsIBinaryInputStream);
-  stream.setInputStream(channel.open());
-
-  let data = "";
-  while (true) {
-    let available = stream.available();
-    if (available <= 0)
-      break;
-    data += stream.readBytes(available);
-  }
-  stream.close();
-
-  return data;
-}
-
-// Create a temporary file from a given string and returns its path
-exports.createFromString = function createFromString(data, tmpName) {  
-  let filename = (tmpName ? tmpName : "tmp-file") + "-" + (new Date().getTime());
-  let path = file.join(tmpDir, filename);
-
-  let tmpFile = file.open(path, "wb");
-  tmpFile.write(data);
-  tmpFile.close();
-
-  // Register tmp file path
-  files.push(path);
-
-  return path;
-}
-
-// Create a temporary file from a given URL and returns its path
-exports.createFromURL = function createFromURL(url, tmpName) {
-  let data = readBinaryURI(url);
-  return exports.createFromString(data, tmpName);
-}
-
--- a/addon-sdk/source/lib/sdk/ui/button/contract.js
+++ b/addon-sdk/source/lib/sdk/ui/button/contract.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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 { isLocalURL } = require('../../url');
 const { isNil, isObject, isString } = require('../../lang/type');
 const { required, either, string, boolean, object, number } = require('../../deprecated/api-utils');
 const { merge } = require('../../util/object');
 const { freeze } = Object;
--- a/addon-sdk/source/lib/sdk/ui/frame.js
+++ b/addon-sdk/source/lib/sdk/ui/frame.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/frame/model.js
+++ b/addon-sdk/source/lib/sdk/ui/frame/model.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/frame/view.js
+++ b/addon-sdk/source/lib/sdk/ui/frame/view.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/sidebar.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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': '*'
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/sidebar/actions.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/actions.js
@@ -1,10 +1,10 @@
 /* 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/. */
+ * 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');
--- a/addon-sdk/source/lib/sdk/ui/sidebar/contract.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/contract.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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: {
--- a/addon-sdk/source/lib/sdk/ui/sidebar/namespace.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/namespace.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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) views.get(sidebar);
 exports.modelFor = function modelFor(sidebar) models.get(sidebar);
--- a/addon-sdk/source/lib/sdk/ui/sidebar/utils.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/utils.js
@@ -1,8 +1,8 @@
 /* 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/. */
+ * 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');
--- a/addon-sdk/source/lib/sdk/ui/sidebar/view.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/view.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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': '*'
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/toolbar.js
+++ b/addon-sdk/source/lib/sdk/ui/toolbar.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/toolbar/model.js
+++ b/addon-sdk/source/lib/sdk/ui/toolbar/model.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/ui/toolbar/view.js
+++ b/addon-sdk/source/lib/sdk/ui/toolbar/view.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * 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"
   }
 };
--- a/addon-sdk/source/lib/sdk/util/dispatcher.js
+++ b/addon-sdk/source/lib/sdk/util/dispatcher.js
@@ -1,12 +1,11 @@
 /* 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/.
- */
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const method = require("method/core");
 
--- a/addon-sdk/source/lib/sdk/view/core.js
+++ b/addon-sdk/source/lib/sdk/view/core.js
@@ -1,12 +1,11 @@
 /* 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"
 };
 
 var { Ci } = require("chrome");
 var method = require("../../method/core");
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/widget.js
+++ /dev/null
@@ -1,952 +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 widget module currently supports only Firefox.
-// See: https://bugzilla.mozilla.org/show_bug.cgi?id=560716
-module.metadata = {
-  "stability": "deprecated",
-  "engines": {
-    "Firefox": "*"
-  }
-};
-
-// Widget content types
-const CONTENT_TYPE_URI    = 1;
-const CONTENT_TYPE_HTML   = 2;
-const CONTENT_TYPE_IMAGE  = 3;
-
-const ERR_CONTENT = "No content or contentURL property found. Widgets must "
-                         + "have one or the other.",
-      ERR_LABEL = "The widget must have a non-empty label property.",
-      ERR_ID = "You have to specify a unique value for the id property of " +
-               "your widget in order for the application to remember its " +
-               "position.",
-      ERR_DESTROYED = "The widget has been destroyed and can no longer be used.";
-
-const INSERTION_PREF_ROOT = "extensions.sdk-widget-inserted.";
-
-// Supported events, mapping from DOM event names to our event names
-const EVENTS = {
-  "click": "click",
-  "mouseover": "mouseover",
-  "mouseout": "mouseout",
-};
-
-// In the Australis menu panel, normally widgets should be treated like
-// normal toolbarbuttons. If they're any wider than this margin, we'll
-// treat them as wide widgets instead, which fill up the width of the panel:
-const AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF = 70;
-const AUSTRALIS_PANEL_WIDE_CLASSNAME = "panel-wide-item";
-
-const { validateOptions } = require("./deprecated/api-utils");
-const panels = require("./panel");
-const { EventEmitter, EventEmitterTrait } = require("./deprecated/events");
-const { Trait } = require("./deprecated/traits");
-const LightTrait = require('./deprecated/light-traits').Trait;
-const { Loader } = require("./content/loader");
-const { Symbiont } = require("./deprecated/symbiont");
-const { Cortex } = require('./deprecated/cortex');
-const windowsAPI = require("./windows");
-const { WindowTracker } = require("./deprecated/window-utils");
-const { isBrowser } = require("./window/utils");
-const { setTimeout } = require("./timers");
-const unload = require("./system/unload");
-const { getNodeView } = require("./view/core");
-const prefs = require('./preferences/service');
-
-require("./util/deprecate").deprecateUsage(
-  "The widget module is deprecated.  " +
-  "Please consider using the sdk/ui module instead."
-);
-
-// Data types definition
-const valid = {
-  number: { is: ["null", "undefined", "number"] },
-  string: { is: ["null", "undefined", "string"] },
-  id: {
-    is: ["string"],
-    ok: function (v) v.length > 0,
-    msg: ERR_ID,
-    readonly: true
-  },
-  label: {
-    is: ["string"],
-    ok: function (v) v.length > 0,
-    msg: ERR_LABEL
-  },
-  panel: {
-    is: ["null", "undefined", "object"],
-    ok: function(v) !v || v instanceof panels.Panel
-  },
-  width: {
-    is: ["null", "undefined", "number"],
-    map: function (v) {
-      if (null === v || undefined === v) v = 16;
-      return v;
-    },
-    defaultValue: 16
-  },
-  allow: {
-    is: ["null", "undefined", "object"],
-    map: function (v) {
-      if (!v) v = { script: true };
-      return v;
-    },
-    get defaultValue() ({ script: true })
-  },
-};
-
-// Widgets attributes definition
-let widgetAttributes = {
-  label: valid.label,
-  id: valid.id,
-  tooltip: valid.string,
-  width: valid.width,
-  content: valid.string,
-  panel: valid.panel,
-  allow: valid.allow
-};
-
-// Import data definitions from loader, but don't compose with it as Model
-// functions allow us to recreate easily all Loader code.
-let loaderAttributes = require("./content/loader").validationAttributes;
-for (let i in loaderAttributes)
-  widgetAttributes[i] = loaderAttributes[i];
-
-widgetAttributes.contentURL.optional = true;
-
-// Widgets public events list, that are automatically binded in options object
-const WIDGET_EVENTS = [
-  "click",
-  "mouseover",
-  "mouseout",
-  "error",
-  "message",
-  "attach"
-];
-
-// `Model` utility functions that help creating these various Widgets objects
-let model = {
-
-  // Validate one attribute using api-utils.js:validateOptions function
-  _validate: function _validate(name, suspect, validation) {
-    let $1 = {};
-    $1[name] = suspect;
-    let $2 = {};
-    $2[name] = validation;
-    return validateOptions($1, $2)[name];
-  },
-
-  /**
-   * This method has two purposes:
-   * 1/ Validate and define, on a given object, a set of attribute
-   * 2/ Emit a "change" event on this object when an attribute is changed
-   *
-   * @params {Object} object
-   *    Object on which we can bind attributes on and watch for their changes.
-   *    This object must have an EventEmitter interface, or, at least `_emit`
-   *    method
-   * @params {Object} attrs
-   *    Dictionary of attributes definition following api-utils:validateOptions
-   *    scheme
-   * @params {Object} values
-   *    Dictionary of attributes default values
-   */
-  setAttributes: function setAttributes(object, attrs, values) {
-    let properties = {};
-    for (let name in attrs) {
-      let value = values[name];
-      let req = attrs[name];
-
-      // Retrieve default value from typedef if the value is not defined
-      if ((typeof value == "undefined" || value == null) && req.defaultValue)
-        value = req.defaultValue;
-
-      // Check for valid value if value is defined or mandatory
-      if (!req.optional || typeof value != "undefined")
-        value = model._validate(name, value, req);
-
-      // In any case, define this property on `object`
-      let property = null;
-      if (req.readonly) {
-        property = {
-          value: value,
-          writable: false,
-          enumerable: true,
-          configurable: false
-        };
-      }
-      else {
-        property = model._createWritableProperty(name, value);
-      }
-
-      properties[name] = property;
-    }
-    Object.defineProperties(object, properties);
-  },
-
-  // Generate ES5 property definition for a given attribute
-  _createWritableProperty: function _createWritableProperty(name, value) {
-    return {
-      get: function () {
-        return value;
-      },
-      set: function (newValue) {
-        value = newValue;
-        // The main goal of all this Model stuff is here:
-        // We want to forward all changes to some listeners
-        this._emit("change", name, value);
-      },
-      enumerable: true,
-      configurable: false
-    };
-  },
-
-  /**
-   * Automagically register listeners in options dictionary
-   * by detecting listener attributes with name starting with `on`
-   *
-   * @params {Object} object
-   *    Target object that need to follow EventEmitter interface, or, at least,
-   *    having `on` method.
-   * @params {Array} events
-   *    List of events name to automatically bind.
-   * @params {Object} listeners
-   *    Dictionary of event listener functions to register.
-   */
-  setEvents: function setEvents(object, events, listeners) {
-    for (let i = 0, l = events.length; i < l; i++) {
-      let name = events[i];
-      let onName = "on" + name[0].toUpperCase() + name.substr(1);
-      if (!listeners[onName])
-        continue;
-      object.on(name, listeners[onName].bind(object));
-    }
-  }
-
-};
-
-function saveInserted(widgetId) {
-  prefs.set(INSERTION_PREF_ROOT + widgetId, true);
-}
-
-function haveInserted(widgetId) {
-  return prefs.has(INSERTION_PREF_ROOT + widgetId);
-}
-
-const isWide = node => node.classList.contains(AUSTRALIS_PANEL_WIDE_CLASSNAME);
-
-/**
- * Main Widget class: entry point of the widget API
- *
- * Allow to control all widget across all existing windows with a single object.
- * Widget.getView allow to retrieve a WidgetView instance to control a widget
- * specific to one window.
- */
-const WidgetTrait = LightTrait.compose(EventEmitterTrait, LightTrait({
-
-  _initWidget: function _initWidget(options) {
-    model.setAttributes(this, widgetAttributes, options);
-
-    browserManager.validate(this);
-
-    // We must have at least content or contentURL defined
-    if (!(this.content || this.contentURL))
-      throw new Error(ERR_CONTENT);
-
-    this._views = [];
-
-    // Set tooltip to label value if we don't have tooltip defined
-    if (!this.tooltip)
-      this.tooltip = this.label;
-
-    model.setEvents(this, WIDGET_EVENTS, options);
-
-    this.on('change', this._onChange.bind(this));
-
-    let self = this;
-    this._port = EventEmitterTrait.create({
-      emit: function () {
-        let args = arguments;
-        self._views.forEach(function(v) v.port.emit.apply(v.port, args));
-      }
-    });
-    // expose wrapped port, that exposes only public properties.
-    this._port._public = Cortex(this._port);
-
-    // Register this widget to browser manager in order to create new widget on
-    // all new windows
-    browserManager.addItem(this);
-  },
-
-  _onChange: function _onChange(name, value) {
-    // Set tooltip to label value if we don't have tooltip defined
-    if (name == 'tooltip' && !value) {
-      // we need to change tooltip again in order to change the value of the
-      // attribute itself
-      this.tooltip = this.label;
-      return;
-    }
-
-    // Forward attributes changes to WidgetViews
-    if (['width', 'tooltip', 'content', 'contentURL'].indexOf(name) != -1) {
-      this._views.forEach(function(v) v[name] = value);
-    }
-  },
-
-  _onEvent: function _onEvent(type, eventData) {
-    this._emit(type, eventData);
-  },
-
-  _createView: function _createView() {
-    // Create a new WidgetView instance
-    let view = WidgetView(this);
-
-    // Keep a reference to it
-    this._views.push(view);
-
-    return view;
-  },
-
-  // a WidgetView instance is destroyed
-  _onViewDestroyed: function _onViewDestroyed(view) {
-    let idx = this._views.indexOf(view);
-    this._views.splice(idx, 1);
-  },
-
-  /**
-   * Called on browser window closed, to destroy related WidgetViews
-   * @params {ChromeWindow} window
-   *         Window that has been closed
-   */
-  _onWindowClosed: function _onWindowClosed(window) {
-    for (let view of this._views) {
-      if (view._isInChromeWindow(window)) {
-        view.destroy();
-        break;
-      }
-    }
-  },
-
-  /**
-   * Get the WidgetView instance related to a BrowserWindow instance
-   * @params {BrowserWindow} window
-   *         BrowserWindow reference from "windows" module
-   */
-  getView: function getView(window) {
-    for (let view of this._views) {
-      if (view._isInWindow(window)) {
-        return view._public;
-      }
-    }
-    return null;
-  },
-
-  get port() this._port._public,
-  set port(v) {}, // Work around Cortex failure with getter without setter
-                  // See bug 653464
-  _port: null,
-
-  postMessage: function postMessage(message) {
-    this._views.forEach(function(v) v.postMessage(message));
-  },
-
-  destroy: function destroy() {
-    if (this.panel)
-      this.panel.destroy();
-
-    // Dispatch destroy calls to views
-    // we need to go backward as we remove items from this array in
-    // _onViewDestroyed
-    for (let i = this._views.length - 1; i >= 0; i--)
-      this._views[i].destroy();
-
-    // Unregister widget to stop creating it over new windows
-    // and allow creation of new widget with same id
-    browserManager.removeItem(this);
-  }
-
-}));
-
-// Widget constructor
-const Widget = function Widget(options) {
-  let w = WidgetTrait.create(Widget.prototype);
-  w._initWidget(options);
-
-  // Return a Cortex of widget in order to hide private attributes like _onEvent
-  let _public = Cortex(w);
-  unload.ensure(_public, "destroy");
-  return _public;
-}
-exports.Widget = Widget;
-
-
-/**
- * WidgetView is an instance of a widget for a specific window.
- *
- * This is an external API that can be retrieved by calling Widget.getView or
- * by watching `attach` event on Widget.
- */
-const WidgetViewTrait = LightTrait.compose(EventEmitterTrait, LightTrait({
-
-  // Reference to the matching WidgetChrome
-  // set right after constructor call
-  _chrome: null,
-
-  // Public interface of the WidgetView, passed in `attach` event or in
-  // Widget.getView
-  _public: null,
-
-  _initWidgetView: function WidgetView__initWidgetView(baseWidget) {
-    this._baseWidget = baseWidget;
-
-    model.setAttributes(this, widgetAttributes, baseWidget);
-
-    this.on('change', this._onChange.bind(this));
-
-    let self = this;
-    this._port = EventEmitterTrait.create({
-      emit: function () {
-        if (!self._chrome)
-          throw new Error(ERR_DESTROYED);
-        self._chrome.update(self._baseWidget, "emit", arguments);
-      }
-    });
-    // expose wrapped port, that exposes only public properties.
-    this._port._public = Cortex(this._port);
-
-    this._public = Cortex(this);
-  },
-
-  // Called by WidgetChrome, when the related Worker is applied to the document,
-  // so that we can start sending events to it
-  _onWorkerReady: function () {
-    // Emit an `attach` event with a WidgetView instance without private attrs
-    this._baseWidget._emit("attach", this._public);
-  },
-
-  _onChange: function WidgetView__onChange(name, value) {
-    if (name == 'tooltip' && !value) {
-      this.tooltip = this.label;
-      return;
-    }
-
-    // Forward attributes changes to WidgetChrome instance
-    if (['width', 'tooltip', 'content', 'contentURL'].indexOf(name) != -1) {
-      this._chrome.update(this._baseWidget, name, value);
-    }
-  },
-
-  _onEvent: function WidgetView__onEvent(type, eventData, domNode) {
-    // Dispatch event in view
-    this._emit(type, eventData);
-
-    // And forward it to the main Widget object
-    if ("click" == type || type.indexOf("mouse") == 0)
-      this._baseWidget._onEvent(type, this._public);
-    else
-      this._baseWidget._onEvent(type, eventData);
-
-    // Special case for click events: if the widget doesn't have a click
-    // handler, but it does have a panel, display the panel.
-    if ("click" == type && !this._listeners("click").length && this.panel) {
-      // This kind of ugly workaround, instead we should implement
-      // `getNodeView` for the `Widget` class itself, but that's kind of
-      // hard without cleaning things up.
-      this.panel.show(null, getNodeView.implement({}, () => domNode));
-    }
-  },
-
-  _isInWindow: function WidgetView__isInWindow(window) {
-    return windowsAPI.BrowserWindow({
-      window: this._chrome.window
-    }) == window;
-  },
-
-  _isInChromeWindow: function WidgetView__isInChromeWindow(window) {
-    return this._chrome.window == window;
-  },
-
-  _onPortEvent: function WidgetView__onPortEvent(args) {
-    let port = this._port;
-    port._emit.apply(port, args);
-    let basePort = this._baseWidget._port;
-    basePort._emit.apply(basePort, args);
-  },
-
-  get port() this._port._public,
-  set port(v) {}, // Work around Cortex failure with getter without setter
-                  // See bug 653464
-  _port: null,
-
-  postMessage: function WidgetView_postMessage(message) {
-    if (!this._chrome)
-      throw new Error(ERR_DESTROYED);
-    this._chrome.update(this._baseWidget, "postMessage", message);
-  },
-
-  destroy: function WidgetView_destroy() {
-    this._chrome.destroy();
-    delete this._chrome;
-    this._baseWidget._onViewDestroyed(this);
-    this._emit("detach");
-  }
-
-}));
-
-
-const WidgetView = function WidgetView(baseWidget) {
-  let w = WidgetViewTrait.create(WidgetView.prototype);
-  w._initWidgetView(baseWidget);
-  return w;
-}
-
-
-/**
- * Keeps track of all browser windows.
- * Exposes methods for adding/removing widgets
- * across all open windows (and future ones).
- * Create a new instance of BrowserWindow per window.
- */
-let browserManager = {
-  items: [],
-  windows: [],
-
-  // Registers the manager to listen for window openings and closings.  Note
-  // that calling this method can cause onTrack to be called immediately if
-  // there are open windows.
-  init: function () {
-    let windowTracker = new WindowTracker(this);
-    unload.ensure(windowTracker);
-  },
-
-  // Registers a window with the manager.  This is a WindowTracker callback.
-  onTrack: function browserManager_onTrack(window) {
-    if (isBrowser(window)) {
-      let win = new BrowserWindow(window);
-      win.addItems(this.items);
-      this.windows.push(win);
-    }
-  },
-
-  // Unregisters a window from the manager.  It's told to undo all
-  // modifications.  This is a WindowTracker callback.  Note that when
-  // WindowTracker is unloaded, it calls onUntrack for every currently opened
-  // window.  The browserManager therefore doesn't need to specially handle
-  // unload itself, since unloading the browserManager means untracking all
-  // currently opened windows.
-  onUntrack: function browserManager_onUntrack(window) {
-    if (isBrowser(window)) {
-      this.items.forEach(function(i) i._onWindowClosed(window));
-      for (let i = 0; i < this.windows.length; i++) {
-        if (this.windows[i].window == window) {
-          this.windows.splice(i, 1)[0];
-          return;
-        }
-      }
-
-    }
-  },
-
-  // Used to validate widget by browserManager before adding it,
-  // in order to check input very early in widget constructor
-  validate : function (item) {
-    let idx = this.items.indexOf(item);
-    if (idx > -1)
-      throw new Error("The widget " + item + " has already been added.");
-    if (item.id) {
-      let sameId = this.items.filter(function(i) i.id == item.id);
-      if (sameId.length > 0)
-        throw new Error("This widget ID is already used: " + item.id);
-    } else {
-      item.id = this.items.length;
-    }
-  },
-
-  // Registers an item with the manager. It's added to all currently registered
-  // windows, and when new windows are registered it will be added to them, too.
-  addItem: function browserManager_addItem(item) {
-    this.items.push(item);
-    this.windows.forEach(function (w) w.addItems([item]));
-  },
-
-  // Unregisters an item from the manager.  It's removed from all windows that
-  // are currently registered.
-  removeItem: function browserManager_removeItem(item) {
-    let idx = this.items.indexOf(item);
-    if (idx > -1)
-      this.items.splice(idx, 1);
-  },
-  propagateCurrentset: function browserManager_propagateCurrentset(id, currentset) {
-    this.windows.forEach(function (w) w.doc.getElementById(id).setAttribute("currentset", currentset));
-  }
-};
-
-
-
-/**
- * Keeps track of a single browser window.
- *
- * This is where the core of how a widget's content is added to a window lives.
- */
-function BrowserWindow(window) {
-  this.window = window;
-  this.doc = window.document;
-}
-
-BrowserWindow.prototype = {
-  // Adds an array of items to the window.
-  addItems: function BW_addItems(items) {
-    items.forEach(this._addItemToWindow, this);
-  },
-
-  _addItemToWindow: function BW__addItemToWindow(baseWidget) {
-    // Create a WidgetView instance
-    let widget = baseWidget._createView();
-
-    // Create a WidgetChrome instance
-    let item = new WidgetChrome({
-      widget: widget,
-      doc: this.doc,
-      window: this.window
-    });
-
-    widget._chrome = item;
-
-    this._insertNodeInToolbar(item.node);
-
-    // We need to insert Widget DOM Node before finishing widget view creation
-    // (because fill creates an iframe and tries to access its docShell)
-    item.fill();
-  },
-
-  _insertNodeInToolbar: function BW__insertNodeInToolbar(node) {
-    // Add to the customization palette
-    let toolbox = this.doc.getElementById("navigator-toolbox");
-    let palette = toolbox.palette;
-    palette.appendChild(node);
-
-    let { CustomizableUI } = this.window;
-    let { id } = node;
-
-    let placement = CustomizableUI.getPlacementOfWidget(id);
-
-    if (!placement) {
-      if (haveInserted(id) || isWide(node))
-        return;
-
-      placement = {area: 'nav-bar', position: undefined};
-      saveInserted(id);
-    }
-
-    CustomizableUI.addWidgetToArea(id, placement.area, placement.position);
-    CustomizableUI.ensureWidgetPlacedInWindow(id, this.window);
-  }
-}
-
-
-/**
- * Final Widget class that handles chrome DOM Node:
- *  - create initial DOM nodes
- *  - receive instruction from WidgetView through update method and update DOM
- *  - watch for DOM events and forward them to WidgetView
- */
-function WidgetChrome(options) {
-  this.window = options.window;
-  this._doc = options.doc;
-  this._widget = options.widget;
-  this._symbiont = null; // set later
-  this.node = null; // set later
-
-  this._createNode();
-}
-
-// Update a property of a widget.
-WidgetChrome.prototype.update = function WC_update(updatedItem, property, value) {
-  switch(property) {
-    case "contentURL":
-    case "content":
-      this.setContent();
-      break;
-    case "width":
-      this.node.style.minWidth = value + "px";
-      this.node.querySelector("iframe").style.width = value + "px";
-      break;
-    case "tooltip":
-      this.node.setAttribute("tooltiptext", value);
-      break;
-    case "postMessage":
-      this._symbiont.postMessage(value);
-      break;
-    case "emit":
-      let port = this._symbiont.port;
-      port.emit.apply(port, value);
-      break;
-  }
-}
-
-// Add a widget to this window.
-WidgetChrome.prototype._createNode = function WC__createNode() {
-  // XUL element container for widget
-  let node = this._doc.createElement("toolbaritem");
-
-  // Temporary work around require("self") failing on unit-test execution ...
-  let jetpackID = "testID";
-  try {
-    jetpackID = require("./self").id;
-  } catch(e) {}
-
-  // Compute an unique and stable widget id with jetpack id and widget.id
-  let id = "widget:" + jetpackID + "-" + this._widget.id;
-  node.setAttribute("id", id);
-  node.setAttribute("label", this._widget.label);
-  node.setAttribute("tooltiptext", this._widget.tooltip);
-  node.setAttribute("align", "center");
-  // Bug 626326: Prevent customize toolbar context menu to appear
-  node.setAttribute("context", "");
-
-  // For use in styling by the browser
-  node.setAttribute("sdkstylewidget", "true");
-
-  if (this._widget.width > AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF) {
-    node.classList.add(AUSTRALIS_PANEL_WIDE_CLASSNAME);
-  }
-
-  // TODO move into a stylesheet, configurable by consumers.
-  // Either widget.style, exposing the style object, or a URL
-  // (eg, can load local stylesheet file).
-  node.setAttribute("style", [
-      "overflow: hidden; margin: 1px 2px 1px 2px; padding: 0px;",
-      "min-height: 16px;",
-  ].join(""));
-
-  node.style.minWidth = this._widget.width + "px";
-
-  this.node = node;
-}
-
-// Initial population of a widget's content.
-WidgetChrome.prototype.fill = function WC_fill() {
-  let { node, _doc: document } = this;
-
-  // Create element
-  let iframe = document.createElement("iframe");
-  iframe.setAttribute("type", "content");
-  iframe.setAttribute("transparent", "transparent");
-  iframe.style.overflow = "hidden";
-  iframe.style.height = "16px";
-  iframe.style.maxHeight = "16px";
-  iframe.style.width = this._widget.width + "px";
-  iframe.setAttribute("flex", "1");
-  iframe.style.border = "none";
-  iframe.style.padding = "0px";
-
-  // Do this early, because things like contentWindow are null
-  // until the node is attached to a document.
-  node.appendChild(iframe);
-
-  let label = document.createElement("label");
-  label.setAttribute("value", this._widget.label);
-  label.className = "toolbarbutton-text";
-  label.setAttribute("crop", "right");
-  label.setAttribute("flex", "1");
-  node.appendChild(label);
-
-  // This toolbarbutton is created to provide a more consistent user experience
-  // during customization, see:
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=959640
-  let button = document.createElement("toolbarbutton");
-  button.setAttribute("label", this._widget.label);
-  button.setAttribute("crop", "right");
-  button.className = "toolbarbutton-1 chromeclass-toolbar-additional";
-  node.appendChild(button);
-
-  // add event handlers
-  this.addEventHandlers();
-
-  // set content
-  this.setContent();
-}
-
-// Get widget content type.
-WidgetChrome.prototype.getContentType = function WC_getContentType() {
-  if (this._widget.content)
-    return CONTENT_TYPE_HTML;
-  return (this._widget.contentURL && /\.(jpg|gif|png|ico|svg)$/i.test(this._widget.contentURL))
-    ? CONTENT_TYPE_IMAGE : CONTENT_TYPE_URI;
-}
-
-// Set widget content.
-WidgetChrome.prototype.setContent = function WC_setContent() {
-  let type = this.getContentType();
-  let contentURL = null;
-
-  switch (type) {
-    case CONTENT_TYPE_HTML:
-      contentURL = "data:text/html;charset=utf-8," + encodeURIComponent(this._widget.content);
-      break;
-    case CONTENT_TYPE_URI:
-      contentURL = this._widget.contentURL;
-      break;
-    case CONTENT_TYPE_IMAGE:
-      let imageURL = this._widget.contentURL;
-      contentURL = "data:text/html;charset=utf-8,<html><body><img src='" +
-                   encodeURI(imageURL) + "'></body></html>";
-      break;
-    default:
-      throw new Error("The widget's type cannot be determined.");
-  }
-
-  let iframe = this.node.firstElementChild;
-
-  let self = this;
-  // Cleanup previously created symbiont (in case we are update content)
-  if (this._symbiont)
-    this._symbiont.destroy();
-
-  this._symbiont = Trait.compose(Symbiont.resolve({
-    _onContentScriptEvent: "_onContentScriptEvent-not-used",
-    _onInit: "_initSymbiont"
-  }), {
-    // Overload `Symbiont._onInit` in order to know when the related worker
-    // is ready.
-    _onInit: function () {
-      this._initSymbiont();
-      self._widget._onWorkerReady();
-    },
-    _onContentScriptEvent: function () {
-      // Redirect events to WidgetView
-      self._widget._onPortEvent(arguments);
-    }
-  })({
-    frame: iframe,
-    contentURL: contentURL,
-    contentScriptFile: this._widget.contentScriptFile,
-    contentScript: this._widget.contentScript,
-    contentScriptWhen: this._widget.contentScriptWhen,
-    contentScriptOptions: this._widget.contentScriptOptions,
-    allow: this._widget.allow,
-    onMessage: function(message) {
-      setTimeout(function() {
-        self._widget._onEvent("message", message);
-      }, 0);
-    }
-  });
-}
-
-// Detect if document consists of a single image.
-WidgetChrome._isImageDoc = function WC__isImageDoc(doc) {
-  return /*doc.body &&*/ doc.body.childNodes.length == 1 &&
-         doc.body.firstElementChild &&
-         doc.body.firstElementChild.tagName == "IMG";
-}
-
-// Set up all supported events for a widget.
-WidgetChrome.prototype.addEventHandlers = function WC_addEventHandlers() {
-  let contentType = this.getContentType();
-
-  let self = this;
-  let listener = function(e) {
-    // Ignore event firings that target the iframe.
-    if (e.target == self.node.firstElementChild)
-      return;
-
-    // The widget only supports left-click for now,
-    // so ignore all clicks (i.e. middle or right) except left ones.
-    if (e.type == "click" && e.button !== 0)
-      return;
-
-    // Proxy event to the widget
-    setTimeout(function() {
-      self._widget._onEvent(EVENTS[e.type], null, self.node);
-    }, 0);
-  };
-
-  this.eventListeners = {};
-  let iframe = this.node.firstElementChild;
-  for (let type in EVENTS) {
-    iframe.addEventListener(type, listener, true, true);
-
-    // Store listeners for later removal
-    this.eventListeners[type] = listener;
-  }
-
-  // On document load, make modifications required for nice default
-  // presentation.
-  function loadListener(e) {
-    let containerStyle = self.window.getComputedStyle(self.node.parentNode);
-    // Ignore event firings that target the iframe
-    if (e.target == iframe)
-      return;
-    // Ignore about:blank loads
-    if (e.type == "load" && e.target.location == "about:blank")
-      return;
-
-    // We may have had an unload event before that cleaned up the symbiont
-    if (!self._symbiont)
-      self.setContent();
-
-    let doc = e.target;
-
-    if (contentType == CONTENT_TYPE_IMAGE || WidgetChrome._isImageDoc(doc)) {
-      // Force image content to size.
-      // Add-on authors must size their images correctly.
-      doc.body.firstElementChild.style.width = self._widget.width + "px";
-      doc.body.firstElementChild.style.height = "16px";
-    }
-
-    // Extend the add-on bar's default text styles to the widget.
-    doc.body.style.color = containerStyle.color;
-    doc.body.style.fontFamily = containerStyle.fontFamily;
-    doc.body.style.fontSize = containerStyle.fontSize;
-    doc.body.style.fontWeight = containerStyle.fontWeight;
-    doc.body.style.textShadow = containerStyle.textShadow;
-    // Allow all content to fill the box by default.
-    doc.body.style.margin = "0";
-  }
-
-  iframe.addEventListener("load", loadListener, true);
-  this.eventListeners["load"] = loadListener;
-
-  // Register a listener to unload symbiont if the toolbaritem is moved
-  // on user toolbars customization
-  function unloadListener(e) {
-    if (e.target.location == "about:blank")
-      return;
-    self._symbiont.destroy();
-    self._symbiont = null;
-    // This may fail but not always, it depends on how the node is
-    // moved or removed
-    try {
-      self.setContent();
-    } catch(e) {}
-
-  }
-
-  iframe.addEventListener("unload", unloadListener, true);
-  this.eventListeners["unload"] = unloadListener;
-}
-
-// Remove and unregister the widget from everything
-WidgetChrome.prototype.destroy = function WC_destroy(removedItems) {
-  // remove event listeners
-  for (let type in this.eventListeners) {
-    let listener = this.eventListeners[type];
-    this.node.firstElementChild.removeEventListener(type, listener, true);
-  }
-  // remove dom node
-  this.node.parentNode.removeChild(this.node);
-  // cleanup symbiont
-  this._symbiont.destroy();
-  // cleanup itself
-  this.eventListeners = null;
-  this._widget = null;
-  this._symbiont = null;
-}
-
-// Init the browserManager only after setting prototypes and such above, because
-// it will cause browserManager.onTrack to be called immediately if there are
-// open windows.
-browserManager.init();
--- a/addon-sdk/source/lib/sdk/window/helpers.js
+++ b/addon-sdk/source/lib/sdk/window/helpers.js
@@ -1,21 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const { defer } = require('../core/promise');
+const { defer, all } = require('../core/promise');
 const events = require('../system/events');
 const { open: openWindow, onFocus, getToplevelWindow,
         isInteractive, getOuterId } = require('./utils');
 const { Ci } = require("chrome");
 
 function open(uri, options) {
-  return promise(openWindow.apply(null, arguments), 'load');
+  return promise(openWindow.apply(null, arguments), 'load').then(focus);
 }
 exports.open = open;
 
 function close(window) {
   let deferred = defer();
   let toplevelWindow = getToplevelWindow(window);
   let outerId = getOuterId(toplevelWindow);
   events.on("outer-window-destroyed", function onclose({subject}) {
--- a/addon-sdk/source/lib/sdk/window/utils.js
+++ b/addon-sdk/source/lib/sdk/window/utils.js
@@ -159,17 +159,17 @@ exports.isTopLevel = isTopLevel;
  * can be used passed to `window.open`. For more details on features string see:
  * https://developer.mozilla.org/en/DOM/window.open#Position_and_size_features
  */
 function serializeFeatures(options) {
   return Object.keys(options).reduce(function(result, name) {
     let value = options[name];
 
     // the chrome and private features are special
-    if ((name == 'private' || name == 'chrome'))
+    if ((name == 'private' || name == 'chrome' || name == 'all'))
       return result + ((value === true) ? ',' + name : '');
 
     return result + ',' + name + '=' +
            (value === true ? 'yes' : value === false ? 'no' : value);
   }, '').substr(1);
 }
 
 /**
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/windows/dom.js
+++ /dev/null
@@ -1,29 +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 { Trait } = require('../deprecated/traits');
-const { getWindowTitle } = require('../window/utils');
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const WindowDom = Trait.compose({
-  _window: Trait.required,
-  get title() {
-    return getWindowTitle(this._window);
-  },
-  close: function close() {
-    let window = this._window;
-    if (window) window.close();
-    return this._public;
-  },
-  activate: function activate() {
-    let window = this._window;
-    if (window) window.focus();
-    return this._public;
-  }
-});
-exports.WindowDom = WindowDom;
--- a/addon-sdk/source/lib/sdk/windows/fennec.js
+++ b/addon-sdk/source/lib/sdk/windows/fennec.js
@@ -46,17 +46,17 @@ function getRegisteredWindow(chromeWindo
   }
 
   return null;
 }
 
 /**
  * Gets a `BrowserWindow` for the provided window options obj
  * @params {Object} options
- *    Options that are passed to the the `BrowserWindowTrait`
+ *    Options that are passed to the the `BrowserWindow`
  * @returns {BrowserWindow}
  */
 function getBrowserWindow(options) {
   let window = null;
 
   // if we have a BrowserWindow already then use it
   if ('window' in options)
     window = getRegisteredWindow(options.window);
--- a/addon-sdk/source/lib/sdk/windows/firefox.js
+++ b/addon-sdk/source/lib/sdk/windows/firefox.js
@@ -1,356 +1,222 @@
 /* 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';
+"use strict";
 
-const { Cc, Ci, Cr } = require('chrome'),
-      { Trait } = require('../deprecated/traits'),
-      { List } = require('../deprecated/list'),
-      { EventEmitter } = require('../deprecated/events'),
-      { WindowTabs, WindowTabTracker } = require('./tabs-firefox'),
-      { WindowDom } = require('./dom'),
-      { isBrowser, getWindowDocShell, isFocused,
-        windows: windowIterator, isWindowPrivate } = require('../window/utils'),
-      { Options } = require('../tabs/common'),
-      apiUtils = require('../deprecated/api-utils'),
-      unload = require('../system/unload'),
-      windowUtils = require('../deprecated/window-utils'),
-      { WindowTrackerTrait } = windowUtils,
-      { ns } = require('../core/namespace'),
-      { observer: windowObserver } = require('./observer');
-const { windowNS } = require('../window/namespace');
-const { isPrivateBrowsingSupported } = require('../self');
-const { ignoreWindow, isPrivate } = require('sdk/private-browsing/utils');
+const { Class } = require('../core/heritage');
+const { observer } = require('./observer');
+const { isBrowser, getMostRecentBrowserWindow, windows, open, getInnerId,
+        getWindowTitle, isFocused, isWindowPrivate } = require('../window/utils');
+const { List, addListItem, removeListItem } = require('../util/list');
 const { viewFor } = require('../view/core');
-const { openDialog } = require('../window/utils');
-const ON_LOAD = 'load',
-      ON_UNLOAD = 'unload',
-      STATE_LOADED = 'complete';
-/**
- * Window trait composes safe wrappers for browser window that are E10S
- * compatible.
- */
-const BrowserWindowTrait = Trait.compose(
-  EventEmitter,
-  WindowDom.resolve({ close: '_close' }),
-  WindowTabs,
-  WindowTabTracker,
-  /* WindowSidebars, */
-  Trait.compose({
-    _emit: Trait.required,
-    _close: Trait.required,
-    /**
-     * Private window who's load event is being tracked. Once window is loaded
-     * `_onLoad` is called.
-     * @type {nsIWindow}
-     */
-    get _window() this.__window,
-    set _window(window) {
-      let _window = this.__window;
-      if (!window) window = null;
+const { modelFor } = require('../model/core');
+const { emit, emitOnObject, setListeners } = require('../event/core');
+const { once } = require('../dom/events');
+const { EventTarget } = require('../event/target');
+const { getSelectedTab } = require('../tabs/utils');
+const { Cc, Ci } = require('chrome');
+const { Options } = require('../tabs/common');
+const system = require('../system/events');
+const { ignoreWindow, isPrivate, isWindowPBSupported } = require('../private-browsing/utils');
+const { data, isPrivateBrowsingSupported } = require('../self');
+const { setImmediate } = require('../timers');