#yolo draft
authorsole <spenades@mozilla.com>
Wed, 06 Sep 2017 18:25:03 +0100
changeset 660802 0efe5af2dc49c5ce45f667ca3764d61c0cef6efb
parent 660801 0aa60b70d7b8c4ed23fae88e9cd0146e73103a93
child 660803 67ef84062f72a99cde1600655e33a5a2d95c0ad0
push id78541
push userbmo:spenades@mozilla.com
push dateThu, 07 Sep 2017 15:29:11 +0000
milestone57.0a1
#yolo
addon-sdk/Makefile.in
addon-sdk/moz.build
addon-sdk/source/.gitattributes
addon-sdk/source/.gitignore
addon-sdk/source/.hgignore
addon-sdk/source/.hgtags
addon-sdk/source/.jpmignore
addon-sdk/source/.travis.yml
addon-sdk/source/CONTRIBUTING.md
addon-sdk/source/LICENSE
addon-sdk/source/README.md
addon-sdk/source/app-extension/application.ini
addon-sdk/source/app-extension/bootstrap.js
addon-sdk/source/app-extension/install.rdf
addon-sdk/source/bin/activate
addon-sdk/source/bin/activate.bat
addon-sdk/source/bin/activate.fish
addon-sdk/source/bin/activate.ps1
addon-sdk/source/bin/cfx
addon-sdk/source/bin/cfx.bat
addon-sdk/source/bin/deactivate.bat
addon-sdk/source/bin/fx-download.sh
addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper
addon-sdk/source/bin/integration-scripts/integration-check
addon-sdk/source/bin/jpm-test.js
addon-sdk/source/bin/node-scripts/apply-patch.js
addon-sdk/source/bin/node-scripts/test.addons.js
addon-sdk/source/bin/node-scripts/test.docs.js
addon-sdk/source/bin/node-scripts/test.examples.js
addon-sdk/source/bin/node-scripts/test.firefox-bin.js
addon-sdk/source/bin/node-scripts/test.ini.js
addon-sdk/source/bin/node-scripts/test.modules.js
addon-sdk/source/bin/node-scripts/update-ini.js
addon-sdk/source/bin/node-scripts/utils.js
addon-sdk/source/bin/node-scripts/words.txt
addon-sdk/source/examples/actor-repl/README.md
addon-sdk/source/examples/actor-repl/data/codemirror-compressed.js
addon-sdk/source/examples/actor-repl/data/codemirror.css
addon-sdk/source/examples/actor-repl/data/index.html
addon-sdk/source/examples/actor-repl/data/main.css
addon-sdk/source/examples/actor-repl/data/robot.png
addon-sdk/source/examples/actor-repl/index.js
addon-sdk/source/examples/actor-repl/package.json
addon-sdk/source/examples/actor-repl/test/test-main.js
addon-sdk/source/examples/debug-client/data/client.js
addon-sdk/source/examples/debug-client/data/index.html
addon-sdk/source/examples/debug-client/data/plugin.png
addon-sdk/source/examples/debug-client/data/task.js
addon-sdk/source/examples/debug-client/index.js
addon-sdk/source/examples/debug-client/package.json
addon-sdk/source/examples/debug-client/test/test-main.js
addon-sdk/source/examples/reading-data/data/mom.png
addon-sdk/source/examples/reading-data/data/sample.html
addon-sdk/source/examples/reading-data/lib/main.js
addon-sdk/source/examples/reading-data/package.json
addon-sdk/source/examples/reading-data/tests/test-main.js
addon-sdk/source/examples/theme/data/icon-16.png
addon-sdk/source/examples/theme/data/index.html
addon-sdk/source/examples/theme/data/theme.css
addon-sdk/source/examples/theme/lib/main.js
addon-sdk/source/examples/theme/package.json
addon-sdk/source/examples/theme/test/test-main.js
addon-sdk/source/examples/toolbar-api/data/favicon.ico
addon-sdk/source/examples/toolbar-api/data/index.html
addon-sdk/source/examples/toolbar-api/lib/main.js
addon-sdk/source/examples/toolbar-api/package.json
addon-sdk/source/examples/toolbar-api/test/test-main.js
addon-sdk/source/examples/ui-button-apis/lib/main.js
addon-sdk/source/examples/ui-button-apis/package.json
addon-sdk/source/examples/ui-button-apis/tests/test-main.js
addon-sdk/source/gulpfile.js
addon-sdk/source/lib/diffpatcher/.travis.yml
addon-sdk/source/lib/diffpatcher/History.md
addon-sdk/source/lib/diffpatcher/License.md
addon-sdk/source/lib/diffpatcher/Readme.md
addon-sdk/source/lib/diffpatcher/package.json
addon-sdk/source/lib/index.js
addon-sdk/source/lib/jetpack-id/index.js
addon-sdk/source/lib/jetpack-id/package.json
addon-sdk/source/lib/method/.travis.yml
addon-sdk/source/lib/method/History.md
addon-sdk/source/lib/method/License.md
addon-sdk/source/lib/method/Readme.md
addon-sdk/source/lib/method/core.js
addon-sdk/source/lib/method/package.json
addon-sdk/source/lib/mozilla-toolkit-versioning/index.js
addon-sdk/source/lib/mozilla-toolkit-versioning/lib/utils.js
addon-sdk/source/lib/mozilla-toolkit-versioning/package.json
addon-sdk/source/lib/node/os.js
addon-sdk/source/lib/sdk/addon/installer.js
addon-sdk/source/lib/sdk/addon/window.js
addon-sdk/source/lib/sdk/base64.js
addon-sdk/source/lib/sdk/console/traceback.js
addon-sdk/source/lib/sdk/core/disposable.js
addon-sdk/source/lib/sdk/core/namespace.js
addon-sdk/source/lib/sdk/core/observer.js
addon-sdk/source/lib/sdk/core/promise.js
addon-sdk/source/lib/sdk/core/reference.js
addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js
addon-sdk/source/lib/sdk/deprecated/unit-test.js
addon-sdk/source/lib/sdk/deprecated/window-utils.js
addon-sdk/source/lib/sdk/event/chrome.js
addon-sdk/source/lib/sdk/event/core.js
addon-sdk/source/lib/sdk/event/dom.js
addon-sdk/source/lib/sdk/event/target.js
addon-sdk/source/lib/sdk/event/utils.js
addon-sdk/source/lib/sdk/frame/utils.js
addon-sdk/source/lib/sdk/io/file.js
addon-sdk/source/lib/sdk/lang/functional.js
addon-sdk/source/lib/sdk/lang/functional/concurrent.js
addon-sdk/source/lib/sdk/lang/functional/core.js
addon-sdk/source/lib/sdk/lang/functional/helpers.js
addon-sdk/source/lib/sdk/lang/type.js
addon-sdk/source/lib/sdk/lang/weak-set.js
addon-sdk/source/lib/sdk/net/url.js
addon-sdk/source/lib/sdk/platform/xpcom.js
addon-sdk/source/lib/sdk/preferences/service.js
addon-sdk/source/lib/sdk/preferences/utils.js
addon-sdk/source/lib/sdk/private-browsing.js
addon-sdk/source/lib/sdk/private-browsing/utils.js
addon-sdk/source/lib/sdk/querystring.js
addon-sdk/source/lib/sdk/self.js
addon-sdk/source/lib/sdk/system.js
addon-sdk/source/lib/sdk/system/environment.js
addon-sdk/source/lib/sdk/system/events.js
addon-sdk/source/lib/sdk/system/globals.js
addon-sdk/source/lib/sdk/system/process.js
addon-sdk/source/lib/sdk/system/runtime.js
addon-sdk/source/lib/sdk/system/unload.js
addon-sdk/source/lib/sdk/system/xul-app.js
addon-sdk/source/lib/sdk/system/xul-app.jsm
addon-sdk/source/lib/sdk/test.js
addon-sdk/source/lib/sdk/test/assert.js
addon-sdk/source/lib/sdk/test/harness.js
addon-sdk/source/lib/sdk/test/loader.js
addon-sdk/source/lib/sdk/test/options.js
addon-sdk/source/lib/sdk/test/utils.js
addon-sdk/source/lib/sdk/timers.js
addon-sdk/source/lib/sdk/uri/resource.js
addon-sdk/source/lib/sdk/url.js
addon-sdk/source/lib/sdk/url/utils.js
addon-sdk/source/lib/sdk/util/array.js
addon-sdk/source/lib/sdk/util/collection.js
addon-sdk/source/lib/sdk/util/deprecate.js
addon-sdk/source/lib/sdk/util/dispatcher.js
addon-sdk/source/lib/sdk/util/list.js
addon-sdk/source/lib/sdk/util/object.js
addon-sdk/source/lib/sdk/util/sequence.js
addon-sdk/source/lib/sdk/util/uuid.js
addon-sdk/source/lib/sdk/window/utils.js
addon-sdk/source/lib/sdk/zip/utils.js
addon-sdk/source/lib/test.js
addon-sdk/source/lib/toolkit/loader.js
addon-sdk/source/lib/toolkit/require.js
addon-sdk/source/mapping.json
addon-sdk/source/modules/system/Startup.js
addon-sdk/source/modules/system/moz.build
addon-sdk/source/package.json
addon-sdk/source/python-lib/cuddlefish/__init__.py
addon-sdk/source/python-lib/cuddlefish/_version.py
addon-sdk/source/python-lib/cuddlefish/bunch.py
addon-sdk/source/python-lib/cuddlefish/manifest.py
addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js
addon-sdk/source/python-lib/cuddlefish/mobile-utils/install.rdf
addon-sdk/source/python-lib/cuddlefish/packaging.py
addon-sdk/source/python-lib/cuddlefish/preflight.py
addon-sdk/source/python-lib/cuddlefish/prefs.py
addon-sdk/source/python-lib/cuddlefish/property_parser.py
addon-sdk/source/python-lib/cuddlefish/rdf.py
addon-sdk/source/python-lib/cuddlefish/runner.py
addon-sdk/source/python-lib/cuddlefish/templates.py
addon-sdk/source/python-lib/cuddlefish/tests/__init__.py
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon.png
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon64.png
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon.png
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon64.png
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/lib/bar-loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/lib/foo-loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/docs/main.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/doc/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/lib/foo-loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/test/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/docs/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/lib/foo-loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/tests/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/doc/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/test/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/locale/emptyFolder
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/doc/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/test/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/doc/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/test/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/loader.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/doc/foo.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/test/test-foo.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/docs/main.md
addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json
addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar-e10s-adapter.js
addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar.js
addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/lib/misc.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/topfiles/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/subdir/three.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/two.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/data/text.data
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/unused.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/lib/unused.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/unreachable.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/subdir/subfile.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/unused.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/locale/fr-FR.properties
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/locale/fr-FR.properties
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/sub/foo.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/locale/fr-FR.properties
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/msg.txt
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/subdir/submsg.txt
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/package.json
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/nontest.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-one.js
addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-two.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/doc/main.md
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/ignore_me
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/surprise.js/ignore_me_too
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/lib/loader.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/lib/bar-module.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/lib/main.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/docs/third_party.md
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/lib/third-party.js
addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/package.json
addon-sdk/source/python-lib/cuddlefish/tests/static-files/xpi-template/components/harness.js
addon-sdk/source/python-lib/cuddlefish/tests/test_init.py
addon-sdk/source/python-lib/cuddlefish/tests/test_licenses.py
addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
addon-sdk/source/python-lib/cuddlefish/tests/test_manifest.py
addon-sdk/source/python-lib/cuddlefish/tests/test_packaging.py
addon-sdk/source/python-lib/cuddlefish/tests/test_preflight.py
addon-sdk/source/python-lib/cuddlefish/tests/test_property_parser.py
addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py
addon-sdk/source/python-lib/cuddlefish/tests/test_runner.py
addon-sdk/source/python-lib/cuddlefish/tests/test_util.py
addon-sdk/source/python-lib/cuddlefish/tests/test_version.py
addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py
addon-sdk/source/python-lib/cuddlefish/util.py
addon-sdk/source/python-lib/cuddlefish/version_comparator.py
addon-sdk/source/python-lib/cuddlefish/xpi.py
addon-sdk/source/python-lib/jetpack_sdk_env.py
addon-sdk/source/python-lib/mozrunner/__init__.py
addon-sdk/source/python-lib/mozrunner/killableprocess.py
addon-sdk/source/python-lib/mozrunner/qijo.py
addon-sdk/source/python-lib/mozrunner/winprocess.py
addon-sdk/source/python-lib/mozrunner/wpk.py
addon-sdk/source/python-lib/plural-rules-generator.py
addon-sdk/source/python-lib/simplejson/LICENSE.txt
addon-sdk/source/python-lib/simplejson/__init__.py
addon-sdk/source/python-lib/simplejson/decoder.py
addon-sdk/source/python-lib/simplejson/encoder.py
addon-sdk/source/python-lib/simplejson/scanner.py
addon-sdk/source/python-lib/simplejson/tool.py
addon-sdk/source/test/addons/addon-manager/lib/main.js
addon-sdk/source/test/addons/addon-manager/lib/test-main.js
addon-sdk/source/test/addons/addon-manager/package.json
addon-sdk/source/test/addons/author-email/main.js
addon-sdk/source/test/addons/author-email/package.json
addon-sdk/source/test/addons/child_process/index.js
addon-sdk/source/test/addons/child_process/package.json
addon-sdk/source/test/addons/chrome/chrome.manifest
addon-sdk/source/test/addons/chrome/chrome/content/new-window.xul
addon-sdk/source/test/addons/chrome/chrome/content/panel.html
addon-sdk/source/test/addons/chrome/chrome/locale/en-US/description.properties
addon-sdk/source/test/addons/chrome/chrome/locale/ja-JP/description.properties
addon-sdk/source/test/addons/chrome/chrome/skin/style.css
addon-sdk/source/test/addons/chrome/data/panel.js
addon-sdk/source/test/addons/chrome/main.js
addon-sdk/source/test/addons/chrome/package.json
addon-sdk/source/test/addons/content-permissions/httpd.js
addon-sdk/source/test/addons/content-permissions/main.js
addon-sdk/source/test/addons/content-permissions/package.json
addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
addon-sdk/source/test/addons/content-script-messages-latency/main.js
addon-sdk/source/test/addons/content-script-messages-latency/package.json
addon-sdk/source/test/addons/contributors/main.js
addon-sdk/source/test/addons/contributors/package.json
addon-sdk/source/test/addons/curly-id/lib/main.js
addon-sdk/source/test/addons/curly-id/package.json
addon-sdk/source/test/addons/developers/main.js
addon-sdk/source/test/addons/developers/package.json
addon-sdk/source/test/addons/e10s-content/data/test-contentScriptFile.js
addon-sdk/source/test/addons/e10s-content/data/test-page-worker.html
addon-sdk/source/test/addons/e10s-content/data/test-page-worker.js
addon-sdk/source/test/addons/e10s-content/data/test.html
addon-sdk/source/test/addons/e10s-content/lib/fixtures.js
addon-sdk/source/test/addons/e10s-content/lib/httpd.js
addon-sdk/source/test/addons/e10s-content/lib/main.js
addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js
addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js
addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
addon-sdk/source/test/addons/e10s-content/package.json
addon-sdk/source/test/addons/e10s-l10n/data/test-localization.html
addon-sdk/source/test/addons/e10s-l10n/locale/en.properties
addon-sdk/source/test/addons/e10s-l10n/locale/eo.properties
addon-sdk/source/test/addons/e10s-l10n/locale/fr-FR.properties
addon-sdk/source/test/addons/e10s-l10n/main.js
addon-sdk/source/test/addons/e10s-l10n/package.json
addon-sdk/source/test/addons/e10s-remote/main.js
addon-sdk/source/test/addons/e10s-remote/package.json
addon-sdk/source/test/addons/e10s-remote/remote-module.js
addon-sdk/source/test/addons/e10s-remote/utils.js
addon-sdk/source/test/addons/e10s-tabs/lib/main.js
addon-sdk/source/test/addons/e10s-tabs/lib/private-browsing/helper.js
addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-events.js
addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-observer.js
addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-utils.js
addon-sdk/source/test/addons/e10s-tabs/lib/test-tab.js
addon-sdk/source/test/addons/e10s-tabs/package.json
addon-sdk/source/test/addons/e10s/lib/main.js
addon-sdk/source/test/addons/e10s/package.json
addon-sdk/source/test/addons/embedded-webextension/main.js
addon-sdk/source/test/addons/embedded-webextension/package.json
addon-sdk/source/test/addons/embedded-webextension/webextension/background-page.js
addon-sdk/source/test/addons/embedded-webextension/webextension/content-script.js
addon-sdk/source/test/addons/embedded-webextension/webextension/manifest.json
addon-sdk/source/test/addons/jetpack-addon.ini
addon-sdk/source/test/addons/l10n-properties/app-extension/application.ini
addon-sdk/source/test/addons/l10n-properties/app-extension/bootstrap.js
addon-sdk/source/test/addons/l10n-properties/app-extension/install.rdf
addon-sdk/source/test/addons/l10n-properties/app-extension/locale/en-GB.properties
addon-sdk/source/test/addons/l10n-properties/app-extension/locale/en-US.properties
addon-sdk/source/test/addons/l10n-properties/app-extension/locale/eo.properties
addon-sdk/source/test/addons/l10n-properties/app-extension/locale/fr-FR.properties
addon-sdk/source/test/addons/l10n-properties/data/test-localization.html
addon-sdk/source/test/addons/l10n-properties/main.js
addon-sdk/source/test/addons/l10n-properties/package.json
addon-sdk/source/test/addons/l10n/data/test-localization.html
addon-sdk/source/test/addons/l10n/locale/en.properties
addon-sdk/source/test/addons/l10n/locale/eo.properties
addon-sdk/source/test/addons/l10n/locale/fr-FR.properties
addon-sdk/source/test/addons/l10n/main.js
addon-sdk/source/test/addons/l10n/package.json
addon-sdk/source/test/addons/layout-change/lib/main.js
addon-sdk/source/test/addons/layout-change/lib/test-cuddlefish-loader.js
addon-sdk/source/test/addons/layout-change/lib/test-toolkit-loader.js
addon-sdk/source/test/addons/layout-change/package.json
addon-sdk/source/test/addons/main/main.js
addon-sdk/source/test/addons/main/package.json
addon-sdk/source/test/addons/name-in-numbers-plus/index.js
addon-sdk/source/test/addons/name-in-numbers-plus/package.json
addon-sdk/source/test/addons/name-in-numbers/index.js
addon-sdk/source/test/addons/name-in-numbers/package.json
addon-sdk/source/test/addons/packaging/main.js
addon-sdk/source/test/addons/packaging/package.json
addon-sdk/source/test/addons/packed/main.js
addon-sdk/source/test/addons/packed/package.json
addon-sdk/source/test/addons/page-mod-debugger-post/data/index.html
addon-sdk/source/test/addons/page-mod-debugger-post/data/script.js
addon-sdk/source/test/addons/page-mod-debugger-post/main.js
addon-sdk/source/test/addons/page-mod-debugger-post/package.json
addon-sdk/source/test/addons/page-mod-debugger-pre/data/index.html
addon-sdk/source/test/addons/page-mod-debugger-pre/data/script.js
addon-sdk/source/test/addons/page-mod-debugger-pre/main.js
addon-sdk/source/test/addons/page-mod-debugger-pre/package.json
addon-sdk/source/test/addons/page-worker/data/page.html
addon-sdk/source/test/addons/page-worker/data/page.js
addon-sdk/source/test/addons/page-worker/main.js
addon-sdk/source/test/addons/page-worker/package.json
addon-sdk/source/test/addons/places/lib/favicon-helpers.js
addon-sdk/source/test/addons/places/lib/httpd.js
addon-sdk/source/test/addons/places/lib/main.js
addon-sdk/source/test/addons/places/lib/places-helper.js
addon-sdk/source/test/addons/places/lib/test-places-bookmarks.js
addon-sdk/source/test/addons/places/lib/test-places-events.js
addon-sdk/source/test/addons/places/lib/test-places-favicon.js
addon-sdk/source/test/addons/places/lib/test-places-history.js
addon-sdk/source/test/addons/places/lib/test-places-host.js
addon-sdk/source/test/addons/places/lib/test-places-utils.js
addon-sdk/source/test/addons/places/package.json
addon-sdk/source/test/addons/predefined-id-with-at/lib/main.js
addon-sdk/source/test/addons/predefined-id-with-at/package.json
addon-sdk/source/test/addons/preferences-branch/lib/main.js
addon-sdk/source/test/addons/preferences-branch/package.json
addon-sdk/source/test/addons/private-browsing-supported/main.js
addon-sdk/source/test/addons/private-browsing-supported/package.json
addon-sdk/source/test/addons/private-browsing-supported/sidebar/utils.js
addon-sdk/source/test/addons/private-browsing-supported/test-page-mod.js
addon-sdk/source/test/addons/private-browsing-supported/test-panel.js
addon-sdk/source/test/addons/private-browsing-supported/test-private-browsing.js
addon-sdk/source/test/addons/private-browsing-supported/test-selection.js
addon-sdk/source/test/addons/private-browsing-supported/test-sidebar.js
addon-sdk/source/test/addons/private-browsing-supported/test-tabs.js
addon-sdk/source/test/addons/private-browsing-supported/test-window-tabs.js
addon-sdk/source/test/addons/private-browsing-supported/test-windows.js
addon-sdk/source/test/addons/remote/main.js
addon-sdk/source/test/addons/remote/package.json
addon-sdk/source/test/addons/remote/remote-module.js
addon-sdk/source/test/addons/remote/utils.js
addon-sdk/source/test/addons/require/list.js
addon-sdk/source/test/addons/require/main.js
addon-sdk/source/test/addons/require/multiple/a.js
addon-sdk/source/test/addons/require/multiple/b.js
addon-sdk/source/test/addons/require/package.json
addon-sdk/source/test/addons/require/packages/tabs/main.js
addon-sdk/source/test/addons/require/packages/tabs/package.json
addon-sdk/source/test/addons/require/packages/tabs/page-mod.js
addon-sdk/source/test/addons/require/same-folder.js
addon-sdk/source/test/addons/require/sub-folder/module.js
addon-sdk/source/test/addons/require/tabs.js
addon-sdk/source/test/addons/self/data/data.md
addon-sdk/source/test/addons/self/main.js
addon-sdk/source/test/addons/self/package.json
addon-sdk/source/test/addons/simple-prefs-l10n/locale/en.properties
addon-sdk/source/test/addons/simple-prefs-l10n/main.js
addon-sdk/source/test/addons/simple-prefs-l10n/package.json
addon-sdk/source/test/addons/simple-prefs-regression/app-extension/application.ini
addon-sdk/source/test/addons/simple-prefs-regression/app-extension/bootstrap.js
addon-sdk/source/test/addons/simple-prefs-regression/app-extension/defaults/preferences/prefs.js
addon-sdk/source/test/addons/simple-prefs-regression/app-extension/install.rdf
addon-sdk/source/test/addons/simple-prefs-regression/app-extension/options.xul
addon-sdk/source/test/addons/simple-prefs-regression/lib/main.js
addon-sdk/source/test/addons/simple-prefs-regression/package.json
addon-sdk/source/test/addons/simple-prefs/lib/main.js
addon-sdk/source/test/addons/simple-prefs/package.json
addon-sdk/source/test/addons/standard-id/lib/main.js
addon-sdk/source/test/addons/standard-id/package.json
addon-sdk/source/test/addons/tab-close-on-startup/main.js
addon-sdk/source/test/addons/tab-close-on-startup/package.json
addon-sdk/source/test/addons/toolkit-require-reload/main.js
addon-sdk/source/test/addons/toolkit-require-reload/package.json
addon-sdk/source/test/addons/translators/main.js
addon-sdk/source/test/addons/translators/package.json
addon-sdk/source/test/addons/unsafe-content-script/main.js
addon-sdk/source/test/addons/unsafe-content-script/package.json
addon-sdk/source/test/buffers/test-read-types.js
addon-sdk/source/test/buffers/test-write-types.js
addon-sdk/source/test/commonjs-test-adapter/asserts.js
addon-sdk/source/test/context-menu/framescript.js
addon-sdk/source/test/context-menu/test-helper.js
addon-sdk/source/test/context-menu/util.js
addon-sdk/source/test/event/helpers.js
addon-sdk/source/test/fixtures.js
addon-sdk/source/test/fixtures/addon-install-unit-test@mozilla.com.xpi
addon-sdk/source/test/fixtures/addon-sdk/data/border-style.css
addon-sdk/source/test/fixtures/addon-sdk/data/test-contentScriptFile.js
addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.html
addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.js
addon-sdk/source/test/fixtures/addon-sdk/data/test.html
addon-sdk/source/test/fixtures/addon/bootstrap.js
addon-sdk/source/test/fixtures/addon/index.js
addon-sdk/source/test/fixtures/addon/package.json
addon-sdk/source/test/fixtures/bootstrap-addon/META-INF/manifest.mf
addon-sdk/source/test/fixtures/bootstrap-addon/META-INF/mozilla.rsa
addon-sdk/source/test/fixtures/bootstrap-addon/META-INF/mozilla.sf
addon-sdk/source/test/fixtures/bootstrap-addon/bootstrap.js
addon-sdk/source/test/fixtures/bootstrap-addon/install.rdf
addon-sdk/source/test/fixtures/bootstrap-addon/options.xul
addon-sdk/source/test/fixtures/bootstrap/utils.js
addon-sdk/source/test/fixtures/border-style.css
addon-sdk/source/test/fixtures/child-process-scripts.js
addon-sdk/source/test/fixtures/chrome-worker/addEventListener.js
addon-sdk/source/test/fixtures/chrome-worker/jsctypes.js
addon-sdk/source/test/fixtures/chrome-worker/onerror.js
addon-sdk/source/test/fixtures/chrome-worker/onmessage.js
addon-sdk/source/test/fixtures/chrome-worker/setTimeout.js
addon-sdk/source/test/fixtures/chrome-worker/xhr.js
addon-sdk/source/test/fixtures/create_xpi.py
addon-sdk/source/test/fixtures/es5.js
addon-sdk/source/test/fixtures/include-file.css
addon-sdk/source/test/fixtures/index.html
addon-sdk/source/test/fixtures/jsm-package/Test.jsm
addon-sdk/source/test/fixtures/jsm-package/index.js
addon-sdk/source/test/fixtures/jsm-package/package.json
addon-sdk/source/test/fixtures/loader/cycles/a.js
addon-sdk/source/test/fixtures/loader/cycles/b.js
addon-sdk/source/test/fixtures/loader/cycles/c.js
addon-sdk/source/test/fixtures/loader/cycles/main.js
addon-sdk/source/test/fixtures/loader/errors/boomer.js
addon-sdk/source/test/fixtures/loader/errors/main.js
addon-sdk/source/test/fixtures/loader/exceptions/boomer.js
addon-sdk/source/test/fixtures/loader/exceptions/main.js
addon-sdk/source/test/fixtures/loader/globals/main.js
addon-sdk/source/test/fixtures/loader/json/invalid.json
addon-sdk/source/test/fixtures/loader/json/manifest.json
addon-sdk/source/test/fixtures/loader/json/mutation.json
addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
addon-sdk/source/test/fixtures/loader/json/test.json
addon-sdk/source/test/fixtures/loader/json/test.json.js
addon-sdk/source/test/fixtures/loader/lazy/main.js
addon-sdk/source/test/fixtures/loader/missing-twice/file.json
addon-sdk/source/test/fixtures/loader/missing-twice/main.js
addon-sdk/source/test/fixtures/loader/missing/main.js
addon-sdk/source/test/fixtures/loader/self/main.js
addon-sdk/source/test/fixtures/loader/syntax-error/error.js
addon-sdk/source/test/fixtures/loader/syntax-error/main.js
addon-sdk/source/test/fixtures/loader/unsupported/fennec.js
addon-sdk/source/test/fixtures/loader/unsupported/firefox.js
addon-sdk/source/test/fixtures/mofo_logo.SVG
addon-sdk/source/test/fixtures/moz.build
addon-sdk/source/test/fixtures/moz_favicon.ico
addon-sdk/source/test/fixtures/native-addon-test/dir/a.js
addon-sdk/source/test/fixtures/native-addon-test/dir/a/index.js
addon-sdk/source/test/fixtures/native-addon-test/dir/b.js
addon-sdk/source/test/fixtures/native-addon-test/dir/c.js
addon-sdk/source/test/fixtures/native-addon-test/dir/dummy.js
addon-sdk/source/test/fixtures/native-addon-test/dir/test.jsm
addon-sdk/source/test/fixtures/native-addon-test/expectedmap.json
addon-sdk/source/test/fixtures/native-addon-test/index.js
addon-sdk/source/test/fixtures/native-addon-test/newmodule/index.js
addon-sdk/source/test/fixtures/native-addon-test/newmodule/lib/file.js
addon-sdk/source/test/fixtures/native-addon-test/newmodule/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/index.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/styles.css
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main-relative/lib/custom-entry.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main-relative/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main/lib/custom-entry.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-default-main/index.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-default-main/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/index.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/lib/sqrt.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-add/index.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-add/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-subtract/index.js
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-subtract/package.json
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/package.json
addon-sdk/source/test/fixtures/native-addon-test/package.json
addon-sdk/source/test/fixtures/native-addon-test/utils/index.js
addon-sdk/source/test/fixtures/native-overrides-test/ignore.js
addon-sdk/source/test/fixtures/native-overrides-test/index.js
addon-sdk/source/test/fixtures/native-overrides-test/lib/ignore.js
addon-sdk/source/test/fixtures/native-overrides-test/lib/internal.js
addon-sdk/source/test/fixtures/native-overrides-test/lib/tabs.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/index.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/lib/tabs.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/package.json
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/index.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/lib/foo.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/node_modules/bar/index.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/node_modules/bar/package.json
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/package.json
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/fs-extra/index.js
addon-sdk/source/test/fixtures/native-overrides-test/node_modules/fs-extra/package.json
addon-sdk/source/test/fixtures/native-overrides-test/package.json
addon-sdk/source/test/fixtures/preferences/curly-id/package.json
addon-sdk/source/test/fixtures/preferences/no-prefs/package.json
addon-sdk/source/test/fixtures/preferences/preferences-branch/package.json
addon-sdk/source/test/fixtures/preferences/simple-prefs/package.json
addon-sdk/source/test/fixtures/sandbox-complex-character.js
addon-sdk/source/test/fixtures/sandbox-normal.js
addon-sdk/source/test/fixtures/test-addon-extras-window.html
addon-sdk/source/test/fixtures/test-addon-extras.html
addon-sdk/source/test/fixtures/test-contentScriptFile.js
addon-sdk/source/test/fixtures/test-context-menu.js
addon-sdk/source/test/fixtures/test-iframe-postmessage.html
addon-sdk/source/test/fixtures/test-iframe.html
addon-sdk/source/test/fixtures/test-iframe.js
addon-sdk/source/test/fixtures/test-message-manager.js
addon-sdk/source/test/fixtures/test-net-url.txt
addon-sdk/source/test/fixtures/test-page-mod.html
addon-sdk/source/test/fixtures/test-sidebar-addon-global.html
addon-sdk/source/test/fixtures/test-trusted-document.html
addon-sdk/source/test/fixtures/test.html
addon-sdk/source/test/fixtures/testLocalXhr.json
addon-sdk/source/test/framescript-manager/frame-script.js
addon-sdk/source/test/framescript-manager/pong.js
addon-sdk/source/test/framescript-util/frame-script.js
addon-sdk/source/test/jetpack-package.ini
addon-sdk/source/test/leak/jetpack-package.ini
addon-sdk/source/test/leak/leak-utils.js
addon-sdk/source/test/leak/test-leak-event-dom-closed-window.js
addon-sdk/source/test/leak/test-leak-tab-events.js
addon-sdk/source/test/leak/test-leak-window-events.js
addon-sdk/source/test/lib/httpd.js
addon-sdk/source/test/loader/b2g.js
addon-sdk/source/test/loader/fixture.js
addon-sdk/source/test/loader/user-global.js
addon-sdk/source/test/modules/add.js
addon-sdk/source/test/modules/async1.js
addon-sdk/source/test/modules/async2.js
addon-sdk/source/test/modules/badExportAndReturn.js
addon-sdk/source/test/modules/badFirst.js
addon-sdk/source/test/modules/badSecond.js
addon-sdk/source/test/modules/blue.js
addon-sdk/source/test/modules/castor.js
addon-sdk/source/test/modules/cheetah.js
addon-sdk/source/test/modules/color.js
addon-sdk/source/test/modules/dupe.js
addon-sdk/source/test/modules/dupeNested.js
addon-sdk/source/test/modules/dupeSetExports.js
addon-sdk/source/test/modules/exportsEquals.js
addon-sdk/source/test/modules/green.js
addon-sdk/source/test/modules/lion.js
addon-sdk/source/test/modules/orange.js
addon-sdk/source/test/modules/pollux.js
addon-sdk/source/test/modules/red.js
addon-sdk/source/test/modules/setExports.js
addon-sdk/source/test/modules/subtract.js
addon-sdk/source/test/modules/tiger.js
addon-sdk/source/test/modules/traditional1.js
addon-sdk/source/test/modules/traditional2.js
addon-sdk/source/test/modules/types/cat.js
addon-sdk/source/test/page-mod/helpers.js
addon-sdk/source/test/path/test-path.js
addon-sdk/source/test/preferences/common.json
addon-sdk/source/test/preferences/e10s-off.json
addon-sdk/source/test/preferences/e10s-on.json
addon-sdk/source/test/preferences/firefox.json
addon-sdk/source/test/preferences/no-connections.json
addon-sdk/source/test/preferences/test-e10s-preferences.js
addon-sdk/source/test/preferences/test-preferences.js
addon-sdk/source/test/preferences/test.json
addon-sdk/source/test/private-browsing/helper.js
addon-sdk/source/test/private-browsing/tabs.js
addon-sdk/source/test/private-browsing/windows.js
addon-sdk/source/test/querystring/test-querystring.js
addon-sdk/source/test/sidebar/utils.js
addon-sdk/source/test/tabs/test-fennec-tabs.js
addon-sdk/source/test/tabs/test-firefox-tabs.js
addon-sdk/source/test/tabs/utils.js
addon-sdk/source/test/test-addon-bootstrap.js
addon-sdk/source/test/test-addon-extras.js
addon-sdk/source/test/test-addon-installer.js
addon-sdk/source/test/test-addon-window.js
addon-sdk/source/test/test-api-utils.js
addon-sdk/source/test/test-array.js
addon-sdk/source/test/test-base64.js
addon-sdk/source/test/test-bootstrap.js
addon-sdk/source/test/test-browser-events.js
addon-sdk/source/test/test-buffer.js
addon-sdk/source/test/test-byte-streams.js
addon-sdk/source/test/test-child_process.js
addon-sdk/source/test/test-chrome.js
addon-sdk/source/test/test-clipboard.js
addon-sdk/source/test/test-collection.js
addon-sdk/source/test/test-commonjs-test-adapter.js
addon-sdk/source/test/test-content-events.js
addon-sdk/source/test/test-content-script.js
addon-sdk/source/test/test-content-sync-worker.js
addon-sdk/source/test/test-content-worker.js
addon-sdk/source/test/test-context-menu.html
addon-sdk/source/test/test-context-menu.js
addon-sdk/source/test/test-context-menu@2.js
addon-sdk/source/test/test-cuddlefish.js
addon-sdk/source/test/test-deprecate.js
addon-sdk/source/test/test-dev-panel.js
addon-sdk/source/test/test-diffpatcher.js
addon-sdk/source/test/test-dispatcher.js
addon-sdk/source/test/test-disposable.js
addon-sdk/source/test/test-dom.js
addon-sdk/source/test/test-environment.js
addon-sdk/source/test/test-event-core.js
addon-sdk/source/test/test-event-dom.js
addon-sdk/source/test/test-event-target.js
addon-sdk/source/test/test-event-utils.js
addon-sdk/source/test/test-file.js
addon-sdk/source/test/test-frame-utils.js
addon-sdk/source/test/test-framescript-manager.js
addon-sdk/source/test/test-framescript-util.js
addon-sdk/source/test/test-fs.js
addon-sdk/source/test/test-functional.js
addon-sdk/source/test/test-globals.js
addon-sdk/source/test/test-heritage.js
addon-sdk/source/test/test-hidden-frame.js
addon-sdk/source/test/test-host-events.js
addon-sdk/source/test/test-hotkeys.js
addon-sdk/source/test/test-httpd.js
addon-sdk/source/test/test-indexed-db.js
addon-sdk/source/test/test-jetpack-id.js
addon-sdk/source/test/test-keyboard-observer.js
addon-sdk/source/test/test-keyboard-utils.js
addon-sdk/source/test/test-l10n-locale.js
addon-sdk/source/test/test-l10n-plural-rules.js
addon-sdk/source/test/test-lang-type.js
addon-sdk/source/test/test-libxul.js
addon-sdk/source/test/test-list.js
addon-sdk/source/test/test-loader.js
addon-sdk/source/test/test-match-pattern.js
addon-sdk/source/test/test-method.js
addon-sdk/source/test/test-module.js
addon-sdk/source/test/test-modules.js
addon-sdk/source/test/test-mozilla-toolkit-versioning.js
addon-sdk/source/test/test-mpl2-license-header.js
addon-sdk/source/test/test-namespace.js
addon-sdk/source/test/test-native-loader.js
addon-sdk/source/test/test-native-options.js
addon-sdk/source/test/test-net-url.js
addon-sdk/source/test/test-node-os.js
addon-sdk/source/test/test-notifications.js
addon-sdk/source/test/test-object.js
addon-sdk/source/test/test-observers.js
addon-sdk/source/test/test-page-mod-debug.js
addon-sdk/source/test/test-page-mod.js
addon-sdk/source/test/test-page-worker.js
addon-sdk/source/test/test-panel.js
addon-sdk/source/test/test-passwords-utils.js
addon-sdk/source/test/test-passwords.js
addon-sdk/source/test/test-path.js
addon-sdk/source/test/test-plain-text-console.js
addon-sdk/source/test/test-preferences-service.js
addon-sdk/source/test/test-preferences-target.js
addon-sdk/source/test/test-private-browsing.js
addon-sdk/source/test/test-promise.js
addon-sdk/source/test/test-querystring.js
addon-sdk/source/test/test-reference.js
addon-sdk/source/test/test-request.js
addon-sdk/source/test/test-require.js
addon-sdk/source/test/test-rules.js
addon-sdk/source/test/test-sandbox.js
addon-sdk/source/test/test-selection.js
addon-sdk/source/test/test-self.js
addon-sdk/source/test/test-sequence.js
addon-sdk/source/test/test-set-exports.js
addon-sdk/source/test/test-shared-require.js
addon-sdk/source/test/test-simple-prefs.js
addon-sdk/source/test/test-simple-storage.js
addon-sdk/source/test/test-system-events.js
addon-sdk/source/test/test-system-input-output.js
addon-sdk/source/test/test-system-runtime.js
addon-sdk/source/test/test-system-startup.js
addon-sdk/source/test/test-system.js
addon-sdk/source/test/test-tab-events.js
addon-sdk/source/test/test-tab-observer.js
addon-sdk/source/test/test-tab-utils.js
addon-sdk/source/test/test-tab.js
addon-sdk/source/test/test-tabs-common.js
addon-sdk/source/test/test-tabs.js
addon-sdk/source/test/test-test-addon-file.js
addon-sdk/source/test/test-test-assert.js
addon-sdk/source/test/test-test-loader.js
addon-sdk/source/test/test-test-memory.js
addon-sdk/source/test/test-test-utils-async.js
addon-sdk/source/test/test-test-utils-generator.js
addon-sdk/source/test/test-test-utils-sync.js
addon-sdk/source/test/test-test-utils.js
addon-sdk/source/test/test-text-streams.js
addon-sdk/source/test/test-timer.js
addon-sdk/source/test/test-traceback.js
addon-sdk/source/test/test-ui-action-button.js
addon-sdk/source/test/test-ui-frame.js
addon-sdk/source/test/test-ui-id.js
addon-sdk/source/test/test-ui-sidebar-private-browsing.js
addon-sdk/source/test/test-ui-sidebar.js
addon-sdk/source/test/test-ui-toggle-button.js
addon-sdk/source/test/test-ui-toolbar.js
addon-sdk/source/test/test-unit-test-finder.js
addon-sdk/source/test/test-unit-test.js
addon-sdk/source/test/test-unload.js
addon-sdk/source/test/test-unsupported-skip.js
addon-sdk/source/test/test-uri-resource.js
addon-sdk/source/test/test-url.js
addon-sdk/source/test/test-uuid.js
addon-sdk/source/test/test-weak-set.js
addon-sdk/source/test/test-window-events.js
addon-sdk/source/test/test-window-observer.js
addon-sdk/source/test/test-window-utils-private-browsing.js
addon-sdk/source/test/test-window-utils.js
addon-sdk/source/test/test-window-utils2.js
addon-sdk/source/test/test-windows-common.js
addon-sdk/source/test/test-windows.js
addon-sdk/source/test/test-xhr.js
addon-sdk/source/test/test-xpcom.js
addon-sdk/source/test/test-xul-app.js
addon-sdk/source/test/traits/assert.js
addon-sdk/source/test/traits/utils.js
addon-sdk/source/test/util.js
addon-sdk/source/test/windows/test-fennec-windows.js
addon-sdk/source/test/windows/test-firefox-windows.js
addon-sdk/source/test/zip/utils.js
addon-sdk/test/Math.jsm
addon-sdk/test/browser.ini
addon-sdk/test/browser_sdk_loader_chrome.js
addon-sdk/test/browser_sdk_loader_chrome_in_sdk.js
addon-sdk/test/browser_sdk_loader_js_modules.js
addon-sdk/test/browser_sdk_loader_jsm_modules.js
addon-sdk/test/browser_sdk_loader_json.js
addon-sdk/test/browser_sdk_loader_sdk_gui_modules.js
addon-sdk/test/browser_sdk_loader_sdk_modules.js
addon-sdk/test/data.json
addon-sdk/test/head.js
addon-sdk/test/invalid.json
addon-sdk/test/math.js
deleted file mode 100644
--- a/addon-sdk/Makefile.in
+++ /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/.
-
-TESTADDONS = source/test/addons
-ADDONSRC = $(srcdir)/$(TESTADDONS)
-
-include $(topsrcdir)/config/rules.mk
-
-# This can switch to just zipping the files when native jetpacks land
-%.xpi: FORCE
-	$(PYTHON) $(srcdir)/source/bin/cfx xpi --no-strip-xpi --pkgdir=$(ADDONSRC)/$* --output-file=$@
-
-TEST_FILES = \
-  $(srcdir)/source/app-extension \
-  $(srcdir)/source/bin \
-  $(srcdir)/source/python-lib \
-  $(srcdir)/source/test \
-  $(srcdir)/source/package.json \
-  $(srcdir)/source/mapping.json \
-  $(NULL)
-
-# Remove this once the test harness uses the APIs built into Firefox
-TEST_FILES += $(srcdir)/source/lib
-
-PKG_STAGE = $(DIST)/test-stage
-
-stage-tests-package:: $(TEST_FILES)
-	$(INSTALL) $^ $(PKG_STAGE)/jetpack
deleted file mode 100644
--- a/addon-sdk/moz.build
+++ /dev/null
@@ -1,119 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Makefile.in uses a misc target through test_addons_TARGET.
-HAS_MISC_RULE = True
-
-BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
-JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
-
-DIRS += ['source/test/fixtures']
-
-EXTRA_JS_MODULES.sdk += [
-    'source/app-extension/bootstrap.js',
-]
-
-EXTRA_JS_MODULES.sdk.system += [
-    'source/modules/system/Startup.js',
-]
-
-modules = [
-    'index.js',
-    'jetpack-id/index.js',
-    'method/core.js',
-    'mozilla-toolkit-versioning/index.js',
-    'mozilla-toolkit-versioning/lib/utils.js',
-    'node/os.js',
-    'sdk/addon/installer.js',
-    'sdk/addon/window.js',
-    'sdk/base64.js',
-    'sdk/console/traceback.js',
-    'sdk/core/disposable.js',
-    'sdk/core/namespace.js',
-    'sdk/core/observer.js',
-    'sdk/core/promise.js',
-    'sdk/core/reference.js',
-    'sdk/deprecated/unit-test-finder.js',
-    'sdk/deprecated/unit-test.js',
-    'sdk/deprecated/window-utils.js',
-    'sdk/event/chrome.js',
-    'sdk/event/core.js',
-    'sdk/event/dom.js',
-    'sdk/event/target.js',
-    'sdk/event/utils.js',
-    'sdk/frame/utils.js',
-    'sdk/io/file.js',
-    'sdk/lang/functional.js',
-    'sdk/lang/functional/concurrent.js',
-    'sdk/lang/functional/core.js',
-    'sdk/lang/functional/helpers.js',
-    'sdk/lang/type.js',
-    'sdk/lang/weak-set.js',
-    'sdk/net/url.js',
-    'sdk/platform/xpcom.js',
-    'sdk/preferences/service.js',
-    'sdk/preferences/utils.js',
-    'sdk/private-browsing.js',
-    'sdk/private-browsing/utils.js',
-    'sdk/querystring.js',
-    'sdk/self.js',
-    'sdk/system.js',
-    'sdk/system/environment.js',
-    'sdk/system/events.js',
-    'sdk/system/globals.js',
-    'sdk/system/process.js',
-    'sdk/system/runtime.js',
-    'sdk/system/unload.js',
-    'sdk/system/xul-app.js',
-    'sdk/system/xul-app.jsm',
-    'sdk/test.js',
-    'sdk/test/assert.js',
-    'sdk/test/harness.js',
-    'sdk/test/loader.js',
-    'sdk/test/options.js',
-    'sdk/test/utils.js',
-    'sdk/timers.js',
-    'sdk/uri/resource.js',
-    'sdk/url.js',
-    'sdk/url/utils.js',
-    'sdk/util/array.js',
-    'sdk/util/collection.js',
-    'sdk/util/deprecate.js',
-    'sdk/util/dispatcher.js',
-    'sdk/util/list.js',
-    'sdk/util/object.js',
-    'sdk/util/sequence.js',
-    'sdk/util/uuid.js',
-    'sdk/window/utils.js',
-    'sdk/zip/utils.js',
-    'test.js',
-    'toolkit/loader.js',
-    'toolkit/require.js',
-]
-
-commonjs = EXTRA_JS_MODULES.commonjs
-
-sources = {}
-def get_sources(path):
-    key = '/'.join(path)
-    if key in sources:
-        return sources[key]
-
-    source_dir = commonjs
-    for dir_ in path:
-        source_dir = source_dir[dir_]
-
-    sources[key] = source_dir
-    return source_dir
-
-for module in modules:
-    path = module.split('/')[:-1]
-
-    source_dir = get_sources(path)
-    source_dir += ['source/lib/%s' % module]
-
-with Files("**"):
-    BUG_COMPONENT = ("Add-on SDK", "General")
deleted file mode 100644
--- a/addon-sdk/source/.gitattributes
+++ /dev/null
@@ -1,5 +0,0 @@
-.gitignore export-ignore
-.hgignore export-ignore
-.hgtags export-ignore
-.gitattributes export-ignore
-python-lib/cuddlefish/_version.py export-subst
deleted file mode 100644
--- a/addon-sdk/source/.gitignore
+++ /dev/null
@@ -1,36 +0,0 @@
-local.json
-python-lib/cuddlefish/app-extension/components/jetpack.xpt
-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
deleted file mode 100644
--- a/addon-sdk/source/.hgignore
+++ /dev/null
@@ -1,15 +0,0 @@
-syntax: glob
-local.json
-python-lib/cuddlefish/app-extension/components/jetpack.xpt
-testdocs.tgz
-jetpack-sdk-docs.tgz
-.test_tmp
-jetpack-sdk-docs
-node_modules
-
-# These should really be in a global .hgignore, but such a thing
-# seems ridiculously confusing to set up, so we'll include some
-# common intermediate files here.
-*.pyc
-*~
-*.DS_Store
deleted file mode 100644
--- a/addon-sdk/source/.hgtags
+++ /dev/null
@@ -1,64 +0,0 @@
-39c45211aa250d43f6e54b776a60ef07a7a4cbb6 jep-31-examples
-0120642297b217680e75e68c4005a93b16466001 0.1rc1
-1fd7993ff2cec39c5948a1b2535b78c2d4c65858 0.1rc2
-530e51d02922ad05fd43e8cf113618068216b0cf 0.1
-ed11a9e3ae23aefd56ac88042b9816887d10a04f 0.2rc1
-f70ab8998abdce809bda93408435f83648909cdd 0.2rc2
-f70ab8998abdce809bda93408435f83648909cdd 0.2
-436968c6ec833d9c18a15426be26595a44b79283 0.3rc1
-a3b091d29607f0bcecf77fe27801ba901142f1c9 0.3
-06031b56312ad7f1880a9620b4d26ce253a23b23 0.3rc2
-a3b091d29607f0bcecf77fe27801ba901142f1c9 0.3
-4b08c8a8c1eef71ac3aa54e004b68e87049ca56b 0.3
-6884e54fd6a1cfa9ec63910c46d2cbf51495b584 0.3rc3
-4b08c8a8c1eef71ac3aa54e004b68e87049ca56b 0.3
-cd70b7140ec20689255f1248512a1e5b9cf90a32 0.3
-d9d733666ca8738e9665ba816d5d12f41fc0d216 0.4rc1
-8d2871fc10df16740273f53ef05815310da4b210 0.4
-201e60065b1aef23259a71756f93207cffa2abd5 0.4rc2
-8d2871fc10df16740273f53ef05815310da4b210 0.4
-c0e5bbdcafad4572a5de22e533543bf3330a869e 0.4
-201e60065b1aef23259a71756f93207cffa2abd5 0.4rc2
-a8dceaefd6f3376b7bc1619cccd854591b76ecc0 0.4rc2
-c0e5bbdcafad4572a5de22e533543bf3330a869e 0.4
-dfa3bdfedb12d743b5e0ac19d0ecf116b567a0b3 0.4
-b519a0848585e2a665a14aac2fb6f15c0a839e6c 0.4rc3
-dfa3bdfedb12d743b5e0ac19d0ecf116b567a0b3 0.4
-05acdf4987c28d8cc1d5a12d87e71b1445fdd6b7 0.4
-04b5afe48d1cee819d9f0af72ed16556a075b67d 0.5rc1
-1968150561097bcfeeb28a75801ef881d2fcbbf5 0.5
-3236e68e6f2e36353e47f01a9b8acfce56686263 0.5rc2
-1968150561097bcfeeb28a75801ef881d2fcbbf5 0.5
-0097da78aa23be8b7a5a811c4be0e3e35395af43 0.5
-be7016807a69c910ac31ff068a6c2bde0a25c9d4 0.5rc3
-0097da78aa23be8b7a5a811c4be0e3e35395af43 0.5
-83e97107e4a381b898c780b32e30e48b0e4d37f3 0.5
-182a405aa393dbd412e671e8516d2decd8e8d80c 0.6rc1
-96799a3d96abfdb1408f9b8e30479668f1feed70 0.6
-c5f6cdfa36b2ad33d8017e6844992de0b0a6c0e0 0.6rc2
-96799a3d96abfdb1408f9b8e30479668f1feed70 0.6
-65c393fbc6af7db79a4a2e903d06b17e90d254bf 0.6
-3e747e3e307a4e853d468b03357f96b2172bad37 0.7rc1
-b0e97e12eb9115f08127cc447d459f871c5046ed 0.7
-37288479d249168668abd60a907620fa7f593128 0.7rc2
-b0e97e12eb9115f08127cc447d459f871c5046ed 0.7
-db0eabc310619d00ce47372ecaafba7d2539b601 0.7
-37288479d249168668abd60a907620fa7f593128 0.7rc2
-b90bedb83525d8f32ebb4d3833e8d91efa991b6d 0.7rc2
-db0eabc310619d00ce47372ecaafba7d2539b601 0.7
-e6ea2e5c5274cbbb0278dc976844dbf51818a95e 0.7
-b90bedb83525d8f32ebb4d3833e8d91efa991b6d 0.7rc2
-9b978d823509de5d52ca222b9907f72591c68c5a 0.7rc2
-e6ea2e5c5274cbbb0278dc976844dbf51818a95e 0.7
-cd71e1e77c93adf169b9f38184b1f95d423876ba 0.7
-67e3fd285fa955898a2641226c86725365d68b95 0.8rc1
-b2f9405db6d74c21601ca9c250887411c837396a 0.8
-67e3fd285fa955898a2641226c86725365d68b95 0.8rc1
-56e8179ff5b467959ddf33978558d7eb5346ee53 0.8rc1
-b2f9405db6d74c21601ca9c250887411c837396a 0.8
-51a22a186b1c7d8e7292a5ec9670752dad223ca1 0.8
-d150cca77cfef60dee2f2fe7c892fd7fc5ce83c4 0.9rc1
-1e106beb57f65fabc32682f277de51a8101c919b 0.9
-173d56fa8cc1c5622eae70f1ae88ef789de4722b 0.9rc2
-1e106beb57f65fabc32682f277de51a8101c919b 0.9
-cde12eefd178d7a0ee7d5e9ae77f3089bcbdc6ec 0.9
deleted file mode 100644
--- a/addon-sdk/source/.jpmignore
+++ /dev/null
@@ -1,18 +0,0 @@
-local.json
-mapping.json
-CONTRIBUTING.md
-@addon-sdk.xpi
-.*
-app-extension/
-bin/
-modules/
-node_modules/
-examples/
-cache/
-
-# Python
-python-lib/
-*.pyc
-
-# Windows
-*Thumbs.db
deleted file mode 100644
--- a/addon-sdk/source/.travis.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-sudo: false
-language: node_js
-node_js:
-  - "0.12"
-
-env:
-  - JPM_FX_DEBUG=0
-  - JPM_FX_DEBUG=1
-
-notifications:
-  irc: "irc.mozilla.org#jetpack"
-
-cache:
-  directories:
-  - cache
-
-before_install:
-  - "export DISPLAY=:99.0"
-  - "/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 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
deleted file mode 100644
--- a/addon-sdk/source/CONTRIBUTING.md
+++ /dev/null
@@ -1,54 +0,0 @@
-##  Overview
-
-- Changes should follow the [design guidelines], as well as the [coding style guide]
-- 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
-
-Follow the [standard mozilla contribution guidelines](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Introduction). All contributions and patches should be through Bugzilla.
-
-Pull requests on github are not accepted and new pull requests on github will be rejected.
-
-## Good First Bugs
-
-There is a list of [good first bugs here][good first bugs].
-
-## Reviewers
-
-Changes should be reviewed by someone on the [add-on sdk review team](https://bugzilla.mozilla.org/page.cgi?id=review_suggestions.html#Add-on%20SDK) within Bugzilla.
-
-Others who might be able to help include:
-
-- [@mossop]
-- [@gozala]
-- [@ZER0]
-- [@jsantell]
-- [@zombie]
-
-For review of Mozilla platform usage and best practices, ask [@autonome],
-[@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
-[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/
-[@gozala]:https://github.com/Gozala/
-[@ZER0]:https://github.com/ZER0/
-[@jsantell]:https://github.com/jsantell
-[@zombie]:https://github.com/zombie
deleted file mode 100644
--- a/addon-sdk/source/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-The files which make up the SDK are developed by Mozilla and licensed
-under the MPL 2.0 (http://mozilla.org/MPL/2.0/), with the exception of the
-components listed below, which are made available by their authors under
-the licenses listed alongside.
-
-syntaxhighlighter
-------------------
-doc/static-files/syntaxhighlighter
-Made available under the MIT license.
-
-jQuery
-------
-examples/reddit-panel/data/jquery-1.4.4.min.js
-examples/annotator/data/jquery-1.4.2.min.js
-Made available under the MIT license.
-
-simplejson
-----------
-python-lib/simplejson
-Made available under the MIT license.
-
-Python Markdown
----------------
-python-lib/markdown
-Made available under the BSD license.
-
-LibraryDetector
----------------
-examples/library-detector/data/library-detector.js
-Made available under the MIT license.
deleted file mode 100644
--- a/addon-sdk/source/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Mozilla Add-on SDK [![Build Status](https://travis-ci.org/mozilla/addon-sdk.png)](https://travis-ci.org/mozilla/addon-sdk)
-
-We suggest that developers of new add-ons [should look at using WebExtensions](https://developer.mozilla.org/en-US/Add-ons/WebExtensions).
-
-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 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 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)
deleted file mode 100644
--- a/addon-sdk/source/app-extension/application.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[App]
-Vendor=Varma
-Name=Test App
-Version=1.0
-BuildID=20060101
-Copyright=Copyright (c) 2009 Atul Varma
-ID=xulapp@toolness.com
-
-[Gecko]
-MinVersion=1.9.2.0
-MaxVersion=2.0.*
deleted file mode 100644
--- a/addon-sdk/source/app-extension/bootstrap.js
+++ /dev/null
@@ -1,362 +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/. */
-
-// @see http://dxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp
-
-'use strict';
-
-// IMPORTANT: Avoid adding any initialization tasks here, if you need to do
-// something before add-on is loaded consider addon/runner module instead!
-
-const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
-        results: Cr, manager: Cm } = Components;
-const ioService = Cc['@mozilla.org/network/io-service;1'].
-                  getService(Ci.nsIIOService);
-const resourceHandler = ioService.getProtocolHandler('resource').
-                        QueryInterface(Ci.nsIResProtocolHandler);
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const prefService = Cc['@mozilla.org/preferences-service;1'].
-                    getService(Ci.nsIPrefService).
-                    QueryInterface(Ci.nsIPrefBranch);
-const appInfo = Cc["@mozilla.org/xre/app-info;1"].
-                getService(Ci.nsIXULAppInfo);
-const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
-           getService(Ci.nsIVersionComparator);
-
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-
-const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
-
-
-const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
-                 'install', 'uninstall', 'upgrade', 'downgrade' ];
-
-const bind = Function.call.bind(Function.bind);
-
-var loader = null;
-var unload = null;
-var cuddlefishSandbox = null;
-var nukeTimer = null;
-
-var resourceDomains = [];
-function setResourceSubstitution(domain, uri) {
-  resourceDomains.push(domain);
-  resourceHandler.setSubstitution(domain, uri);
-}
-
-// Utility function that synchronously reads local resource from the given
-// `uri` and returns content string.
-function readURI(uri) {
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, 'UTF-8'),
-    loadUsingSystemPrincipal: true
-  });
-
-  let stream = channel.open2();
-
-  let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
-    createInstance(Ci.nsIConverterInputStream);
-  cstream.init(stream, 'UTF-8', 0, 0);
-
-  let str = {};
-  let data = '';
-  let read = 0;
-  do {
-    read = cstream.readString(0xffffffff, str);
-    data += str.value;
-  } while (read != 0);
-
-  cstream.close();
-
-  return data;
-}
-
-// We don't do anything on install & uninstall yet, but in a future
-// we should allow add-ons to cleanup after uninstall.
-function install(data, reason) {}
-function uninstall(data, reason) {}
-
-function startup(data, reasonCode) {
-  try {
-    let reason = REASON[reasonCode];
-    // URI for the root of the XPI file.
-    // 'jar:' URI if the addon is packed, 'file:' URI otherwise.
-    // (Used by l10n module in order to fetch `locale` folder)
-    let rootURI = data.resourceURI.spec;
-
-    // TODO: Maybe we should perform read harness-options.json asynchronously,
-    // since we can't do anything until 'sessionstore-windows-restored' anyway.
-    let options = JSON.parse(readURI(rootURI + './harness-options.json'));
-
-    let id = options.jetpackID;
-    let name = options.name;
-
-    // Clean the metadata
-    options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {};
-
-    // freeze the permissionss
-    Object.freeze(options.metadata[name]['permissions']);
-    // freeze the metadata
-    Object.freeze(options.metadata[name]);
-
-    // Register a new resource 'domain' for this addon which is mapping to
-    // XPI's `resources` folder.
-    // Generate the domain name by using jetpack ID, which is the extension ID
-    // by stripping common characters that doesn't work as a domain name:
-    let uuidRe =
-      /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
-
-    let domain = id.
-      toLowerCase().
-      replace(/@/g, '-at-').
-      replace(/\./g, '-dot-').
-      replace(uuidRe, '$1');
-
-    let prefixURI = 'resource://' + domain + '/';
-    let resourcesURI = ioService.newURI(rootURI + '/resources/');
-    setResourceSubstitution(domain, resourcesURI);
-
-    // Create path to URLs mapping supported by loader.
-    let paths = {
-      // Relative modules resolve to add-on package lib
-      './': prefixURI + name + '/lib/',
-      './tests/': prefixURI + name + '/tests/',
-      '': 'resource://gre/modules/commonjs/'
-    };
-
-    // Maps addon lib and tests ressource folders for each package
-    paths = Object.keys(options.metadata).reduce(function(result, name) {
-      result[name + '/'] = prefixURI + name + '/lib/'
-      result[name + '/tests/'] = prefixURI + name + '/tests/'
-      return result;
-    }, paths);
-
-    // We need to map tests folder when we run sdk tests whose package name
-    // is stripped
-    if (name == 'addon-sdk')
-      paths['tests/'] = prefixURI + name + '/tests/';
-
-    let useBundledSDK = options['force-use-bundled-sdk'];
-    if (!useBundledSDK) {
-      try {
-        useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK");
-      }
-      catch (e) {
-        // Pref doesn't exist, allow using Firefox shipped SDK
-      }
-    }
-
-    // Starting with Firefox 21.0a1, we start using modules shipped into firefox
-    // Still allow using modules from the xpi if the manifest tell us to do so.
-    // And only try to look for sdk modules in xpi if the xpi actually ship them
-    if (options['is-sdk-bundled'] &&
-        (vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) {
-      // Maps sdk module folders to their resource folder
-      paths[''] = prefixURI + 'addon-sdk/lib/';
-      // test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
-      // so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
-      // until we no longer support SDK modules in XPI:
-      paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
-    }
-
-    // Retrieve list of module folder overloads based on preferences in order to
-    // eventually used a local modules instead of files shipped into Firefox.
-    let branch = prefService.getBranch('extensions.modules.' + id + '.path');
-    paths = branch.getChildList('', {}).reduce(function (result, name) {
-      // Allows overloading of any sub folder by replacing . by / in pref name
-      let path = name.substr(1).split('.').join('/');
-      // Only accept overloading folder by ensuring always ending with `/`
-      if (path) path += '/';
-      let fileURI = branch.getCharPref(name);
-
-      // On mobile, file URI has to end with a `/` otherwise, setSubstitution
-      // takes the parent folder instead.
-      if (fileURI[fileURI.length-1] !== '/')
-        fileURI += '/';
-
-      // Maps the given file:// URI to a resource:// in order to avoid various
-      // failure that happens with file:// URI and be close to production env
-      let resourcesURI = ioService.newURI(fileURI);
-      let resName = 'extensions.modules.' + domain + '.commonjs.path' + name;
-      setResourceSubstitution(resName, resourcesURI);
-
-      result[path] = 'resource://' + resName + '/';
-      return result;
-    }, paths);
-
-    // Make version 2 of the manifest
-    let manifest = options.manifest;
-
-    // Import `cuddlefish.js` module using a Sandbox and bootstrap loader.
-    let cuddlefishPath = 'loader/cuddlefish.js';
-    let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath;
-    if (paths['sdk/']) { // sdk folder has been overloaded
-                         // (from pref, or cuddlefish is still in the xpi)
-      cuddlefishURI = paths['sdk/'] + cuddlefishPath;
-    }
-    else if (paths['']) { // root modules folder has been overloaded
-      cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath;
-    }
-
-    cuddlefishSandbox = loadSandbox(cuddlefishURI);
-    let cuddlefish = cuddlefishSandbox.exports;
-
-    // Normalize `options.mainPath` so that it looks like one that will come
-    // in a new version of linker.
-    let main = options.mainPath;
-
-    unload = cuddlefish.unload;
-    loader = cuddlefish.Loader({
-      paths: paths,
-      // modules manifest.
-      manifest: manifest,
-
-      // Add-on ID used by different APIs as a unique identifier.
-      id: id,
-      // Add-on name.
-      name: name,
-      // Add-on version.
-      version: options.metadata[name].version,
-      // Add-on package descriptor.
-      metadata: options.metadata[name],
-      // Add-on load reason.
-      loadReason: reason,
-
-      prefixURI: prefixURI,
-      // Add-on URI.
-      rootURI: rootURI,
-      // options used by system module.
-      // File to write 'OK' or 'FAIL' (exit code emulation).
-      resultFile: options.resultFile,
-      // Arguments passed as --static-args
-      staticArgs: options.staticArgs,
-
-      // Option to prevent automatic kill of firefox during tests
-      noQuit: options.no_quit,
-
-      // Add-on preferences branch name
-      preferencesBranch: options.preferencesBranch,
-
-      // Arguments related to test runner.
-      modules: {
-        '@test/options': {
-          iterations: options.iterations,
-          filter: options.filter,
-          profileMemory: options.profileMemory,
-          stopOnError: options.stopOnError,
-          verbose: options.verbose,
-          parseable: options.parseable,
-          checkMemory: options.check_memory,
-        }
-      }
-    });
-
-    let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI);
-    let require = cuddlefish.Require(loader, module);
-
-    // Init the 'sdk/webextension' module from the bootstrap addon parameter.
-    require("sdk/webextension").initFromBootstrapAddonParam(data);
-
-    require('sdk/addon/runner').startup(reason, {
-      loader: loader,
-      main: main,
-      prefsURI: rootURI + 'defaults/preferences/prefs.js'
-    });
-  } catch (error) {
-    dump('Bootstrap error: ' +
-         (error.message ? error.message : String(error)) + '\n' +
-         (error.stack || error.fileName + ': ' + error.lineNumber) + '\n');
-    throw error;
-  }
-};
-
-function loadSandbox(uri) {
-  let proto = {
-    sandboxPrototype: {
-      loadSandbox: loadSandbox,
-      ChromeWorker: ChromeWorker
-    }
-  };
-  let sandbox = Cu.Sandbox(systemPrincipal, proto);
-  // Create a fake commonjs environnement just to enable loading loader.js
-  // correctly
-  sandbox.exports = {};
-  sandbox.module = { uri: uri, exports: sandbox.exports };
-  sandbox.require = function (id) {
-    if (id !== "chrome")
-      throw new Error("Bootstrap sandbox `require` method isn't implemented.");
-
-    return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
-      CC: bind(CC, Components), components: Components,
-      ChromeWorker: ChromeWorker });
-  };
-  scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
-  return sandbox;
-}
-
-function unloadSandbox(sandbox) {
-  if (Cu.getClassName(sandbox, true) == "Sandbox")
-    Cu.nukeSandbox(sandbox);
-}
-
-function setTimeout(callback, delay) {
-  let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-  timer.initWithCallback({ notify: callback }, delay,
-                         Ci.nsITimer.TYPE_ONE_SHOT);
-  return timer;
-}
-
-function shutdown(data, reasonCode) {
-  let reason = REASON[reasonCode];
-  if (loader) {
-    unload(loader, reason);
-    unload = null;
-
-    // Don't waste time cleaning up if the application is shutting down
-    if (reason != "shutdown") {
-      // Avoid leaking all modules when something goes wrong with one particular
-      // module. Do not clean it up immediatly in order to allow executing some
-      // actions on addon disabling.
-      // We need to keep a reference to the timer, otherwise it is collected
-      // and won't ever fire.
-      nukeTimer = setTimeout(nukeModules, 1000);
-
-      // Bug 944951 - bootstrap.js must remove the added resource: URIs on unload
-      resourceDomains.forEach(domain => {
-        resourceHandler.setSubstitution(domain, null);
-      })
-    }
-  }
-};
-
-function nukeModules() {
-  nukeTimer = null;
-  // module objects store `exports` which comes from sandboxes
-  // We should avoid keeping link to these object to avoid leaking sandboxes
-  for (let key in loader.modules) {
-    delete loader.modules[key];
-  }
-  // Direct links to sandboxes should be removed too
-  for (let key in loader.sandboxes) {
-    let sandbox = loader.sandboxes[key];
-    delete loader.sandboxes[key];
-    // Bug 775067: From FF17 we can kill all CCW from a given sandbox
-    unloadSandbox(sandbox);
-  }
-  unloadSandbox(loader.sharedGlobalSandbox);
-  loader = null;
-
-  // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
-  // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when
-  // the addon is unload.
-
-  unloadSandbox(cuddlefishSandbox.loaderSandbox);
-
-  // Bug 764840: We need to unload cuddlefish otherwise it will stay alive
-  // and keep a reference to this compartment.
-  unloadSandbox(cuddlefishSandbox);
-  cuddlefishSandbox = null;
-}
deleted file mode 100644
--- a/addon-sdk/source/app-extension/install.rdf
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.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/. -->
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>xulapp@toolness.com</em:id>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-    <em:unpack>false</em:unpack>
-
-    <!-- Firefox -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>26.0</em:minVersion>
-        <em:maxVersion>30.0</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Test App</em:name>
-    <em:description>Harness for tests.</em:description>
-    <em:creator>Mozilla Corporation</em:creator>
-    <em:homepageURL></em:homepageURL>
-    <em:optionsType></em:optionsType>
-    <em:optionsURL></em:optionsURL>
-    <em:updateURL></em:updateURL>
-  </Description>
-</RDF>
deleted file mode 100644
--- a/addon-sdk/source/bin/activate
+++ /dev/null
@@ -1,84 +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 file must be used with "source bin/activate" *from bash*
-# you cannot run it directly
-
-deactivate () {
-    if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
-        PATH="$_OLD_VIRTUAL_PATH"
-        export PATH
-        unset _OLD_VIRTUAL_PATH
-    fi
-
-    # This should detect bash and zsh, which have a hash command that must
-    # be called to get it to forget past commands.  Without forgetting
-    # past commands the $PATH changes we made may not be respected
-    if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
-        hash -r
-    fi
-
-    if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
-        PS1="$_OLD_VIRTUAL_PS1"
-        export PS1
-        unset _OLD_VIRTUAL_PS1
-    fi
-
-    PYTHONPATH="$_OLD_PYTHONPATH"
-    export PYTHONPATH
-    unset _OLD_PYTHONPATH
-
-    unset CUDDLEFISH_ROOT
-
-    unset VIRTUAL_ENV
-    if [ ! "$1" = "nondestructive" ] ; then
-    # Self destruct!
-        unset deactivate
-    fi
-}
-
-# unset irrelavent variables
-deactivate nondestructive
-
-_OLD_PYTHONPATH="$PYTHONPATH"
-_OLD_VIRTUAL_PATH="$PATH"
-
-VIRTUAL_ENV="`pwd`"
-
-if [ "x$OSTYPE" = "xmsys" ] ; then
-  CUDDLEFISH_ROOT="`pwd -W | sed s,/,\\\\\\\\,g`"
-  PATH="`pwd`/bin:$PATH"
-  # msys will convert any env vars with PATH in it to use msys
-  # form and will unconvert before launching
-  PYTHONPATH="`pwd -W`/python-lib;$PYTHONPATH"
-else
-  CUDDLEFISH_ROOT="$VIRTUAL_ENV"
-  PYTHONPATH="$VIRTUAL_ENV/python-lib:$PYTHONPATH"
-  PATH="$VIRTUAL_ENV/bin:$PATH"
-fi
-
-VIRTUAL_ENV="`pwd`"
-
-export CUDDLEFISH_ROOT
-export PYTHONPATH
-export PATH
-
-_OLD_VIRTUAL_PS1="$PS1"
-if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
-    # special case for Aspen magic directories
-    # see http://www.zetadev.com/software/aspen/
-    PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
-else
-    PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
-fi
-export PS1
-
-# This should detect bash and zsh, which have a hash command that must
-# be called to get it to forget past commands.  Without forgetting
-# past commands the $PATH changes we made may not be respected
-if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
-    hash -r
-fi
-
-python -c "from jetpack_sdk_env import welcome; welcome()"
deleted file mode 100644
--- a/addon-sdk/source/bin/activate.bat
+++ /dev/null
@@ -1,134 +0,0 @@
-@echo off
-rem This Source Code Form is subject to the terms of the Mozilla Public
-rem License, v. 2.0. If a copy of the MPL was not distributed with this
-rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-set VIRTUAL_ENV=%~dp0
-set VIRTUAL_ENV=%VIRTUAL_ENV:~0,-5%
-set CUDDLEFISH_ROOT=%VIRTUAL_ENV%
-
-SET PYTHONKEY=SOFTWARE\Python\PythonCore
-
-rem look for 32-bit windows and python, or 64-bit windows and python
-
-SET PYTHONVERSION=2.7
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-SET PYTHONVERSION=2.6
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-SET PYTHONVERSION=2.5
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-if not defined ProgramFiles(x86) goto win32
-
-rem look for 32-bit python on 64-bit windows
-
-SET PYTHONKEY=SOFTWARE\Wow6432Node\Python\PythonCore
-
-SET PYTHONVERSION=2.7
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-SET PYTHONVERSION=2.6
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-SET PYTHONVERSION=2.5
-call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath
-if "%PYTHONINSTALL%" NEQ "" goto FoundPython
-
-:win32
-
-SET PYTHONVERSION=
-set PYTHONKEY=
-echo Warning: Failed to find Python installation directory
-goto :EOF
-
-:FoundPython
-
-if defined _OLD_PYTHONPATH (
-    set PYTHONPATH=%_OLD_PYTHONPATH%
-)
-if not defined PYTHONPATH (
-    set PYTHONPATH=;
-)
-set _OLD_PYTHONPATH=%PYTHONPATH%
-set PYTHONPATH=%VIRTUAL_ENV%\python-lib;%PYTHONPATH%
-
-if not defined PROMPT (
-    set PROMPT=$P$G
-)
-
-if defined _OLD_VIRTUAL_PROMPT (
-    set PROMPT=%_OLD_VIRTUAL_PROMPT%
-)
-
-set _OLD_VIRTUAL_PROMPT=%PROMPT%
-set PROMPT=(%VIRTUAL_ENV%) %PROMPT%
-
-if defined _OLD_VIRTUAL_PATH goto OLDPATH
-goto SKIPPATH
-:OLDPATH
-PATH %_OLD_VIRTUAL_PATH%
-
-:SKIPPATH
-set _OLD_VIRTUAL_PATH=%PATH%
-PATH %VIRTUAL_ENV%\bin;%PYTHONINSTALL%;%PATH%
-set PYTHONKEY=
-set PYTHONINSTALL=
-set PYTHONVERSION=
-set key=
-set reg=
-set _tokens=
-python -c "from jetpack_sdk_env import welcome; welcome()"
-GOTO :EOF
-
-:CheckPython
-::CheckPython(retVal, key)
-::Reads the registry at %2% and checks if a Python exists there.
-::Checks both HKLM and HKCU, then checks the executable actually exists.
-SET key=%2%
-SET "%~1="
-SET reg=reg
-if defined ProgramFiles(x86) (
-  rem 32-bit cmd on 64-bit windows
-  if exist %WINDIR%\sysnative\reg.exe SET reg=%WINDIR%\sysnative\reg.exe
-)
-rem On Vista+, the last line of output is:
-rem    (default)  REG_SZ  the_value
-rem (but note the word "default" will be localized.
-rem On XP, the last line of output is:
-rem   <NO NAME>\tREG_SZ\tthe_value
-rem (not sure if "NO NAME" is localized or not!)
-rem SO: we use ")>" as the tokens to split on, then nuke
-rem the REG_SZ and any tabs or spaces.
-FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKLM\%key% /ve 2^>NUL`) DO SET "%~1=%%A"
-rem Remove the REG_SZ
-set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=%
-rem Remove tabs (note the literal \t in the next line
-set PYTHONINSTALL=%PYTHONINSTALL:	=%
-rem Remove spaces.
-set PYTHONINSTALL=%PYTHONINSTALL: =%
-if exist %PYTHONINSTALL%\python.exe goto :EOF
-rem It may be a 32bit Python directory built from source, in which case the
-rem executable is in the PCBuild directory.
-if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF)
-rem Or maybe a 64bit build directory.
-if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF)
-
-rem And try HKCU
-FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKCU\%key% /ve 2^>NUL`) DO SET "%~1=%%A"
-set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=%
-set PYTHONINSTALL=%PYTHONINSTALL:	=%
-set PYTHONINSTALL=%PYTHONINSTALL: =%
-if exist %PYTHONINSTALL%\python.exe goto :EOF
-if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF)
-if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF)
-rem can't find it here, so arrange to try the next key
-set PYTHONINSTALL=
-
-GOTO :EOF
deleted file mode 100644
--- a/addon-sdk/source/bin/activate.fish
+++ /dev/null
@@ -1,66 +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 file must be used with "source bin/activate.fish" *from fish*
-# you cannot run it directly
-
-# Much of this code is based off of the activate.fish file for the
-# virtualenv project. http://ur1.ca/ehmd6
-
-function deactivate -d "Exit addon-sdk and return to normal shell environment"
-    if test -n "$_OLD_VIRTUAL_PATH"
-        set -gx PATH $_OLD_VIRTUAL_PATH
-        set -e _OLD_VIRTUAL_PATH
-    end
-
-    if test -n "$_OLD_PYTHONPATH"
-        set -gx PYTHONPATH $_OLD_PYTHONPATH
-        set -e _OLD_PYTHONPATH
-    end
-
-    if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
-        functions -e fish_prompt
-        set -e _OLD_FISH_PROMPT_OVERRIDE
-        . ( begin
-                printf "function fish_prompt\n\t#"
-                functions _old_fish_prompt
-            end | psub )
-
-        functions -e _old_fish_prompt
-    end
-
-    set -e CUDDLEFISH_ROOT
-    set -e VIRTUAL_ENV
-
-    if test "$argv[1]" != "nondestructive"
-        functions -e deactivate
-    end
-end
-
-# unset irrelavent variables
-deactivate nondestructive
-
-set -gx _OLD_PYTHONPATH $PYTHONPATH
-set -gx _OLD_VIRTUAL_PATH $PATH
-set -gx _OLD_FISH_PROMPT_OVERRIDE "true"
-
-set VIRTUAL_ENV (pwd)
-
-set -gx CUDDLEFISH_ROOT $VIRTUAL_ENV
-set -gx PYTHONPATH "$VIRTUAL_ENV/python-lib" $PYTHONPATH
-set -gx PATH "$VIRTUAL_ENV/bin" $PATH
-
-# save the current fish_prompt function as the function _old_fish_prompt
-. ( begin
-        printf "function _old_fish_prompt\n\t#"
-        functions fish_prompt
-    end | psub )
-
-# with the original prompt function renamed, we can override with our own.
-function fish_prompt
-    printf "(%s)%s%s" (basename "$VIRTUAL_ENV") (set_color normal) (_old_fish_prompt)
-    return
-end 
-
-python -c "from jetpack_sdk_env import welcome; welcome()"
deleted file mode 100644
--- a/addon-sdk/source/bin/activate.ps1
+++ /dev/null
@@ -1,99 +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/.
-
-$Env:VIRTUAL_ENV = (gl);
-$Env:CUDDLEFISH_ROOT = $Env:VIRTUAL_ENV;
-
-# http://stackoverflow.com/questions/5648931/powershell-test-if-registry-value-exists/5652674#5652674
-Function Test-RegistryValue {
-    param(
-        [Alias("PSPath")]
-        [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
-        [String]$Path
-        ,
-        [Parameter(Position = 1, Mandatory = $true)]
-        [String]$Name
-        ,
-        [Switch]$PassThru
-    ) 
-
-    process {
-        if (Test-Path $Path) {
-            $Key = Get-Item -LiteralPath $Path
-            if ($Key.GetValue($Name, $null) -ne $null) {
-                if ($PassThru) {
-                    Get-ItemProperty $Path $Name
-                } else {
-                    $true
-                }
-            } else {
-                $false
-            }
-        } else {
-            $false
-        }
-    }
-}
-
-$WINCURVERKEY = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion';
-$WIN64 = (Test-RegistryValue $WINCURVERKEY 'ProgramFilesDir (x86)');
-
-if($WIN64) { 
-    $PYTHONKEY='HKLM:SOFTWARE\Wow6432Node\Python\PythonCore';
-}
-else {
-    $PYTHONKEY='HKLM:SOFTWARE\Python\PythonCore';
-}
-
-$Env:PYTHONVERSION = '';
-$Env:PYTHONINSTALL = '';
-
-foreach ($version in @('2.6', '2.5', '2.4')) {
-    if (Test-RegistryValue "$PYTHONKEY\$version\InstallPath" '(default)') { 
-        $Env:PYTHONVERSION = $version;
-    }
-}
-
-if ($Env:PYTHONVERSION) { 
-    $Env:PYTHONINSTALL = (Get-Item "$PYTHONKEY\$version\InstallPath)").'(default)';
-}
-
-if ($Env:PYTHONINSTALL) { 
-    $Env:Path += ";$Env:PYTHONINSTALL";
-}
-
-if (Test-Path Env:_OLD_PYTHONPATH) { 
-    $Env:PYTHONPATH = $Env:_OLD_PYTHONPATH;
-}
-else {
-    $Env:PYTHONPATH = '';
-}
-
-$Env:_OLD_PYTHONPATH=$Env:PYTHONPATH;
-$Env:PYTHONPATH= "$Env:VIRTUAL_ENV\python-lib;$Env:PYTHONPATH";
-
-if (Test-Path Function:_OLD_VIRTUAL_PROMPT) {
-    Set-Content Function:Prompt (Get-Content Function:_OLD_VIRTUAL_PROMPT);
-}
-else {
-    function global:_OLD_VIRTUAL_PROMPT {}
-}
-
-Set-Content Function:_OLD_VIRTUAL_PROMPT (Get-Content Function:Prompt);
-
-function global:prompt { "($Env:VIRTUAL_ENV) $(_OLD_VIRTUAL_PROMPT)"; };
-
-if (Test-Path Env:_OLD_VIRTUAL_PATH) {
-    $Env:PATH = $Env:_OLD_VIRTUAL_PATH;
-}
-else {
-    $Env:_OLD_VIRTUAL_PATH = $Env:PATH;
-}
-
-$Env:Path="$Env:VIRTUAL_ENV\bin;$Env:Path"
-
-[System.Console]::WriteLine("Note: this PowerShell SDK activation script is experimental.")
-
-python -c "from jetpack_sdk_env import welcome; welcome()"
-
deleted file mode 100755
--- a/addon-sdk/source/bin/cfx
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-import os
-import sys
-
-# set the cuddlefish "root directory" for this process if it's not already
-# set in the environment
-cuddlefish_root = os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0])))
-
-if 'CUDDLEFISH_ROOT' not in os.environ:
-    os.environ['CUDDLEFISH_ROOT'] = cuddlefish_root
-
-# add our own python-lib path to the python module search path.
-python_lib_dir = os.path.join(cuddlefish_root, "python-lib")
-if python_lib_dir not in sys.path:
-    sys.path.insert(0, python_lib_dir)
-
-# now export to env so sub-processes get it too
-if 'PYTHONPATH' not in os.environ:
-    os.environ['PYTHONPATH'] = python_lib_dir
-elif python_lib_dir not in os.environ['PYTHONPATH'].split(os.pathsep):
-    paths = os.environ['PYTHONPATH'].split(os.pathsep)
-    paths.insert(0, python_lib_dir)
-    os.environ['PYTHONPATH'] = os.pathsep.join(paths)
-
-import cuddlefish
-
-if __name__ == '__main__':
-    cuddlefish.run()
deleted file mode 100644
--- a/addon-sdk/source/bin/cfx.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-@echo off
-rem This Source Code Form is subject to the terms of the Mozilla Public
-rem License, v. 2.0. If a copy of the MPL was not distributed with this
-rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-python "%VIRTUAL_ENV%\bin\cfx" %*
deleted file mode 100644
--- a/addon-sdk/source/bin/deactivate.bat
+++ /dev/null
@@ -1,23 +0,0 @@
-@echo off
-rem This Source Code Form is subject to the terms of the Mozilla Public
-rem License, v. 2.0. If a copy of the MPL was not distributed with this
-rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-if defined _OLD_VIRTUAL_PROMPT (
-    set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
-)
-set _OLD_VIRTUAL_PROMPT=
-
-if defined _OLD_VIRTUAL_PATH (
-    set "PATH=%_OLD_VIRTUAL_PATH%"
-)
-set _OLD_VIRTUAL_PATH=
-
-if defined _OLD_PYTHONPATH (
-    set "PYTHONPATH=%_OLD_PYTHONPATH%"
-)
-set _OLD_PYTHONPATH=
-
-set CUDDLEFISH_ROOT=
-
-:END
deleted file mode 100644
--- a/addon-sdk/source/bin/fx-download.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/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
deleted file mode 100755
--- a/addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-# 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/.
-
-
-source ./bin/activate
-if [ type -P xvfb-run ]
-then
-  xvfb-run cfx $*
-else
-  cfx $*
-fi  
-deactivate
deleted file mode 100644
--- a/addon-sdk/source/bin/integration-scripts/integration-check
+++ /dev/null
@@ -1,364 +0,0 @@
-#!/usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import os
-import signal
-import threading
-import urllib2, urllib
-import zipfile
-import tarfile
-import subprocess
-import optparse
-import sys, re
-#import win32api
-
-
-class SDK:
-    def __init__(self):
-        try:
-            # Take the current working directory
-            self.default_path = os.getcwd()
-            if sys.platform == "win32":
-                self.mswindows = True
-            else:
-                self.mswindows = False
-            # Take the default home path of the user.
-            home = os.path.expanduser('~')
-
-            # The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0
-            # If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop"
-            parser = optparse.OptionParser()
-            parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip')
-            parser.add_option('-p', '--path', dest = 'path', default = self.default_path)
-            parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app')
-            (options, args) = parser.parse_args()
-      
-            # Get the URL from the parameter
-            self.link = options.url
-            # Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory.
-            if options.path!=self.default_path:
-                if self.mswindows:
-                    self.base_path = home + str(options.path).strip() + '\\'
-                else:
-                    self.base_path = home + str(options.path).strip() + '/'
-            else:
-                if self.mswindows:
-                    self.base_path = str(options.path).strip() + '\\'
-                else:
-                    self.base_path = str(options.path).strip() + '/'
-            assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue."
-            print('Your Base path is =' + self.base_path)
-            
-            # This assignment is not used in this program. It will be used in version 2 of this script.
-            self.bin = options.binary
-            # if app or bin is empty, dont pass anything
-    
-            # Search for the .zip file or tarball file in the URL.
-            i = self.link.rfind('/')
-
-            self.fname = self.link[i+1:]
-            z = re.search('zip',self.fname,re.I)
-            g = re.search('gz',self.fname,re.I)
-            if z:
-                print 'zip file present in the URL.'
-                self.zip = True
-                self.gz = False
-            elif g:
-                print 'gz file present in the URL'
-                self.gz = True
-                self.zip = False
-            else:
-                print 'zip/gz file not present. Check the URL.'
-                return
-            print("File name is =" + self.fname)
-    
-            # Join the base path and the zip/tar file name to crate a complete Local file path.
-            self.fpath = self.base_path + self.fname
-            print('Your local file path will be=' + self.fpath)
-        except AssertionError, e:
-            print e.args[0] 
-            sys.exit(1)
-
-    # Download function - to download the SDK from the URL to the local machine.
-    def download(self,url,fpath,fname):
-        try:
-            # Start the download
-            print("Downloading...Please be patient!")
-            urllib.urlretrieve(url,filename = fname)
-            print('Download was successful.')
-        except ValueError: # Handles broken URL errors.
-            print 'The URL is ether broken or the file does not exist. Please enter the correct URL.'
-            raise
-        except urllib2.URLError: # Handles URL errors
-            print '\nURL not correct. Check again!'
-            raise
-
-    # Function to extract the downloaded zipfile.
-    def extract(self, zipfilepath, extfile):
-        try:
-            # Timeout is set to 30 seconds. 
-            timeout = 30
-            # Change the directory to the location of the zip file.
-            try:
-                os.chdir(zipfilepath)
-            except OSError:
-             # Will reach here if zip file doesnt exist
-                 print 'O/S Error:' + zipfilepath + 'does not exist'
-                 raise
-
-            # Get the folder name of Jetpack to get the exact version number.
-            if self.zip:
-                try:
-                    f = zipfile.ZipFile(extfile, "r")
-                except IOError as (errno, strerror): # Handles file errors
-                    print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
-                    raise
-                list = f.namelist()[0]
-                temp_name = list.split('/')
-                print('Folder Name= ' +temp_name[0])
-                self.folder_name = temp_name[0]
-            elif self.gz:
-                try:
-                    f = tarfile.open(extfile,'r')
-                except IOError as (errno, strerror): # Handles file errors
-                    print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
-                    raise
-                list = f.getnames()[0]
-                temp_name = list.split('/')
-                print('Folder Name= ' +temp_name[0])
-                self.folder_name = temp_name[0]
-
-            print ('Starting to Extract...')
-
-            # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
-            # timeout, the process is killed.
-            kill_check = threading.Event()
-            
-            if self.zip:
-            # Call the command to unzip the file.
-                if self.mswindows:
-                    zipfile.ZipFile.extractall(f)
-                else:
-                    p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True)
-                    pid = p.pid
-            elif self.gz:
-            # Call the command to untar the file.
-                if self.mswindows:
-                    tarfile.TarFile.extractall(f)
-                else:
-                    p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True)
-                    pid = p.pid
-            
-            #No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix)
-            if self.mswindows==False:
-                watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows ))
-                watch.start()
-                (stdout, stderr) = p.communicate()
-                watch.cancel() # if it's still waiting to run
-                success = not kill_check.isSet()
-    
-                # Abort process if process fails.
-                if not success:
-                    raise RuntimeError
-                kill_check.clear()
-            print('Extraction Successful.')
-        except RuntimeError:
-            print "Ending the program"
-            sys.exit(1)
-        except:
-            print "Error during file extraction: ", sys.exc_info()[0]
-            raise
-
-    # Function to run the cfx testall comands and to make sure the SDK is not broken.
-    def run_testall(self, home_path, folder_name):
-        try:
-            timeout = 500
-
-            self.new_dir = home_path + folder_name
-            try:
-                os.chdir(self.new_dir)
-            except OSError:
-             # Will reach here if the jetpack 0.X directory doesnt exist
-                print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir
-                raise
-            print '\nStarting tests...'
-            # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
-            # timeout, the process is killed.
-            kill_check = threading.Event()
-
-            # Set the path for the logs. They will be in the parent directory of the Jetpack SDK.
-            log_path = home_path + 'tests.log'
-
-            # Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file.
-            if self.bin != None:
-                if self.mswindows:
-                    p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    proc_handle = p._handle
-                    (stdout,stderr) = p.communicate()
-                else:
-                    p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    pid = p.pid
-                    (stdout,stderr) = p.communicate()
-            elif self.bin == None:
-                if self.mswindows:
-                    p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    proc_handle = p._handle
-                    (stdout,stderr) = p.communicate()
-                else:
-                    p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    pid = p.pid
-                    (stdout,stderr) = p.communicate()
-                    
-            #Write the output to log file
-            f=open(log_path,"w")
-            f.write(stdout+stderr)
-            f.close()
-
-            #Watchdog for timeout process
-            if self.mswindows:
-                watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
-            else:
-                watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
-            watch.start()
-            watch.cancel() # if it's still waiting to run
-            success = not kill_check.isSet()
-            if not success:
-                raise RuntimeError
-            kill_check.clear()
-        
-            if p.returncode!=0:
-                print('\nAll tests were not successful. Check the test-logs in the jetpack directory.')
-                result_sdk(home_path)
-                #sys.exit(1)
-                raise RuntimeError
-            else:
-                ret_code=result_sdk(home_path)
-                if ret_code==0:
-                    print('\nAll tests were successful. Yay \o/ . Running a sample package test now...')
-                else:
-                    print ('\nThere were errors during the tests.Take a look at logs')
-                    raise RuntimeError
-        except RuntimeError:
-            print "Ending the program"
-            sys.exit(1)
-        except:
-            print "Error during the testall command execution:", sys.exc_info()[0]
-            raise
-        
-    def package(self, example_dir):
-        try:
-            timeout = 30
-    
-            print '\nNow Running packaging tests...'
-    
-            kill_check = threading.Event()
-
-            # Set the path for the example logs. They will be in the parent directory of the Jetpack SDK.
-            exlog_path = example_dir + 'test-example.log'
-            # Subprocess call to test the sample example for packaging.
-            if self.bin!=None:
-                if self.mswindows:
-                    p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data  --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    proc_handle = p._handle
-                    (stdout, stderr) = p.communicate()
-                else:
-                    p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data  --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    pid = p.pid
-                    (stdout, stderr) = p.communicate()
-            elif self.bin==None:
-                if self.mswindows:
-                    p = subprocess.Popen('bin\\activate && cfx run  --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    proc_handle = p._handle
-                    (stdout, stderr) = p.communicate()
-                else:
-                    p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-                    pid = p.pid
-                    (stdout, stderr) = p.communicate()
-            
-            #Write the output to log file
-            f=open(exlog_path,"w")
-            f.write(stdout+stderr)
-            f.close()
-            
-            #Watch dog for timeout process
-            if self.mswindows:
-                watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
-            else:
-                watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
-            watch.start()
-            watch.cancel() # if it's still waiting to run
-            success = not kill_check.isSet()
-            if not success:
-                raise RuntimeError
-            kill_check.clear()
-
-            if p.returncode != 0:
-                print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.')
-                result_example(example_dir)
-                raise RuntimeError
-            else:
-                ret_code=result_example(example_dir)
-                if ret_code==0:
-                    print('\nAll tests pass. The SDK is working! Yay \o/')
-                else:
-                    print ('\nTests passed with warning.Take a look at logs')
-                    sys.exit(1)
-        
-        except RuntimeError:
-            print "Ending program"
-            sys.exit(1)
-        except:
-            print "Error during running sample tests:", sys.exc_info()[0]
-            raise
-    
-def result_sdk(sdk_dir):
-    log_path = sdk_dir + 'tests.log'
-    print 'Results are logged at:' + log_path
-    try:
-        f = open(log_path,'r')
-    # Handles file errors
-    except IOError : 
-        print 'I/O error - Cannot open test log at ' + log_path
-        raise
-
-    for line in reversed(open(log_path).readlines()):
-        if line.strip()=='FAIL':
-            print ('\nOverall result - FAIL. Look at the test log at '+log_path)
-            return 1
-    return 0
-    
-
-def result_example(sdk_dir):
-    exlog_path = sdk_dir + 'test-example.log'
-    print 'Sample test results are logged at:' + exlog_path
-    try:
-        f = open(exlog_path,'r')
-    # Handles file errors
-    except IOError : 
-        print 'I/O error - Cannot open sample test log at ' + exlog_path
-        raise
-    
-    #Read the file in reverse and check for the keyword 'FAIL'.
-    for line in reversed(open(exlog_path).readlines()):
-        if line.strip()=='FAIL':
-            print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path)
-            return 1
-    return 0
-
-def kill_process(process, kill_check, mswindows):
-    print '\nProcess Timedout. Killing the process. Please Rerun this script.'
-    if mswindows:
-        win32api.TerminateProcess(process, -1)
-    else:
-        os.kill(process, signal.SIGKILL)
-    kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process.
-    return
-
-if __name__ == "__main__":
-    obj = SDK()
-    obj.download(obj.link,obj.fpath,obj.fname)
-    obj.extract(obj.base_path,obj.fname)
-    obj.run_testall(obj.base_path,obj.folder_name)
-    obj.package(obj.base_path)
deleted file mode 100644
--- a/addon-sdk/source/bin/jpm-test.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-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 || "";
-    [
-      (!isDebug && /^(firefox-bin)?$/.test(type)) && require.resolve("../bin/node-scripts/test.firefox-bin"),
-      (!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"),
-      (!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"),
-      (/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
-      (!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
-      (!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
-    ].forEach(function(filepath) {
-      filepath && mocha.addFile(filepath);
-    })
-
-    mocha.run(function(failures) {
-      resolve(failures);
-    });
-  });
-}
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/apply-patch.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";
-
-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;
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.addons.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var 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)
-  .filter(fileFilter.bind(null, addonsPath))
-  .forEach(function (file) {
-    it(file, function (done) {
-      var addonPath = path.join(addonsPath, file);
-      process.chdir(addonPath);
-
-      var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }};
-      if (process.env.DISPLAY) {
-        options.env.DISPLAY = process.env.DISPLAY;
-      }
-      if (/^e10s/.test(file)) {
-        options.e10s = true;
-      }
-
-      jpm("run", options).then(done).catch(done);
-    });
-  });
-});
-
-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());
-}
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.docs.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-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();
-      });
-    });
-  });
-});
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.examples.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var utils = require("./utils");
-var path = require("path");
-var fs = require("fs");
-var jpm = utils.run;
-var readParam = utils.readParam;
-
-var examplesPath = path.join(__dirname, "..", "..", "examples");
-
-var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
-var filterPattern = readParam("filter");
-
-describe("jpm test sdk examples", function () {
-  fs.readdirSync(examplesPath)
-  .filter(fileFilter.bind(null, examplesPath))
-  .forEach(function (file) {
-    it(file, function (done) {
-      var addonPath = path.join(examplesPath, file);
-      process.chdir(addonPath);
-
-      var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }};
-      if (process.env.DISPLAY) {
-        options.env.DISPLAY = process.env.DISPLAY;
-      }
-
-      jpm("test", options).then(done);
-    });
-  });
-});
-
-function fileFilter(root, file) {
-  var matcher = filterPattern && new RegExp(filterPattern);
-  if (/^(reading-data)/.test(file)) {
-    return false;
-  }
-  if (matcher && !matcher.test(file)) {
-    return false;
-  }
-  var stat = fs.statSync(path.join(root, file))
-  return (stat && stat.isDirectory());
-}
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.firefox-bin.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var fs = require("fs");
-var Promise = require("promise");
-var chai = require("chai");
-var expect = chai.expect;
-var normalizeBinary = require("fx-runner/lib/utils").normalizeBinary;
-
-//var firefox_binary = process.env["JPM_FIREFOX_BINARY"] || normalizeBinary("nightly");
-
-describe("Checking Firefox binary", function () {
-
-  it("using matching fx-runner version with jpm", function () {
-    var sdkPackageJSON = require("../../package.json");
-    var jpmPackageINI = require("jpm/package.json");
-    expect(sdkPackageJSON.devDependencies["fx-runner"]).to.be.equal(jpmPackageINI.dependencies["fx-runner"]);
-  });
-
-  it("exists", function (done) {
-    var useEnvVar = new Promise(function(resolve) {
-      resolve(process.env["JPM_FIREFOX_BINARY"]);
-    });
-
-    var firefox_binary = process.env["JPM_FIREFOX_BINARY"] ? useEnvVar : normalizeBinary("nightly");
-    firefox_binary.then(function(path) {
-      expect(path).to.be.ok;
-      fs.exists(path, function (exists) {
-        expect(exists).to.be.ok;
-        done();
-      });
-    })
-  });
-
-});
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.ini.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-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");
-var packageINI = path.resolve("./test/jetpack-package.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;
-      }
-      // filter comments
-      var text = data.toString().split("\n").filter(function(line) {
-        return !/^\s*#/.test(line);
-      }).join("\n");
-      var expected = "";
-
-      ini.makeAddonIniContent()
-      .then(function(contents) {
-        expected = contents;
-
-        setTimeout(function end() {
-          expect(text.trim()).to.be.equal(expected.trim());
-          done();
-        });
-      });
-    });
-
-  });
-
-  it("Check test/jetpack-package.ini", function (done) {
-
-    fs.readFile(packageINI, function (err, data) {
-      if (err) {
-        throw err;
-      }
-      // filter comments
-      var text = data.toString().split("\n").filter(function(line) {
-        return !/^\s*#/.test(line);
-      }).join("\n");
-      var expected = "";
-
-      ini.makePackageIniContent()
-      .then(function(contents) {
-        expected = contents;
-
-        setTimeout(function end() {
-          expect(text.trim()).to.be.equal(expected.trim());
-          done();
-        });
-      });
-    });
-
-  });
-
-});
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/test.modules.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var utils = require("./utils");
-var readParam = utils.readParam;
-var path = require("path");
-var fs = require("fs");
-var jpm = utils.run;
-var sdk = path.join(__dirname, "..", "..");
-var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
-
-var filterPattern = readParam("filter");
-
-describe("jpm test sdk modules", function () {
-  it("SDK Modules", function (done) {
-    process.chdir(sdk);
-
-    var options = { cwd: sdk, env: { JPM_FIREFOX_BINARY: binary } };
-    if (process.env.DISPLAY) {
-      options.env.DISPLAY = process.env.DISPLAY;
-    }
-    options.filter = filterPattern;
-
-    jpm("test", options, process).then(done);
-  });
-});
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/update-ini.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var 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/");
-var packageINI = path.resolve("./test/jetpack-package.ini");
-var packageDir = path.resolve("./test/");
-var packageIgnorables = [ "addons", "preferences" ];
-var packageSupportFiles = [
-  "fixtures.js",
-  "test-context-menu.html",
-  "util.js"
-]
-
-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) {
-      // get a list of folders
-      var folders = files.filter(function(file) {
-        return fs.statSync(path.resolve(addonsDir, file)).isDirectory();
-      }).sort();
-
-      // copy any related data from the existing ini
-      folders.forEach(function(folder) {
-        var oldData = data[folder + ".xpi"];
-        result[folder] = oldData ? oldData : {};
-      });
-
-      // build a new 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;
-
-function makePackageIniContent() {
-  return new Promise(function(resolve) {
-    var data = parser.parse(fs.readFileSync(packageINI, { encoding: "utf8" }).toString());
-    var result = {};
-
-    fs.readdir(packageDir, function(err, files) {
-      // get a list of folders
-      var folders = files.filter(function(file) {
-        var ignore = (packageIgnorables.indexOf(file) >= 0);
-        var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
-        return (isDir && !ignore);
-      }).sort();
-
-      // get a list of "test-"" files
-      var files = files.filter(function(file) {
-        var ignore = !/^test\-.*\.js$/i.test(file);
-        var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
-        return (!isDir && !ignore);
-      }).sort();
-
-      // get a list of the support files
-      var support_files = packageSupportFiles.map(function(file) {
-        return "  " + file;
-      });
-      folders.forEach(function(folder) {
-        support_files.push("  " + folder + "/**");
-      });
-      support_files = support_files.sort();
-
-      // copy any related data from the existing ini
-      files.forEach(function(file) {
-        var oldData = data[file];
-        result[file] = oldData ? oldData : {};
-      });
-
-      // build a new ini file
-      var contents = [
-        "[DEFAULT]",
-        "support-files ="
-      ];
-      support_files.forEach(function(support_file) {
-        contents.push(support_file);
-      });
-      contents.push("");
-
-      Object.keys(result).sort().forEach(function(key) {
-        contents.push("[" + key + "]");
-        Object.keys(result[key]).forEach(function(dataKey) {
-          contents.push(dataKey + " = " + result[key][dataKey]);
-        });
-      });
-      contents = contents.join("\n") + "\n";
-
-      return resolve(contents);
-    });
-  });
-}
-exports.makePackageIniContent = makePackageIniContent;
-
-function updatePackageINI() {
-  return new Promise(function(resolve) {
-    console.log("Start updating " + packageINI);
-
-    makeAddonIniContent().
-    then(function(contents) {
-      fs.writeFileSync(packageINI, contents, { encoding: "utf8" });
-      console.log("Done updating " + packageINI);
-      resolve();
-    });
-  })
-}
-exports.updatePackageINI = updatePackageINI;
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/utils.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var _ = require("lodash");
-var path = require("path");
-var child_process = require("child_process");
-var jpm = require.resolve("../../node_modules/jpm/bin/jpm");
-var Promise = require("promise");
-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", "--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 if (!isDebug) {
-      proc.stdout.pipe(DEFAULT_PROCESS.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;
-
-function readParam(name) {
-  var index = process.argv.indexOf("--" + name)
-  return index >= 0 && process.argv[index + 1]
-}
-exports.readParam = readParam;
deleted file mode 100644
--- a/addon-sdk/source/bin/node-scripts/words.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-addon-sdk
-github
-stackoverflow
-bugzilla
-irc
-jsantell
-mossop
-gozala
-zer0
-autonome
-0c0w3
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Actor REPL
-
-Simple REPL for a Firefox debugging protocol.
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/data/codemirror-compressed.js
+++ /dev/null
@@ -1,5 +0,0 @@
-window.CodeMirror=function(){"use strict";function z(a,c){if(!(this instanceof z))return new z(a,c);this.options=c=c||{};for(var d in fd)!c.hasOwnProperty(d)&&fd.hasOwnProperty(d)&&(c[d]=fd[d]);M(c);var e="string"==typeof c.value?0:c.value.first,f=this.display=A(a,e);f.wrapper.CodeMirror=this,J(this),c.autofocus&&!r&&Qb(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new jf},H(this),c.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap");var g=c.value;"string"==typeof g&&(g=new te(c.value,c.mode)),Ib(this,xe)(this,g),b&&setTimeout(tf(Pb,this,!0),20),Tb(this);var h;try{h=document.activeElement==f.input}catch(i){}h||c.autofocus&&!r?setTimeout(tf(rc,this),20):sc(this),Ib(this,function(){for(var a in ed)ed.propertyIsEnumerable(a)&&ed[a](this,c[a],hd);for(var b=0;b<ld.length;++b)ld[b](this)})()}function A(a,b){var d={},e=d.input=zf("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none");return h?e.style.width="1000px":e.setAttribute("wrap","off"),q&&(e.style.border="1px solid black"),e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),e.setAttribute("spellcheck","false"),d.inputDiv=zf("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;"),d.scrollbarH=zf("div",[zf("div",null,null,"height: 1px")],"CodeMirror-hscrollbar"),d.scrollbarV=zf("div",[zf("div",null,null,"width: 1px")],"CodeMirror-vscrollbar"),d.scrollbarFiller=zf("div",null,"CodeMirror-scrollbar-filler"),d.gutterFiller=zf("div",null,"CodeMirror-gutter-filler"),d.lineDiv=zf("div",null,"CodeMirror-code"),d.selectionDiv=zf("div",null,null,"position: relative; z-index: 1"),d.cursor=zf("div","\xa0","CodeMirror-cursor"),d.otherCursor=zf("div","\xa0","CodeMirror-cursor CodeMirror-secondarycursor"),d.measure=zf("div",null,"CodeMirror-measure"),d.lineSpace=zf("div",[d.measure,d.selectionDiv,d.lineDiv,d.cursor,d.otherCursor],null,"position: relative; outline: none"),d.mover=zf("div",[zf("div",[d.lineSpace],"CodeMirror-lines")],null,"position: relative"),d.sizer=zf("div",[d.mover],"CodeMirror-sizer"),d.heightForcer=zf("div",null,null,"position: absolute; height: "+gf+"px; width: 1px;"),d.gutters=zf("div",null,"CodeMirror-gutters"),d.lineGutter=null,d.scroller=zf("div",[d.sizer,d.heightForcer,d.gutters],"CodeMirror-scroll"),d.scroller.setAttribute("tabIndex","-1"),d.wrapper=zf("div",[d.inputDiv,d.scrollbarH,d.scrollbarV,d.scrollbarFiller,d.gutterFiller,d.scroller],"CodeMirror"),c&&(d.gutters.style.zIndex=-1,d.scroller.style.paddingRight=0),a.appendChild?a.appendChild(d.wrapper):a(d.wrapper),q&&(e.style.width="0px"),h||(d.scroller.draggable=!0),m?(d.inputDiv.style.height="1px",d.inputDiv.style.position="absolute"):c&&(d.scrollbarH.style.minWidth=d.scrollbarV.style.minWidth="18px"),d.viewOffset=d.lastSizeC=0,d.showingFrom=d.showingTo=b,d.lineNumWidth=d.lineNumInnerWidth=d.lineNumChars=null,d.prevInput="",d.alignWidgets=!1,d.pollingFast=!1,d.poll=new jf,d.cachedCharWidth=d.cachedTextHeight=d.cachedPaddingH=null,d.measureLineCache=[],d.measureLineCachePos=0,d.inaccurateSelection=!1,d.maxLine=null,d.maxLineLength=0,d.maxLineChanged=!1,d.wheelDX=d.wheelDY=d.wheelStartX=d.wheelStartY=null,d}function B(a){a.doc.mode=z.getMode(a.options,a.doc.modeOption),C(a)}function C(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,eb(a,100),a.state.modeGen++,a.curOp&&Lb(a)}function D(a){a.options.lineWrapping?(a.display.wrapper.className+=" CodeMirror-wrap",a.display.sizer.style.minWidth=""):(a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-wrap",""),L(a)),F(a),Lb(a),sb(a),setTimeout(function(){N(a)},100)}function E(a){var b=Db(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/Eb(a.display)-3);return function(e){if(Sd(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;g<e.widgets.length;g++)e.widgets[g].height&&(f+=e.widgets[g].height);return c?f+(Math.ceil(e.text.length/d)||1)*b:f+b}}function F(a){var b=a.doc,c=E(a);b.iter(function(a){var b=c(a);b!=a.height&&Be(a,b)})}function G(a){var b=qd[a.options.keyMap],c=b.style;a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-keymap-\S+/g,"")+(c?" cm-keymap-"+c:"")}function H(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+a.options.theme.replace(/(^|\s)\s*/g," cm-s-"),sb(a)}function I(a){J(a),Lb(a),setTimeout(function(){P(a)},20)}function J(a){var b=a.display.gutters,c=a.options.gutters;Af(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(zf("div",null,"CodeMirror-gutter "+e));"CodeMirror-linenumbers"==e&&(a.display.lineGutter=f,f.style.width=(a.display.lineNumWidth||1)+"px")}b.style.display=d?"":"none"}function K(a,b){if(0==b.height)return 0;for(var d,c=b.text.length,e=b;d=Od(e);){var f=d.find();e=ye(a,f.from.line),c+=f.from.ch-f.to.ch}for(e=b;d=Pd(e);){var f=d.find();c-=e.text.length-f.from.ch,e=ye(a,f.to.line),c+=e.text.length-f.to.ch}return c}function L(a){var b=a.display,c=a.doc;b.maxLine=ye(c,c.first),b.maxLineLength=K(c,b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var d=K(c,a);d>b.maxLineLength&&(b.maxLineLength=d,b.maxLine=a)})}function M(a){var b=pf(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function N(a){var b=a.display,c=a.doc.height,d=c+jb(b);b.sizer.style.minHeight=b.heightForcer.style.top=d+"px",b.gutters.style.height=Math.max(d,b.scroller.clientHeight-gf)+"px";var e=Math.max(d,b.scroller.scrollHeight),f=b.scroller.scrollWidth>b.scroller.clientWidth+1,g=e>b.scroller.clientHeight+1;g?(b.scrollbarV.style.display="block",b.scrollbarV.style.bottom=f?Hf(b.measure)+"px":"0",b.scrollbarV.firstChild.style.height=Math.max(0,e-b.scroller.clientHeight+b.scrollbarV.clientHeight)+"px"):(b.scrollbarV.style.display="",b.scrollbarV.firstChild.style.height="0"),f?(b.scrollbarH.style.display="block",b.scrollbarH.style.right=g?Hf(b.measure)+"px":"0",b.scrollbarH.firstChild.style.width=b.scroller.scrollWidth-b.scroller.clientWidth+b.scrollbarH.clientWidth+"px"):(b.scrollbarH.style.display="",b.scrollbarH.firstChild.style.width="0"),f&&g?(b.scrollbarFiller.style.display="block",b.scrollbarFiller.style.height=b.scrollbarFiller.style.width=Hf(b.measure)+"px"):b.scrollbarFiller.style.display="",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(b.gutterFiller.style.display="block",b.gutterFiller.style.height=Hf(b.measure)+"px",b.gutterFiller.style.width=b.gutters.offsetWidth+"px"):b.gutterFiller.style.display="",n&&0===Hf(b.measure)&&(b.scrollbarV.style.minWidth=b.scrollbarH.style.minHeight=o?"18px":"12px",b.scrollbarV.style.pointerEvents=b.scrollbarH.style.pointerEvents="none")}function O(a,b,c){var d=a.scroller.scrollTop,e=a.wrapper.clientHeight;"number"==typeof c?d=c:c&&(d=c.top,e=c.bottom-c.top),d=Math.floor(d-ib(a));var f=Math.ceil(d+e);return{from:De(b,d),to:De(b,f)}}function P(a){var b=a.display;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var c=S(b)-b.scroller.scrollLeft+a.doc.scrollLeft,d=b.gutters.offsetWidth,e=c+"px",f=b.lineDiv.firstChild;f;f=f.nextSibling)if(f.alignable)for(var g=0,h=f.alignable;g<h.length;++g)h[g].style.left=e;a.options.fixedGutter&&(b.gutters.style.left=c+d+"px")}}function Q(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=R(a.options,b.first+b.size-1),d=a.display;if(c.length!=d.lineNumChars){var e=d.measure.appendChild(zf("div",[zf("div",c)],"CodeMirror-linenumber CodeMirror-gutter-elt")),f=e.firstChild.offsetWidth,g=e.offsetWidth-f;return d.lineGutter.style.width="",d.lineNumInnerWidth=Math.max(f,d.lineGutter.offsetWidth-g),d.lineNumWidth=d.lineNumInnerWidth+g,d.lineNumChars=d.lineNumInnerWidth?c.length:-1,d.lineGutter.style.width=d.lineNumWidth+"px",!0}return!1}function R(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function S(a){return Df(a.scroller).left-Df(a.sizer).left}function T(a,b,c,d){for(var g,e=a.display.showingFrom,f=a.display.showingTo,h=O(a.display,a.doc,c),i=!0;;i=!1){var j=a.display.scroller.clientWidth;if(!U(a,b,h,d))break;if(g=!0,b=[],ab(a),N(a),i&&a.options.lineWrapping&&j!=a.display.scroller.clientWidth)d=!0;else if(d=!1,c&&(c=Math.min(a.display.scroller.scrollHeight-a.display.scroller.clientHeight,"number"==typeof c?c:c.top)),h=O(a.display,a.doc,c),h.from>=a.display.showingFrom&&h.to<=a.display.showingTo)break}return g&&(bf(a,"update",a),(a.display.showingFrom!=e||a.display.showingTo!=f)&&bf(a,"viewportChange",a,a.display.showingFrom,a.display.showingTo)),g}function U(a,b,c,d){var e=a.display,f=a.doc;if(!e.wrapper.offsetWidth)return e.showingFrom=e.showingTo=f.first,e.viewOffset=0,void 0;if(!(!d&&0==b.length&&c.from>e.showingFrom&&c.to<e.showingTo)){Q(a)&&(b=[{from:f.first,to:f.first+f.size}]);var g=e.sizer.style.marginLeft=e.gutters.offsetWidth+"px";e.scrollbarH.style.left=a.options.fixedGutter?g:"0";var h=1/0;if(a.options.lineNumbers)for(var i=0;i<b.length;++i)b[i].diff&&b[i].from<h&&(h=b[i].from);var j=f.first+f.size,k=Math.max(c.from-a.options.viewportMargin,f.first),l=Math.min(j,c.to+a.options.viewportMargin);if(e.showingFrom<k&&k-e.showingFrom<20&&(k=Math.max(f.first,e.showingFrom)),e.showingTo>l&&e.showingTo-l<20&&(l=Math.min(j,e.showingTo)),y)for(k=Ce(Rd(f,ye(f,k)));j>l&&Sd(f,ye(f,l));)++l;var m=[{from:Math.max(e.showingFrom,f.first),to:Math.min(e.showingTo,j)}];if(m=m[0].from>=m[0].to?[]:X(m,b),y)for(var i=0;i<m.length;++i)for(var o,n=m[i];o=Pd(ye(f,n.to-1));){var p=o.find().from.line;if(!(p>n.from)){m.splice(i--,1);break}n.to=p}for(var q=0,i=0;i<m.length;++i){var n=m[i];n.from<k&&(n.from=k),n.to>l&&(n.to=l),n.from>=n.to?m.splice(i--,1):q+=n.to-n.from}if(!d&&q==l-k&&k==e.showingFrom&&l==e.showingTo)return W(a),void 0;m.sort(function(a,b){return a.from-b.from});try{var r=document.activeElement}catch(s){}.7*(l-k)>q&&(e.lineDiv.style.display="none"),Z(a,k,l,m,h),e.lineDiv.style.display="",r&&document.activeElement!=r&&r.offsetHeight&&r.focus();var t=k!=e.showingFrom||l!=e.showingTo||e.lastSizeC!=e.wrapper.clientHeight;return t&&(e.lastSizeC=e.wrapper.clientHeight,eb(a,400)),e.showingFrom=k,e.showingTo=l,e.gutters.style.height="",V(a),W(a),!0}}function V(a){for(var f,b=a.display,d=b.lineDiv.offsetTop,e=b.lineDiv.firstChild;e;e=e.nextSibling)if(e.lineObj){if(c){var g=e.offsetTop+e.offsetHeight;f=g-d,d=g}else{var h=Df(e);f=h.bottom-h.top}var i=e.lineObj.height-f;if(2>f&&(f=Db(b)),i>.001||-.001>i){Be(e.lineObj,f);var j=e.lineObj.widgets;if(j)for(var k=0;k<j.length;++k)j[k].height=j[k].node.offsetHeight}}}function W(a){var b=a.display.viewOffset=Ee(a,ye(a.doc,a.display.showingFrom));a.display.mover.style.top=b+"px"}function X(a,b){for(var c=0,d=b.length||0;d>c;++c){for(var e=b[c],f=[],g=e.diff||0,h=0,i=a.length;i>h;++h){var j=a[h];e.to<=j.from&&e.diff?f.push({from:j.from+g,to:j.to+g}):e.to<=j.from||e.from>=j.to?f.push(j):(e.from>j.from&&f.push({from:j.from,to:e.from}),e.to<j.to&&f.push({from:e.to+g,to:j.to+g}))}a=f}return a}function Y(a){for(var b=a.display,c={},d={},e=b.gutters.firstChild,f=0;e;e=e.nextSibling,++f)c[a.options.gutters[f]]=e.offsetLeft,d[a.options.gutters[f]]=e.offsetWidth;return{fixedPos:S(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function Z(a,b,c,d,e){function l(b){var c=b.nextSibling;return h&&s&&a.display.currentWheelTarget==b?(b.style.display="none",b.lineObj=null):b.parentNode.removeChild(b),c}var f=Y(a),g=a.display,i=a.options.lineNumbers;d.length||h&&a.display.currentWheelTarget||Af(g.lineDiv);var j=g.lineDiv,k=j.firstChild,m=d.shift(),n=b;for(a.doc.iter(b,c,function(b){if(m&&m.to==n&&(m=d.shift()),Sd(a.doc,b)){if(0!=b.height&&Be(b,0),b.widgets&&k&&k.previousSibling)for(var c=0;c<b.widgets.length;++c){var g=b.widgets[c];if(g.showIfHidden){var h=k.previousSibling;if(/pre/i.test(h.nodeName)){var o=zf("div",null,null,"position: relative");h.parentNode.replaceChild(o,h),o.appendChild(h),h=o}var p=h.appendChild(zf("div",[g.node],"CodeMirror-linewidget"));g.handleMouseEvents||(p.ignoreEvents=!0),_(g,p,h,f)}}}else if(m&&m.from<=n&&m.to>n){for(;k.lineObj!=b;)k=l(k);i&&n>=e&&k.lineNumber&&Cf(k.lineNumber,R(a.options,n)),k=k.nextSibling}else{if(b.widgets)for(var s,q=0,r=k;r&&20>q;++q,r=r.nextSibling)if(r.lineObj==b&&/div/i.test(r.nodeName)){s=r;break}var t=$(a,b,n,f,s);if(t!=s)j.insertBefore(t,k);else{for(;k!=s;)k=l(k);k=k.nextSibling}t.lineObj=b}++n});k;)k=l(k)}function $(a,b,d,e,f){var k,g=ie(a,b),h=g.pre,i=b.gutterMarkers,j=a.display,l=g.bgClass?g.bgClass+" "+(b.bgClass||""):b.bgClass;if(!(a.options.lineNumbers||i||l||b.wrapClass||b.widgets))return h;if(f){f.alignable=null;for(var q,m=!0,n=0,o=null,p=f.firstChild;p;p=q)if(q=p.nextSibling,/\bCodeMirror-linewidget\b/.test(p.className)){for(var r=0;r<b.widgets.length;++r){var s=b.widgets[r];if(s.node==p.firstChild){s.above||o||(o=p),_(s,p,f,e),++n;break}}if(r==b.widgets.length){m=!1;break}}else f.removeChild(p);f.insertBefore(h,o),m&&n==b.widgets.length&&(k=f,f.className=b.wrapClass||"")}if(k||(k=zf("div",null,b.wrapClass,"position: relative"),k.appendChild(h)),l&&k.insertBefore(zf("div",null,l+" CodeMirror-linebackground"),k.firstChild),a.options.lineNumbers||i){var t=k.insertBefore(zf("div",null,"CodeMirror-gutter-wrapper","position: absolute; left: "+(a.options.fixedGutter?e.fixedPos:-e.gutterTotalWidth)+"px"),h);if(a.options.fixedGutter&&(k.alignable||(k.alignable=[])).push(t),!a.options.lineNumbers||i&&i["CodeMirror-linenumbers"]||(k.lineNumber=t.appendChild(zf("div",R(a.options,d),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+e.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+j.lineNumInnerWidth+"px"))),i)for(var u=0;u<a.options.gutters.length;++u){var v=a.options.gutters[u],w=i.hasOwnProperty(v)&&i[v];w&&t.appendChild(zf("div",[w],"CodeMirror-gutter-elt","left: "+e.gutterLeft[v]+"px; width: "+e.gutterWidth[v]+"px"))}}if(c&&(k.style.zIndex=2),b.widgets&&k!=f)for(var r=0,x=b.widgets;r<x.length;++r){var s=x[r],y=zf("div",[s.node],"CodeMirror-linewidget");s.handleMouseEvents||(y.ignoreEvents=!0),_(s,y,k,e),s.above?k.insertBefore(y,a.options.lineNumbers&&0!=b.height?t:h):k.appendChild(y),bf(s,"redraw")}return k}function _(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+"px",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+"px"),b.style.width=e+"px"}a.coverGutter&&(b.style.zIndex=5,b.style.position="relative",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+"px"))}function ab(a){var b=a.display,c=Hc(a.doc.sel.from,a.doc.sel.to);if(c||a.options.showCursorWhenSelecting?bb(a):b.cursor.style.display=b.otherCursor.style.display="none",c?b.selectionDiv.style.display="none":cb(a),a.options.moveInputWithCursor){var d=yb(a,a.doc.sel.head,"div"),e=Df(b.wrapper),f=Df(b.lineDiv);b.inputDiv.style.top=Math.max(0,Math.min(b.wrapper.clientHeight-10,d.top+f.top-e.top))+"px",b.inputDiv.style.left=Math.max(0,Math.min(b.wrapper.clientWidth-10,d.left+f.left-e.left))+"px"}}function bb(a){var b=a.display,c=yb(a,a.doc.sel.head,"div");b.cursor.style.left=c.left+"px",b.cursor.style.top=c.top+"px",b.cursor.style.height=Math.max(0,c.bottom-c.top)*a.options.cursorHeight+"px",b.cursor.style.display="",c.other?(b.otherCursor.style.display="",b.otherCursor.style.left=c.other.left+"px",b.otherCursor.style.top=c.other.top+"px",b.otherCursor.style.height=.85*(c.other.bottom-c.other.top)+"px"):b.otherCursor.style.display="none"}function cb(a){function i(a,b,c,d){0>b&&(b=0),e.appendChild(zf("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?h-a:c)+"px; height: "+(d-b)+"px"))}function j(b,d,e){function m(c,d){return xb(a,Gc(b,c),"div",f,d)}var k,l,f=ye(c,b),j=f.text.length;return Of(Fe(f),d||0,null==e?j:e,function(a,b,c){var n,o,p,f=m(a,"left");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,"right"),"rtl"==c){var q=f;f=n,n=q}o=f.left,p=n.right}null==d&&0==a&&(o=g),n.top-f.top>3&&(i(o,f.top,null,f.bottom),o=g,f.bottom<n.top&&i(o,f.bottom,null,n.top)),null==e&&b==j&&(p=h),(!k||f.top<k.top||f.top==k.top&&f.left<k.left)&&(k=f),(!l||n.bottom>l.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),g+1>o&&(o=g),i(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var b=a.display,c=a.doc,d=a.doc.sel,e=document.createDocumentFragment(),f=kb(a.display),g=f.left,h=b.lineSpace.offsetWidth-f.right;if(d.from.line==d.to.line)j(d.from.line,d.from.ch,d.to.ch);else{var k=ye(c,d.from.line),l=ye(c,d.to.line),m=Rd(c,k)==Rd(c,l),n=j(d.from.line,d.from.ch,m?k.text.length:null).end,o=j(d.to.line,m?0:null,d.to.ch).start;m&&(n.top<o.top-2?(i(n.right,n.top,null,n.bottom),i(g,o.top,o.left,o.bottom)):i(n.right,n.top,o.left-n.right,n.bottom)),n.bottom<o.top&&i(g,n.bottom,null,o.top)}Bf(b.selectionDiv,e),b.selectionDiv.style.display=""}function db(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursor.style.visibility=b.otherCursor.style.visibility="",a.options.cursorBlinkRate>0&&(b.blinker=setInterval(function(){b.cursor.style.visibility=b.otherCursor.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate))}}function eb(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.showingTo&&a.state.highlight.set(b,tf(fb,a))}function fb(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.showingTo)){var f,c=+new Date+a.options.workTime,d=nd(b.mode,hb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.showingTo+500),function(g){if(b.frontier>=a.display.showingFrom){var h=g.styles;g.styles=ce(a,g,d,!0);for(var i=!h||h.length!=g.styles.length,j=0;!i&&j<h.length;++j)i=h[j]!=g.styles[j];i&&(f&&f.end==b.frontier?f.end++:e.push(f={start:b.frontier,end:b.frontier+1})),g.stateAfter=nd(b.mode,d)}else ee(a,g.text,d),g.stateAfter=0==b.frontier%5?nd(b.mode,d):null;return++b.frontier,+new Date>c?(eb(a,a.options.workDelay),!0):void 0}),e.length&&Ib(a,function(){for(var a=0;a<e.length;++a)Lb(this,e[a].start,e[a].end)})()}}function gb(a,b,c){for(var d,e,f=a.doc,g=c?-1:b-(a.doc.mode.innerMode?1e3:100),h=b;h>g;--h){if(h<=f.first)return f.first;var i=ye(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=kf(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function hb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=gb(a,b,c),g=f>d.first&&ye(d,f-1).stateAfter;return g=g?nd(d.mode,g):od(d.mode),d.iter(f,b,function(c){ee(a,c.text,g);var h=f==b-1||0==f%5||f>=e.showingFrom&&f<e.showingTo;c.stateAfter=h?nd(d.mode,g):null,++f}),c&&(d.frontier=f),g}function ib(a){return a.lineSpace.offsetTop}function jb(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function kb(a){if(a.cachedPaddingH)return a.cachedPaddingH;var b=Bf(a.measure,zf("pre","x")),c=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle;return a.cachedPaddingH={left:parseInt(c.paddingLeft),right:parseInt(c.paddingRight)}}function lb(a,b,c,d,e){var f=-1;if(d=d||ob(a,b),d.crude){var g=d.left+c*d.width;return{left:g,right:g+d.width,top:d.top,bottom:d.bottom}}for(var h=c;;h+=f){var i=d[h];if(i)break;0>f&&0==h&&(f=1)}return e=h>c?"left":c>h?"right":e,"left"==e&&i.leftSide?i=i.leftSide:"right"==e&&i.rightSide&&(i=i.rightSide),{left:c>h?i.right:i.left,right:h>c?i.left:i.right,top:i.top,bottom:i.bottom}}function mb(a,b){for(var c=a.display.measureLineCache,d=0;d<c.length;++d){var e=c[d];if(e.text==b.text&&e.markedSpans==b.markedSpans&&a.display.scroller.clientWidth==e.width&&e.classes==b.textClass+"|"+b.wrapClass)return e}}function nb(a,b){var c=mb(a,b);c&&(c.text=c.measure=c.markedSpans=null)}function ob(a,b){var c=mb(a,b);if(c)return c.measure;var d=pb(a,b),e=a.display.measureLineCache,f={text:b.text,width:a.display.scroller.clientWidth,markedSpans:b.markedSpans,measure:d,classes:b.textClass+"|"+b.wrapClass};return 16==e.length?e[++a.display.measureLineCachePos%16]=f:e.push(f),d}function pb(a,e){function t(a){var b=a.top-p.top,c=a.bottom-p.top;c>s&&(c=s),0>b&&(b=0);for(var d=q.length-2;d>=0;d-=2){var e=q[d],f=q[d+1];if(!(e>c||b>f)&&(b>=e&&f>=c||e>=b&&c>=f||Math.min(c,f)-Math.max(b,e)>=c-b>>1)){q[d]=Math.min(b,e),q[d+1]=Math.max(c,f);break}}return 0>d&&(d=q.length,q.push(b,c)),{left:a.left-p.left,right:a.right-p.left,top:d,bottom:null}}function u(a){a.bottom=q[a.top+1],a.top=q[a.top]}if(!a.options.lineWrapping&&e.text.length>=a.options.crudeMeasuringFrom)return qb(a,e);var f=a.display,g=sf(e.text.length),h=ie(a,e,g,!0).pre;if(b&&!c&&!a.options.lineWrapping&&h.childNodes.length>100){for(var i=document.createDocumentFragment(),j=10,k=h.childNodes.length,l=0,m=Math.ceil(k/j);m>l;++l){for(var n=zf("div",null,null,"display: inline-block"),o=0;j>o&&k;++o)n.appendChild(h.firstChild),--k;i.appendChild(n)}h.appendChild(i)}Bf(f.measure,h);var p=Df(f.lineDiv),q=[],r=sf(e.text.length),s=h.offsetHeight;d&&f.measure.first!=h&&Bf(f.measure,h);for(var v,l=0;l<g.length;++l)if(v=g[l]){var w=v,x=null;if(/\bCodeMirror-widget\b/.test(v.className)&&v.getClientRects){1==v.firstChild.nodeType&&(w=v.firstChild);var y=w.getClientRects();y.length>1&&(x=r[l]=t(y[0]),x.rightSide=t(y[y.length-1]))}x||(x=r[l]=t(Df(w))),v.measureRight&&(x.right=Df(v.measureRight).left-p.left),v.leftSide&&(x.leftSide=t(Df(v.leftSide)))}Af(a.display.measure);for(var v,l=0;l<r.length;++l)(v=r[l])&&(u(v),v.leftSide&&u(v.leftSide),v.rightSide&&u(v.rightSide));return r}function qb(a,b){var c=new $d(b.text.slice(0,100),null);b.textClass&&(c.textClass=b.textClass);var d=pb(a,c),e=lb(a,c,0,d,"left"),f=lb(a,c,99,d,"right");return{crude:!0,top:e.top,left:e.left,bottom:e.bottom,width:(f.right-e.left)/100}}function rb(a,b){var c=!1;if(b.markedSpans)for(var d=0;d<b.markedSpans;++d){var e=b.markedSpans[d];!e.collapsed||null!=e.to&&e.to!=b.text.length||(c=!0)}var f=!c&&mb(a,b);if(f||b.text.length>=a.options.crudeMeasuringFrom)return lb(a,b,b.text.length,f&&f.measure,"right").right;var g=ie(a,b,null,!0).pre,h=g.appendChild(Jf(a.display.measure));Bf(a.display.measure,g);var i=Df(h);return 0==i.right&&0==i.bottom&&(h=g.appendChild(zf("span","\xa0")),i=Df(h)),i.left-Df(a.display.lineDiv).left}function sb(a){a.display.measureLineCache.length=a.display.measureLineCachePos=0,a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function tb(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function ub(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function vb(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=Yd(b.widgets[e]);c.top+=f,c.bottom+=f}if("line"==d)return c;d||(d="local");var g=Ee(a,b);if("local"==d?g+=ib(a.display):g-=a.display.viewOffset,"page"==d||"window"==d){var h=Df(a.display.lineSpace);g+=h.top+("window"==d?0:ub());var i=h.left+("window"==d?0:tb());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function wb(a,b,c){if("div"==c)return b;var d=b.left,e=b.top;if("page"==c)d-=tb(),e-=ub();else if("local"==c||!c){var f=Df(a.display.sizer);d+=f.left,e+=f.top}var g=Df(a.display.lineSpace);return{left:d-g.left,top:e-g.top}}function xb(a,b,c,d,e){return d||(d=ye(a.doc,b.line)),vb(a,d,lb(a,d,b.ch,null,e),c)}function yb(a,b,c,d,e){function f(b,f){var g=lb(a,d,b,e,f?"right":"left");return f?g.left=g.right:g.right=g.left,vb(a,d,g,c)}function g(a,b){var c=h[b],d=c.level%2;return a==Pf(c)&&b&&c.level<h[b-1].level?(c=h[--b],a=Qf(c)-(c.level%2?0:1),d=!0):a==Qf(c)&&b<h.length-1&&c.level<h[b+1].level&&(c=h[++b],a=Pf(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?f(a-1):f(a,d)}d=d||ye(a.doc,b.line),e||(e=ob(a,d));var h=Fe(d),i=b.ch;if(!h)return f(i);var j=Xf(h,i),k=g(i,j);return null!=Wf&&(k.other=g(i,Wf)),k}function zb(a,b,c,d){var e=new Gc(a,b);return e.xRel=d,c&&(e.outside=!0),e}function Ab(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return zb(d.first,0,!0,-1);var e=De(d,c),f=d.first+d.size-1;if(e>f)return zb(d.first+d.size-1,ye(d,f).text.length,!0,1);for(0>b&&(b=0);;){var g=ye(d,e),h=Bb(a,g,e,b,c),i=Pd(g),j=i&&i.find();if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=j.to.line}}function Bb(a,b,c,d,e){function j(d){var e=yb(a,Gc(c,d),"line",b,i);return g=!0,f>e.bottom?e.left-h:f<e.top?e.left+h:(g=!1,e.left)}var f=e-Ee(a,b),g=!1,h=2*a.display.wrapper.clientWidth,i=ob(a,b),k=Fe(b),l=b.text.length,m=Rf(b),n=Sf(b),o=j(m),p=g,q=j(n),r=g;if(d>q)return zb(c,n,r,1);for(;;){if(k?n==m||n==Zf(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);yf(b.text.charAt(s));)++s;var u=zb(c,s,s==m?p:r,0>t?-1:t?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=Zf(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function Db(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Cb){Cb=zf("pre");for(var b=0;49>b;++b)Cb.appendChild(document.createTextNode("x")),Cb.appendChild(zf("br"));Cb.appendChild(document.createTextNode("x"))}Bf(a.measure,Cb);var c=Cb.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),Af(a.measure),c||1}function Eb(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=zf("span","x"),c=zf("pre",[b]);Bf(a.measure,c);var d=b.offsetWidth;return d>2&&(a.cachedCharWidth=d),d||10}function Gb(a){a.curOp={changes:[],forceUpdate:!1,updateInput:null,userSelChange:null,textChanged:null,selectionChanged:!1,cursorActivity:!1,updateMaxLine:!1,updateScrollPos:!1,id:++Fb},af++||(_e=[])}function Hb(a){var b=a.curOp,c=a.doc,d=a.display;if(a.curOp=null,b.updateMaxLine&&L(a),d.maxLineChanged&&!a.options.lineWrapping&&d.maxLine){var e=rb(a,d.maxLine);d.sizer.style.minWidth=Math.max(0,e+3)+"px",d.maxLineChanged=!1;var f=Math.max(0,d.sizer.offsetLeft+d.sizer.offsetWidth-d.scroller.clientWidth);f<c.scrollLeft&&!b.updateScrollPos&&ec(a,Math.min(d.scroller.scrollLeft,f),!0)}var g,h;if(b.updateScrollPos)g=b.updateScrollPos;else if(b.selectionChanged&&d.scroller.clientHeight){var i=yb(a,c.sel.head);g=Xc(a,i.left,i.top,i.left,i.bottom)}if((b.changes.length||b.forceUpdate||g&&null!=g.scrollTop)&&(h=T(a,b.changes,g&&g.scrollTop,b.forceUpdate),a.display.scroller.offsetHeight&&(a.doc.scrollTop=a.display.scroller.scrollTop)),!h&&b.selectionChanged&&ab(a),b.updateScrollPos){var j=Math.max(0,Math.min(d.scroller.scrollHeight-d.scroller.clientHeight,g.scrollTop)),k=Math.max(0,Math.min(d.scroller.scrollWidth-d.scroller.clientWidth,g.scrollLeft));d.scroller.scrollTop=d.scrollbarV.scrollTop=c.scrollTop=j,d.scroller.scrollLeft=d.scrollbarH.scrollLeft=c.scrollLeft=k,P(a),b.scrollToPos&&Vc(a,Mc(a.doc,b.scrollToPos.from),Mc(a.doc,b.scrollToPos.to),b.scrollToPos.margin)}else g&&Uc(a);b.selectionChanged&&db(a),a.state.focused&&b.updateInput&&Pb(a,b.userSelChange);var l=b.maybeHiddenMarkers,m=b.maybeUnhiddenMarkers;if(l)for(var n=0;n<l.length;++n)l[n].lines.length||$e(l[n],"hide");if(m)for(var n=0;n<m.length;++n)m[n].lines.length&&$e(m[n],"unhide");var o;if(--af||(o=_e,_e=null),b.textChanged&&$e(a,"change",a,b.textChanged),b.cursorActivity&&$e(a,"cursorActivity",a),o)for(var n=0;n<o.length;++n)o[n]()}function Ib(a,b){return function(){var c=a||this,d=!c.curOp;d&&Gb(c);try{var e=b.apply(c,arguments)}finally{d&&Hb(c)}return e}}function Jb(a){return function(){var c,b=this.cm&&!this.cm.curOp;b&&Gb(this.cm);try{c=a.apply(this,arguments)}finally{b&&Hb(this.cm)}return c}}function Kb(a,b){var d,c=!a.curOp;c&&Gb(a);try{d=b()}finally{c&&Hb(a)}return d}function Lb(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),a.curOp.changes.push({from:b,to:c,diff:d})}function Mb(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){Ob(a),a.state.focused&&Mb(a)})}function Nb(a){function c(){var d=Ob(a);d||b?(a.display.pollingFast=!1,Mb(a)):(b=!0,a.display.poll.set(60,c))}var b=!1;a.display.pollingFast=!0,a.display.poll.set(20,c)}function Ob(a){var b=a.display.input,c=a.display.prevInput,e=a.doc,f=e.sel;if(!a.state.focused||Lf(b)||Sb(a)||a.options.disableInput)return!1;a.state.pasteIncoming&&a.state.fakedLastChar&&(b.value=b.value.substring(0,b.value.length-1),a.state.fakedLastChar=!1);var h=b.value;if(h==c&&Hc(f.from,f.to))return!1;if(g&&!d&&a.display.inputHasSelection===h)return Pb(a,!0),!1;var i=!a.curOp;i&&Gb(a),f.shift=!1;for(var j=0,k=Math.min(c.length,h.length);k>j&&c.charCodeAt(j)==h.charCodeAt(j);)++j;var l=f.from,m=f.to,n=h.slice(j);j<c.length?l=Gc(l.line,l.ch-(c.length-j)):a.state.overwrite&&Hc(l,m)&&!a.state.pasteIncoming&&(m=Gc(m.line,Math.min(ye(e,m.line).text.length,m.ch+n.length)));var o=a.curOp.updateInput,p={from:l,to:m,text:Kf(n),origin:a.state.pasteIncoming?"paste":a.state.cutIncoming?"cut":"+input"};if(zc(a.doc,p,"end"),a.curOp.updateInput=o,bf(a,"inputRead",a,p),n&&!a.state.pasteIncoming&&a.options.electricChars&&a.options.smartIndent&&f.head.ch<100){var q=a.getModeAt(f.head).electricChars;if(q)for(var r=0;r<q.length;r++)if(n.indexOf(q.charAt(r))>-1){$c(a,f.head.line,"smart");break}}return h.length>1e3||h.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=h,i&&Hb(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function Pb(a,b){var c,e,f=a.doc;if(Hc(f.sel.from,f.sel.to))b&&(a.display.prevInput=a.display.input.value="",g&&!d&&(a.display.inputHasSelection=null));else{a.display.prevInput="",c=Mf&&(f.sel.to.line-f.sel.from.line>100||(e=a.getSelection()).length>1e3);var h=c?"-":e||a.getSelection();a.display.input.value=h,a.state.focused&&of(a.display.input),g&&!d&&(a.display.inputHasSelection=h)}a.display.inaccurateSelection=c}function Qb(a){"nocursor"==a.options.readOnly||r&&document.activeElement==a.display.input||a.display.input.focus()}function Rb(a){a.state.focused||(Qb(a),rc(a))}function Sb(a){return a.options.readOnly||a.doc.cantEdit}function Tb(a){function e(){a.state.focused&&setTimeout(tf(Qb,a),0)}function i(){null==f&&(f=setTimeout(function(){f=null,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=Gf=null,sb(a),Kb(a,tf(Lb,a))},100))}function j(){for(var a=c.wrapper.parentNode;a&&a!=document.body;a=a.parentNode);a?setTimeout(j,5e3):Ze(window,"resize",i)}function k(b){cf(a,b)||a.options.onDragEvent&&a.options.onDragEvent(a,Re(b))||Ve(b)}function l(b){c.inaccurateSelection&&(c.prevInput="",c.inaccurateSelection=!1,c.input.value=a.getSelection(),of(c.input)),"cut"==b.type&&(a.state.cutIncoming=!0)}var c=a.display;Ye(c.scroller,"mousedown",Ib(a,Yb)),b?Ye(c.scroller,"dblclick",Ib(a,function(b){if(!cf(a,b)){var c=Vb(a,b);if(c&&!_b(a,b)&&!Ub(a.display,b)){Se(b);var d=cd(ye(a.doc,c.line).text,c);Pc(a.doc,d.from,d.to)}}})):Ye(c.scroller,"dblclick",function(b){cf(a,b)||Se(b)}),Ye(c.lineSpace,"selectstart",function(a){Ub(c,a)||Se(a)}),w||Ye(c.scroller,"contextmenu",function(b){uc(a,b)}),Ye(c.scroller,"scroll",function(){c.scroller.clientHeight&&(dc(a,c.scroller.scrollTop),ec(a,c.scroller.scrollLeft,!0),$e(a,"scroll",a))}),Ye(c.scrollbarV,"scroll",function(){c.scroller.clientHeight&&dc(a,c.scrollbarV.scrollTop)}),Ye(c.scrollbarH,"scroll",function(){c.scroller.clientHeight&&ec(a,c.scrollbarH.scrollLeft)}),Ye(c.scroller,"mousewheel",function(b){hc(a,b)}),Ye(c.scroller,"DOMMouseScroll",function(b){hc(a,b)}),Ye(c.scrollbarH,"mousedown",e),Ye(c.scrollbarV,"mousedown",e),Ye(c.wrapper,"scroll",function(){c.wrapper.scrollTop=c.wrapper.scrollLeft=0});var f;Ye(window,"resize",i),setTimeout(j,5e3),Ye(c.input,"keyup",Ib(a,nc)),Ye(c.input,"input",function(){g&&!d&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),Nb(a)}),Ye(c.input,"keydown",Ib(a,pc)),Ye(c.input,"keypress",Ib(a,qc)),Ye(c.input,"focus",tf(rc,a)),Ye(c.input,"blur",tf(sc,a)),a.options.dragDrop&&(Ye(c.scroller,"dragstart",function(b){cc(a,b)}),Ye(c.scroller,"dragenter",k),Ye(c.scroller,"dragover",k),Ye(c.scroller,"drop",Ib(a,bc))),Ye(c.scroller,"paste",function(b){Ub(c,b)||(Qb(a),Nb(a))}),Ye(c.input,"paste",function(){if(h&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var b=c.input.selectionStart,d=c.input.selectionEnd;
-c.input.value+="$",c.input.selectionStart=b,c.input.selectionEnd=d,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,Nb(a)}),Ye(c.input,"cut",l),Ye(c.input,"copy",l),m&&Ye(c.sizer,"mouseup",function(){document.activeElement==c.input&&c.input.blur(),Qb(a)})}function Ub(a,b){for(var c=We(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function Vb(a,b,c){var d=a.display;if(!c){var e=We(b);if(e==d.scrollbarH||e==d.scrollbarH.firstChild||e==d.scrollbarV||e==d.scrollbarV.firstChild||e==d.scrollbarFiller||e==d.gutterFiller)return null}var f,g,h=Df(d.lineSpace);try{f=b.clientX,g=b.clientY}catch(b){return null}return Ab(a,f-h.left,g-h.top)}function Yb(a){function t(a){if(!Hc(s,a)){if(s=a,"single"==m)return Pc(c.doc,Mc(i,k),a),void 0;if(q=Mc(i,q),r=Mc(i,r),"double"==m){var b=cd(ye(i,a.line).text,a);Ic(a,q)?Pc(c.doc,b.from,r):Pc(c.doc,q,b.to)}else"triple"==m&&(Ic(a,q)?Pc(c.doc,r,Mc(i,Gc(a.line,0))):Pc(c.doc,q,Mc(i,Gc(a.line+1,0))))}}function x(a){var b=++v,d=Vb(c,a,!0);if(d)if(Hc(d,o)){var g=a.clientY<u.top?-20:a.clientY>u.bottom?20:0;g&&setTimeout(Ib(c,function(){v==b&&(f.scroller.scrollTop+=g,x(a))}),50)}else{Rb(c),o=d,t(d);var e=O(f,i);(d.line>=e.to||d.line<e.from)&&setTimeout(Ib(c,function(){v==b&&x(a)}),150)}}function y(a){v=1/0,Se(a),Qb(c),Ze(document,"mousemove",z),Ze(document,"mouseup",A)}if(!cf(this,a)){var c=this,f=c.display,i=c.doc,j=i.sel;if(j.shift=a.shiftKey,Ub(f,a))return h||(f.scroller.draggable=!1,setTimeout(function(){f.scroller.draggable=!0},100)),void 0;if(!_b(c,a)){var k=Vb(c,a);switch(window.focus(),Xe(a)){case 3:return w&&uc.call(c,c,a),void 0;case 2:return h&&(c.state.lastMiddleDown=+new Date),k&&Pc(c.doc,k),setTimeout(tf(Qb,c),20),Se(a),void 0}if(!k)return We(a)==f.scroller&&Se(a),void 0;setTimeout(tf(Rb,c),0);var l=+new Date,m="single";if(Xb&&Xb.time>l-400&&Hc(Xb.pos,k))m="triple",Se(a),setTimeout(tf(Qb,c),20),dd(c,k.line);else if(Wb&&Wb.time>l-400&&Hc(Wb.pos,k)){m="double",Xb={time:l,pos:k},Se(a);var n=cd(ye(i,k.line).text,k);Pc(c.doc,n.from,n.to)}else Wb={time:l,pos:k};var o=k;if(c.options.dragDrop&&Ef&&!Sb(c)&&!Hc(j.from,j.to)&&!Ic(k,j.from)&&!Ic(j.to,k)&&"single"==m){var p=Ib(c,function(e){h&&(f.scroller.draggable=!1),c.state.draggingText=!1,Ze(document,"mouseup",p),Ze(f.scroller,"drop",p),Math.abs(a.clientX-e.clientX)+Math.abs(a.clientY-e.clientY)<10&&(Se(e),Pc(c.doc,k),Qb(c),b&&!d&&setTimeout(function(){document.body.focus(),Qb(c)},20))});return h&&(f.scroller.draggable=!0),c.state.draggingText=p,f.scroller.dragDrop&&f.scroller.dragDrop(),Ye(document,"mouseup",p),Ye(f.scroller,"drop",p),void 0}Se(a),"single"==m&&Pc(c.doc,Mc(i,k));var q=j.from,r=j.to,s=k,u=Df(f.wrapper),v=0,z=Ib(c,function(a){(g&&!e?a.buttons:Xe(a))?x(a):y(a)}),A=Ib(c,y);Ye(document,"mousemove",z),Ye(document,"mouseup",A)}}}function Zb(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(Df(a.display.gutters).right))return!1;d&&Se(b);var h=a.display,i=Df(h.lineDiv);if(g>i.bottom||!ef(a,c))return Ue(b);g-=i.top-h.viewOffset;for(var j=0;j<a.options.gutters.length;++j){var k=h.gutters.childNodes[j];if(k&&Df(k).right>=f){var l=De(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),Ue(b)}}}function $b(a,b){return ef(a,"gutterContextMenu")?Zb(a,b,"gutterContextMenu",!1,$e):!1}function _b(a,b){return Zb(a,b,"gutterClick",!0,bf)}function bc(a){var b=this;if(!(cf(b,a)||Ub(b.display,a)||b.options.onDragEvent&&b.options.onDragEvent(b,Re(a)))){Se(a),g&&(ac=+new Date);var c=Vb(b,a,!0),d=a.dataTransfer.files;if(c&&!Sb(b))if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),h=0,i=function(a,d){var g=new FileReader;g.onload=function(){f[d]=g.result,++h==e&&(c=Mc(b.doc,c),zc(b.doc,{from:c,to:c,text:Kf(f.join("\n")),origin:"paste"},"around"))},g.readAsText(a)},j=0;e>j;++j)i(d[j],j);else{if(b.state.draggingText&&!Ic(c,b.doc.sel.from)&&!Ic(b.doc.sel.to,c))return b.state.draggingText(a),setTimeout(tf(Qb,b),20),void 0;try{var f=a.dataTransfer.getData("Text");if(f){var k=b.doc.sel.from,l=b.doc.sel.to;Rc(b.doc,c,c),b.state.draggingText&&Fc(b.doc,"",k,l,"paste"),b.replaceSelection(f,null,"paste"),Qb(b)}}catch(a){}}}}function cc(a,b){if(g&&(!a.state.draggingText||+new Date-ac<100))return Ve(b),void 0;if(!cf(a,b)&&!Ub(a.display,b)){var c=a.getSelection();if(b.dataTransfer.setData("Text",c),b.dataTransfer.setDragImage&&!l){var d=zf("img",null,null,"position: fixed; left: 0; top: 0;");d.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",k&&(d.width=d.height=1,a.display.wrapper.appendChild(d),d._top=d.offsetTop),b.dataTransfer.setDragImage(d,0,0),k&&d.parentNode.removeChild(d)}}}function dc(b,c){Math.abs(b.doc.scrollTop-c)<2||(b.doc.scrollTop=c,a||T(b,[],c),b.display.scroller.scrollTop!=c&&(b.display.scroller.scrollTop=c),b.display.scrollbarV.scrollTop!=c&&(b.display.scrollbarV.scrollTop=c),a&&T(b,[]),eb(b,100))}function ec(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),a.doc.scrollLeft=b,P(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function hc(b,c){var d=c.wheelDeltaX,e=c.wheelDeltaY;null==d&&c.detail&&c.axis==c.HORIZONTAL_AXIS&&(d=c.detail),null==e&&c.detail&&c.axis==c.VERTICAL_AXIS?e=c.detail:null==e&&(e=c.wheelDelta);var f=b.display,g=f.scroller;if(d&&g.scrollWidth>g.clientWidth||e&&g.scrollHeight>g.clientHeight){if(e&&s&&h)for(var i=c.target;i!=g;i=i.parentNode)if(i.lineObj){b.display.currentWheelTarget=i;break}if(d&&!a&&!k&&null!=gc)return e&&dc(b,Math.max(0,Math.min(g.scrollTop+e*gc,g.scrollHeight-g.clientHeight))),ec(b,Math.max(0,Math.min(g.scrollLeft+d*gc,g.scrollWidth-g.clientWidth))),Se(c),f.wheelStartX=null,void 0;if(e&&null!=gc){var j=e*gc,l=b.doc.scrollTop,m=l+f.wrapper.clientHeight;0>j?l=Math.max(0,l+j-50):m=Math.min(b.doc.height,m+j+50),T(b,[],{top:l,bottom:m})}20>fc&&(null==f.wheelStartX?(f.wheelStartX=g.scrollLeft,f.wheelStartY=g.scrollTop,f.wheelDX=d,f.wheelDY=e,setTimeout(function(){if(null!=f.wheelStartX){var a=g.scrollLeft-f.wheelStartX,b=g.scrollTop-f.wheelStartY,c=b&&f.wheelDY&&b/f.wheelDY||a&&f.wheelDX&&a/f.wheelDX;f.wheelStartX=f.wheelStartY=null,c&&(gc=(gc*fc+c)/(fc+1),++fc)}},200)):(f.wheelDX+=d,f.wheelDY+=e))}}function ic(a,b,c){if("string"==typeof b&&(b=pd[b],!b))return!1;a.display.pollingFast&&Ob(a)&&(a.display.pollingFast=!1);var d=a.doc,e=d.sel.shift,f=!1;try{Sb(a)&&(a.state.suppressEdits=!0),c&&(d.sel.shift=!1),f=b(a)!=hf}finally{d.sel.shift=e,a.state.suppressEdits=!1}return f}function jc(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function lc(a,b){var c=rd(a.options.keyMap),e=c.auto;clearTimeout(kc),e&&!td(b)&&(kc=setTimeout(function(){rd(a.options.keyMap)==c&&(a.options.keyMap=e.call?e.call(null,a):e,G(a))},50));var f=ud(b,!0),g=!1;if(!f)return!1;var h=jc(a);return g=b.shiftKey?sd("Shift-"+f,h,function(b){return ic(a,b,!0)})||sd(f,h,function(b){return("string"==typeof b?/^go[A-Z]/.test(b):b.motion)?ic(a,b):void 0}):sd(f,h,function(b){return ic(a,b)}),g&&(Se(b),db(a),d&&(b.oldKeyCode=b.keyCode,b.keyCode=0),bf(a,"keyHandled",a,f,b)),g}function mc(a,b,c){var d=sd("'"+c+"'",jc(a),function(b){return ic(a,b,!0)});return d&&(Se(b),db(a),bf(a,"keyHandled",a,"'"+c+"'",b)),d}function nc(a){var b=this;cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a))||16==a.keyCode&&(b.doc.sel.shift=!1)}function pc(a){var c=this;if(Rb(c),!(cf(c,a)||c.options.onKeyEvent&&c.options.onKeyEvent(c,Re(a)))){b&&27==a.keyCode&&(a.returnValue=!1);var d=a.keyCode;c.doc.sel.shift=16==d||a.shiftKey;var e=lc(c,a);k&&(oc=e?d:null,!e&&88==d&&!Mf&&(s?a.metaKey:a.ctrlKey)&&c.replaceSelection(""))}}function qc(a){var b=this;if(!(cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a)))){var c=a.keyCode,e=a.charCode;if(k&&c==oc)return oc=null,Se(a),void 0;if(!(k&&(!a.which||a.which<10)||m)||!lc(b,a)){var f=String.fromCharCode(null==e?c:e);mc(b,a,f)||(g&&!d&&(b.display.inputHasSelection=null),Nb(b))}}}function rc(a){"nocursor"!=a.options.readOnly&&(a.state.focused||($e(a,"focus",a),a.state.focused=!0,-1==a.display.wrapper.className.search(/\bCodeMirror-focused\b/)&&(a.display.wrapper.className+=" CodeMirror-focused"),a.curOp||(Pb(a,!0),h&&setTimeout(tf(Pb,a,!0),0))),Mb(a),db(a))}function sc(a){a.state.focused&&($e(a,"blur",a),a.state.focused=!1,a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-focused","")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.doc.sel.shift=!1)},150)}function uc(a,b){function l(){if(null!=c.input.selectionStart){var a=c.input.value="\u200b"+(Hc(e.from,e.to)?"":c.input.value);c.prevInput="\u200b",c.input.selectionStart=1,c.input.selectionEnd=a.length}}function m(){if(c.inputDiv.style.position="relative",c.input.style.cssText=j,d&&(c.scrollbarV.scrollTop=c.scroller.scrollTop=h),Mb(a),null!=c.input.selectionStart){(!g||d)&&l(),clearTimeout(tc);var b=0,e=function(){"\u200b"==c.prevInput&&0==c.input.selectionStart?Ib(a,pd.selectAll)(a):b++<10?tc=setTimeout(e,500):Pb(a)};tc=setTimeout(e,200)}}if(!cf(a,b,"contextmenu")){var c=a.display,e=a.doc.sel;if(!Ub(c,b)&&!$b(a,b)){var f=Vb(a,b),h=c.scroller.scrollTop;if(f&&!k){var i=a.options.resetSelectionOnContextMenu;i&&(Hc(e.from,e.to)||Ic(f,e.from)||!Ic(f,e.to))&&Ib(a,Rc)(a.doc,f,f);var j=c.input.style.cssText;if(c.inputDiv.style.position="absolute",c.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: transparent; outline: none;"+"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);",Qb(a),Pb(a,!0),Hc(e.from,e.to)&&(c.input.value=c.prevInput=" "),g&&!d&&l(),w){Ve(b);var n=function(){Ze(window,"mouseup",n),setTimeout(m,20)};Ye(window,"mouseup",n)}else setTimeout(m,50)}}}}function wc(a,b,c){if(!Ic(b.from,c))return Mc(a,c);var d=b.text.length-1-(b.to.line-b.from.line);if(c.line>b.to.line+d){var e=c.line-d,f=a.first+a.size-1;return e>f?Gc(f,ye(a,f).text.length):Nc(c,ye(a,e).text.length)}if(c.line==b.to.line+d)return Nc(c,nf(b.text).length+(1==b.text.length?b.from.ch:0)+ye(a,b.to.line).text.length-b.to.ch);var g=c.line-b.from.line;return Nc(c,b.text[g].length+(g?0:b.from.ch))}function xc(a,b,c){if(c&&"object"==typeof c)return{anchor:wc(a,b,c.anchor),head:wc(a,b,c.head)};if("start"==c)return{anchor:b.from,head:b.from};var d=vc(b);if("around"==c)return{anchor:b.from,head:d};if("end"==c)return{anchor:d,head:d};var e=function(a){if(Ic(a,b.from))return a;if(!Ic(b.to,a))return d;var c=a.line+b.text.length-(b.to.line-b.from.line)-1,e=a.ch;return a.line==b.to.line&&(e+=d.ch-b.to.ch),Gc(c,e)};return{anchor:e(a.sel.anchor),head:e(a.sel.head)}}function yc(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=Mc(a,b)),c&&(this.to=Mc(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),$e(a,"beforeChange",a,d),a.cm&&$e(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function zc(a,b,c,d){if(a.cm){if(!a.cm.curOp)return Ib(a.cm,zc)(a,b,c,d);if(a.cm.state.suppressEdits)return}if(!(ef(a,"beforeChange")||a.cm&&ef(a.cm,"beforeChange"))||(b=yc(a,b,!0))){var e=x&&!d&&Jd(a,b.from,b.to);if(e){for(var f=e.length-1;f>=1;--f)Ac(a,{from:e[f].from,to:e[f].to,text:[""]});e.length&&Ac(a,{from:e[0].from,to:e[0].to,text:b.text},c)}else Ac(a,b,c)}}function Ac(a,b,c){if(1!=b.text.length||""!=b.text[0]||!Hc(b.from,b.to)){var d=xc(a,b,c);Je(a,b,d,a.cm?a.cm.curOp.id:0/0),Dc(a,b,d,Gd(a,b));var e=[];we(a,function(a,c){c||-1!=pf(e,a.history)||(Pe(a.history,b),e.push(a.history)),Dc(a,b,null,Gd(a,b))})}}function Bc(a,b){if(!a.cm||!a.cm.state.suppressEdits){var c=a.history,d=("undo"==b?c.done:c.undone).pop();if(d){var e={changes:[],anchorBefore:d.anchorAfter,headBefore:d.headAfter,anchorAfter:d.anchorBefore,headAfter:d.headBefore,generation:c.generation};("undo"==b?c.undone:c.done).push(e),c.generation=d.generation||++c.maxGeneration;for(var f=ef(a,"beforeChange")||a.cm&&ef(a.cm,"beforeChange"),g=d.changes.length-1;g>=0;--g){var h=d.changes[g];if(h.origin=b,f&&!yc(a,h,!1))return("undo"==b?c.done:c.undone).length=0,void 0;e.changes.push(Ie(a,h));var i=g?xc(a,h,null):{anchor:d.anchorBefore,head:d.headBefore};Dc(a,h,i,Id(a,h));var j=[];we(a,function(a,b){b||-1!=pf(j,a.history)||(Pe(a.history,h),j.push(a.history)),Dc(a,h,null,Id(a,h))})}}}}function Cc(a,b){function c(a){return Gc(a.line+b,a.ch)}a.first+=b,a.cm&&Lb(a.cm,a.first,a.first,b),a.sel.head=c(a.sel.head),a.sel.anchor=c(a.sel.anchor),a.sel.from=c(a.sel.from),a.sel.to=c(a.sel.to)}function Dc(a,b,c,d){if(a.cm&&!a.cm.curOp)return Ib(a.cm,Dc)(a,b,c,d);if(b.to.line<a.first)return Cc(a,b.text.length-1-(b.to.line-b.from.line)),void 0;if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Cc(a,e),b={from:Gc(a.first,0),to:Gc(b.to.line+e,b.to.ch),text:[nf(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:Gc(f,ye(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=ze(a,b.from,b.to),c||(c=xc(a,b,null)),a.cm?Ec(a.cm,b,d,c):pe(a,b,d,c)}}function Ec(a,b,c,d){var e=a.doc,f=a.display,g=b.from,h=b.to,i=!1,j=g.line;a.options.lineWrapping||(j=Ce(Rd(e,ye(e,g.line))),e.iter(j,h.line+1,function(a){return a==f.maxLine?(i=!0,!0):void 0})),Ic(e.sel.head,b.from)||Ic(b.to,e.sel.head)||(a.curOp.cursorActivity=!0),pe(e,b,c,d,E(a)),a.options.lineWrapping||(e.iter(j,g.line+b.text.length,function(a){var b=K(e,a);b>f.maxLineLength&&(f.maxLine=a,f.maxLineLength=b,f.maxLineChanged=!0,i=!1)}),i&&(a.curOp.updateMaxLine=!0)),e.frontier=Math.min(e.frontier,g.line),eb(a,400);var k=b.text.length-(h.line-g.line)-1;if(Lb(a,g.line,h.line+1,k),ef(a,"change")){var l={from:g,to:h,text:b.text,removed:b.removed,origin:b.origin};if(a.curOp.textChanged){for(var m=a.curOp.textChanged;m.next;m=m.next);m.next=l}else a.curOp.textChanged=l}}function Fc(a,b,c,d,e){if(d||(d=c),Ic(d,c)){var f=d;d=c,c=f}"string"==typeof b&&(b=Kf(b)),zc(a,{from:c,to:d,text:b,origin:e},null)}function Gc(a,b){return this instanceof Gc?(this.line=a,this.ch=b,void 0):new Gc(a,b)}function Hc(a,b){return a.line==b.line&&a.ch==b.ch}function Ic(a,b){return a.line<b.line||a.line==b.line&&a.ch<b.ch}function Jc(a,b){return a.line-b.line||a.ch-b.ch}function Kc(a){return Gc(a.line,a.ch)}function Lc(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function Mc(a,b){if(b.line<a.first)return Gc(a.first,0);var c=a.first+a.size-1;return b.line>c?Gc(c,ye(a,c).text.length):Nc(b,ye(a,b.line).text.length)}function Nc(a,b){var c=a.ch;return null==c||c>b?Gc(a.line,b):0>c?Gc(a.line,0):a}function Oc(a,b){return b>=a.first&&b<a.first+a.size}function Pc(a,b,c,d){if(a.sel.shift||a.sel.extend){var e=a.sel.anchor;if(c){var f=Ic(b,e);f!=Ic(c,e)?(e=b,b=c):f!=Ic(b,c)&&(b=c)}Rc(a,e,b,d)}else Rc(a,b,c||b,d);a.cm&&(a.cm.curOp.userSelChange=!0)}function Qc(a,b,c){var d={anchor:b,head:c};return $e(a,"beforeSelectionChange",a,d),a.cm&&$e(a.cm,"beforeSelectionChange",a.cm,d),d.anchor=Mc(a,d.anchor),d.head=Mc(a,d.head),d}function Rc(a,b,c,d,e){if(!e&&ef(a,"beforeSelectionChange")||a.cm&&ef(a.cm,"beforeSelectionChange")){var f=Qc(a,b,c);c=f.head,b=f.anchor}var g=a.sel;if(g.goalColumn=null,null==d&&(d=Ic(c,g.head)?-1:1),(e||!Hc(b,g.anchor))&&(b=Tc(a,b,d,"push"!=e)),(e||!Hc(c,g.head))&&(c=Tc(a,c,d,"push"!=e)),!Hc(g.anchor,b)||!Hc(g.head,c)){g.anchor=b,g.head=c;var h=Ic(c,b);g.from=h?c:b,g.to=h?b:c,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=a.cm.curOp.cursorActivity=!0),bf(a,"cursorActivity",a)}}function Sc(a){Rc(a.doc,a.doc.sel.from,a.doc.sel.to,null,"push")}function Tc(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=ye(a,f.line);if(h.markedSpans)for(var i=0;i<h.markedSpans.length;++i){var j=h.markedSpans[i],k=j.marker;if((null==j.from||(k.inclusiveLeft?j.from<=f.ch:j.from<f.ch))&&(null==j.to||(k.inclusiveRight?j.to>=f.ch:j.to>f.ch))){if(d&&($e(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find()[0>g?"from":"to"];if(Hc(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?Mc(a,Gc(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?Gc(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,Gc(a.first,0)):Tc(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function Uc(a){var b=Vc(a,a.doc.sel.head,null,a.options.cursorScrollMargin);if(a.state.focused){var c=a.display,d=Df(c.sizer),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!p){var f=zf("div","\u200b",null,"position: absolute; top: "+(b.top-c.viewOffset)+"px; height: "+(b.bottom-b.top+gf)+"px; left: "+b.left+"px; width: 2px;");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function Vc(a,b,c,d){for(null==d&&(d=0);;){var e=!1,f=yb(a,b),g=c&&c!=b?yb(a,c):f,h=Xc(a,Math.min(f.left,g.left),Math.min(f.top,g.top)-d,Math.max(f.left,g.left),Math.max(f.bottom,g.bottom)+d),i=a.doc.scrollTop,j=a.doc.scrollLeft;if(null!=h.scrollTop&&(dc(a,h.scrollTop),Math.abs(a.doc.scrollTop-i)>1&&(e=!0)),null!=h.scrollLeft&&(ec(a,h.scrollLeft),Math.abs(a.doc.scrollLeft-j)>1&&(e=!0)),!e)return f}}function Wc(a,b,c,d,e){var f=Xc(a,b,c,d,e);null!=f.scrollTop&&dc(a,f.scrollTop),null!=f.scrollLeft&&ec(a,f.scrollLeft)}function Xc(a,b,c,d,e){var f=a.display,g=Db(a.display);0>c&&(c=0);var h=f.scroller.clientHeight-gf,i=f.scroller.scrollTop,j={},k=a.doc.height+jb(f),l=g>c,m=e>k-g;if(i>c)j.scrollTop=l?0:c;else if(e>i+h){var n=Math.min(c,(m?k:e)-h);n!=i&&(j.scrollTop=n)}var o=f.scroller.clientWidth-gf,p=f.scroller.scrollLeft;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return p+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>o+p-3&&(j.scrollLeft=d+10-o),j}function Yc(a,b,c){a.curOp.updateScrollPos={scrollLeft:null==b?a.doc.scrollLeft:b,scrollTop:null==c?a.doc.scrollTop:c}}function Zc(a,b,c){var d=a.curOp.updateScrollPos||(a.curOp.updateScrollPos={scrollLeft:a.doc.scrollLeft,scrollTop:a.doc.scrollTop}),e=a.display.scroller;d.scrollTop=Math.max(0,Math.min(e.scrollHeight-e.clientHeight,d.scrollTop+c)),d.scrollLeft=Math.max(0,Math.min(e.scrollWidth-e.clientWidth,d.scrollLeft+b))}function $c(a,b,c,d){var f,e=a.doc;null==c&&(c="add"),"smart"==c&&(a.doc.mode.indent?f=hb(a,b):c="prev");var g=a.options.tabSize,h=ye(e,b),i=kf(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(k=a.doc.mode.indent(f,h.text.slice(j.length),h.text),k==hf)){if(!d)return;c="prev"}}else k=0,c="not";"prev"==c?k=b>e.first?kf(ye(e,b-1).text,null,g):0:"add"==c?k=i+a.options.indentUnit:"subtract"==c?k=i-a.options.indentUnit:"number"==typeof c&&(k=i+c),k=Math.max(0,k);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+="	";k>m&&(l+=mf(k-m)),l!=j?Fc(a.doc,l,Gc(b,0),Gc(b,j.length),"+input"):e.sel.head.line==b&&e.sel.head.ch<j.length&&Rc(e,Gc(b,j.length),Gc(b,j.length),1),h.stateAfter=null}function _c(a,b,c){var d=b,e=b,f=a.doc;return"number"==typeof b?e=ye(f,Lc(f,b)):d=Ce(b),null==d?null:c(e,d)?(Lb(a,d,d+1),e):null}function ad(a,b,c,d,e){function k(){var b=f+c;return b<a.first||b>=a.first+a.size?j=!1:(f=b,i=ye(a,b))}function l(a){var b=(e?Zf:$f)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Sf:Rf)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=ye(a,f),j=!0;if("char"==d)l();else if("column"==d)l(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=!0;!(0>c)||l(!o);o=!1){var p=i.text.charAt(g)||"\n",q=vf(p)?"w":n&&"\n"==p?"n":!n||/\s/.test(p)?null:"p";if(!n||o||q||(q="s"),m&&m!=q){0>c&&(c=1,l());break}if(q&&(m=q),c>0&&!l(!o))break}var r=Tc(a,Gc(f,g),h,!0);return j||(r.hitSide=!0),r}function bd(a,b,c,d){var g,e=a.doc,f=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*Db(a.display))}else"line"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=Ab(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function cd(a,b){var c=b.ch,d=b.ch;if(a){(b.xRel<0||d==a.length)&&c?--c:++d;for(var e=a.charAt(c),f=vf(e)?vf:/\s/.test(e)?function(a){return/\s/.test(a)}:function(a){return!/\s/.test(a)&&!vf(a)};c>0&&f(a.charAt(c-1));)--c;for(;d<a.length&&f(a.charAt(d));)++d}return{from:Gc(b.line,c),to:Gc(b.line,d)}}function dd(a,b){Pc(a.doc,Gc(b,0),Mc(a.doc,Gc(b+1,0)))}function gd(a,b,c,d){z.defaults[a]=b,c&&(ed[a]=d?function(a,b,d){d!=hd&&c(a,b,d)}:c)}function nd(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c}function od(a,b,c){return a.startState?a.startState(b,c):!0}function rd(a){return"string"==typeof a?qd[a]:a}function sd(a,b,c){function d(b){b=rd(b);var e=b[a];if(e===!1)return"stop";if(null!=e&&c(e))return!0;if(b.nofallthrough)return"stop";var f=b.fallthrough;if(null==f)return!1;if("[object Array]"!=Object.prototype.toString.call(f))return d(f);for(var g=0,h=f.length;h>g;++g){var i=d(f[g]);if(i)return i}return!1}for(var e=0;e<b.length;++e){var f=d(b[e]);if(f)return"stop"!=f}}function td(a){var b=Nf[a.keyCode];return"Ctrl"==b||"Alt"==b||"Shift"==b||"Mod"==b}function ud(a,b){if(k&&34==a.keyCode&&a["char"])return!1;var c=Nf[a.keyCode];return null==c||a.altGraphKey?!1:(a.altKey&&(c="Alt-"+c),(v?a.metaKey:a.ctrlKey)&&(c="Ctrl-"+c),(v?a.ctrlKey:a.metaKey)&&(c="Cmd-"+c),!b&&a.shiftKey&&(c="Shift-"+c),c)}function vd(a,b){this.pos=this.start=0,this.string=a,this.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0}function wd(a,b){this.lines=[],this.type=b,this.doc=a}function yd(a,b,c,d,e){if(d&&d.shared)return Ad(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return Ib(a.cm,yd)(a,b,c,d,e);var f=new wd(a,e);if(d&&rf(d,f),Ic(c,b)||Hc(b,c)&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.replacedWith=zf("span",[f.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||(f.replacedWith.ignoreEvents=!0)),f.collapsed){if(Qd(a,b.line,b,c,f)||b.line!=c.line&&Qd(a,c.line,b,c,f))throw new Error("Inserting collapsed marker partially overlapping an existing one");y=!0}f.addToHistory&&Je(a,{from:b,to:c,origin:"markText"},{head:a.sel.head,anchor:a.sel.anchor},0/0);var i,g=b.line,h=a.cm;return a.iter(g,c.line+1,function(d){h&&f.collapsed&&!h.options.lineWrapping&&Rd(a,d)==h.display.maxLine&&(i=!0);var e={from:null,to:null,marker:f};g==b.line&&(e.from=b.ch),g==c.line&&(e.to=c.ch),f.collapsed&&g!=b.line&&Be(d,0),Dd(d,e),++g}),f.collapsed&&a.iter(b.line,c.line+1,function(b){Sd(a,b)&&Be(b,0)}),f.clearOnEnter&&Ye(f,"beforeCursorEnter",function(){f.clear()}),f.readOnly&&(x=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++xd,f.atomic=!0),h&&(i&&(h.curOp.updateMaxLine=!0),(f.className||f.title||f.startStyle||f.endStyle||f.collapsed)&&Lb(h,b.line,c.line+1),f.atomic&&Sc(h)),bf(h,"markerAdded",h,f),f}function zd(a,b){this.markers=a,this.primary=b;for(var c=0,d=this;c<a.length;++c)a[c].parent=this,Ye(a[c],"clear",function(){d.clear()})}function Ad(a,b,c,d,e){d=rf(d),d.shared=!1;var f=[yd(a,b,c,d,e)],g=f[0],h=d.replacedWith;return we(a,function(a){h&&(d.replacedWith=h.cloneNode(!0)),f.push(yd(a,Mc(a,b),Mc(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=nf(f)}),new zd(f,g)}function Bd(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Cd(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Dd(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Ed(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);if(h||f.from==b&&"bookmark"==g.type&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(e||(e=[])).push({from:f.from,to:i?null:f.to,marker:g})}}return e}function Fd(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(e||(e=[])).push({from:i?null:f.from-b,to:null==f.to?null:f.to-b,marker:g})}}return e}function Gd(a,b){var c=Oc(a,b.from.line)&&ye(a,b.from.line).markedSpans,d=Oc(a,b.to.line)&&ye(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=Hc(b.from,b.to),h=Ed(c,e,g),i=Fd(d,f,g),j=1==b.text.length,k=nf(b.text).length+(j?e:0);if(h)for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=Bd(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var l=0;l<i.length;++l){var m=i[l];if(null!=m.to&&(m.to+=k),null==m.from){var n=Bd(h,m.marker);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}h&&(h=Hd(h)),i&&i!=h&&(i=Hd(i));var o=[h];if(!j){var q,p=b.text.length-2;if(p>0&&h)for(var l=0;l<h.length;++l)null==h[l].to&&(q||(q=[])).push({from:null,to:null,marker:h[l].marker});for(var l=0;p>l;++l)o.push(q);o.push(i)}return o}function Hd(a){for(var b=0;b<a.length;++b){var c=a[b];null!=c.from&&c.from==c.to&&c.marker.clearWhenEmpty!==!1&&a.splice(b--,1)}return a.length?a:null}function Id(a,b){var c=Le(a,b),d=Gd(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function Jd(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&-1!=pf(d,c)||(d||(d=[])).push(c)}}),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=g.find(),i=0;i<e.length;++i){var j=e[i];if(!Ic(j.to,h.from)&&!Ic(h.to,j.from)){var k=[i,1];(Ic(j.from,h.from)||!g.inclusiveLeft&&Hc(j.from,h.from))&&k.push({from:j.from,to:h.from}),(Ic(h.to,j.to)||!g.inclusiveRight&&Hc(j.to,h.to))&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Kd(a){return a.inclusiveLeft?-1:0}function Ld(a){return a.inclusiveRight?1:0}function Md(a,b){var c=a.lines.length-b.lines.length;if(0!=c)return c;var d=a.find(),e=b.find(),f=Jc(d.from,e.from)||Kd(a)-Kd(b);if(f)return-f;var g=Jc(d.to,e.to)||Ld(a)-Ld(b);return g?g:b.id-a.id}function Nd(a,b){var d,c=y&&a.markedSpans;if(c)for(var e,f=0;f<c.length;++f)e=c[f],e.marker.collapsed&&null==(b?e.from:e.to)&&(!d||Md(d,e.marker)<0)&&(d=e.marker);return d}function Od(a){return Nd(a,!0)}function Pd(a){return Nd(a,!1)}function Qd(a,b,c,d,e){var f=ye(a,b),g=y&&f.markedSpans;if(g)for(var h=0;h<g.length;++h){var i=g[h];if(i.marker.collapsed){var j=i.marker.find(!0),k=Jc(j.from,c)||Kd(i.marker)-Kd(e),l=Jc(j.to,d)||Ld(i.marker)-Ld(e);if(!(k>=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(Jc(j.to,c)||Ld(i.marker)-Kd(e))>0||k>=0&&(Jc(j.from,d)||Kd(i.marker)-Ld(e))<0))return!0}}}function Rd(a,b){for(var c;c=Od(b);)b=ye(a,c.find().from.line);return b}function Sd(a,b){var c=y&&b.markedSpans;if(c)for(var d,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.replacedWith&&0==d.from&&d.marker.inclusiveLeft&&Td(a,b,d))return!0}}function Td(a,b,c){if(null==c.to){var d=c.marker.find().to,e=ye(a,d.line);return Td(a,e,Bd(e.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var f,g=0;g<b.markedSpans.length;++g)if(f=b.markedSpans[g],f.marker.collapsed&&!f.marker.replacedWith&&f.from==c.to&&(null==f.to||f.to!=c.from)&&(f.marker.inclusiveLeft||c.marker.inclusiveRight)&&Td(a,b,f))return!0}function Ud(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Vd(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Xd(a){return function(){var b=!this.cm.curOp;b&&Gb(this.cm);try{var c=a.apply(this,arguments)}finally{b&&Hb(this.cm)}return c}}function Yd(a){return null!=a.height?a.height:(a.node.parentNode&&1==a.node.parentNode.nodeType||Bf(a.cm.display.measure,zf("div",[a.node],null,"position: relative")),a.height=a.node.offsetHeight)}function Zd(a,b,c,d){var e=new Wd(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),_c(a,b,function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,!Sd(a.doc,b)||e.showIfHidden){var d=Ee(a,b)<a.doc.scrollTop;Be(b,b.height+Yd(e)),d&&Zc(a,0,e.height),a.curOp.forceUpdate=!0}return!0}),e}function _d(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Ud(a),Vd(a,c);var e=d?d(a):1;e!=a.height&&Be(a,e)}function ae(a){a.parent=null,Ud(a)}function be(a,b,c,d,e,f){var g=c.flattenSpans;null==g&&(g=a.options.flattenSpans);var k,h=0,i=null,j=new vd(b,a.options.tabSize);for(""==b&&c.blankLine&&c.blankLine(d);!j.eol();){if(j.pos>a.options.maxHighlightLength?(g=!1,f&&ee(a,b,d,j.pos),j.pos=b.length,k=null):k=c.token(j,d),a.options.addModeClass){var l=z.innerMode(c,d).mode.name;l&&(k="m-"+(k?l+" "+k:l))}g&&i==k||(h<j.start&&e(j.start,i),h=j.start,i=k),j.start=j.pos}for(;h<j.pos;){var m=Math.min(j.pos,h+5e4);e(m,i),h=m}}function ce(a,b,c,d){var e=[a.state.modeGen];be(a,b.text,a.doc.mode,c,function(a,b){e.push(a,b)},d);for(var f=0;f<a.state.overlays.length;++f){var g=a.state.overlays[f],h=1,i=0;be(a,b.text,g.mode,!0,function(a,b){for(var c=h;a>i;){var d=e[h];d>a&&e.splice(h,1,a,e[h+1],d),h+=2,i=Math.min(a,d)}if(b)if(g.opaque)e.splice(c,h-c,a,b),h=c+2;else for(;h>c;c+=2){var f=e[c+1];e[c+1]=f?f+" "+b:b}})}return e}function de(a,b){return b.styles&&b.styles[0]==a.state.modeGen||(b.styles=ce(a,b,b.stateAfter=hb(a,Ce(b)))),b.styles}function ee(a,b,c,d){var e=a.doc.mode,f=new vd(b,a.options.tabSize);for(f.start=f.pos=d||0,""==b&&e.blankLine&&e.blankLine(c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)e.token(f,c),f.start=f.pos}function he(a,b){if(!a)return null;for(;;){var c=a.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!c)break;a=a.slice(0,c.index)+a.slice(c.index+c[0].length);var d=c[1]?"bgClass":"textClass";null==b[d]?b[d]=c[2]:new RegExp("(?:^|s)"+c[2]+"(?:$|s)").test(b[d])||(b[d]+=" "+c[2])}if(/^\s*$/.test(a))return null;var e=b.cm.options.addModeClass?ge:fe;return e[a]||(e[a]=a.replace(/\S+/g,"cm-$&"))}function ie(a,b,c,d){for(var e,f=b,i=!0;e=Od(f);)f=ye(a.doc,e.find().from.line);var j={pre:zf("pre"),col:0,pos:0,measure:null,measuredSomething:!1,cm:a,copyWidgets:d};do{f.text&&(i=!1),j.measure=f==b&&c,j.pos=0,j.addToken=j.measure?le:ke,(g||h)&&a.getOption("lineWrapping")&&(j.addToken=me(j.addToken));var k=oe(f,j,de(a,f));c&&f==b&&!j.measuredSomething&&(c[0]=j.pre.appendChild(Jf(a.display.measure)),j.measuredSomething=!0),k&&(f=ye(a.doc,k.to.line))}while(k);!c||j.measuredSomething||c[0]||(c[0]=j.pre.appendChild(i?zf("span","\xa0"):Jf(a.display.measure))),j.pre.firstChild||Sd(a.doc,b)||j.pre.appendChild(document.createTextNode("\xa0"));var l;if(c&&g&&(l=Fe(f))){var m=l.length-1;l[m].from==l[m].to&&--m;var n=l[m],o=l[m-1];if(n.from+1==n.to&&o&&n.level<o.level){var p=c[j.pos-1];p&&p.parentNode.insertBefore(p.measureRight=Jf(a.display.measure),p.nextSibling)}}var q=j.textClass?j.textClass+" "+(b.textClass||""):b.textClass;return q&&(j.pre.className=q),$e(a,"renderLine",a,b,j.pre),j}function je(a){var b=zf("span","\u2022","cm-invalidchar");return b.title="\\u"+a.charCodeAt(0).toString(16),b}function ke(a,b,c,d,e,f){if(b){var g=a.cm.options.specialChars;if(g.test(b))for(var h=document.createDocumentFragment(),i=0;;){g.lastIndex=i;var j=g.exec(b),k=j?j.index-i:b.length-i;if(k&&(h.appendChild(document.createTextNode(b.slice(i,i+k))),a.col+=k),!j)break;if(i+=k+1,"	"==j[0]){var l=a.cm.options.tabSize,m=l-a.col%l;h.appendChild(zf("span",mf(m),"cm-tab")),a.col+=m
-}else{var n=a.cm.options.specialCharPlaceholder(j[0]);h.appendChild(n),a.col+=1}}else{a.col+=b.length;var h=document.createTextNode(b)}if(c||d||e||a.measure){var o=c||"";d&&(o+=d),e&&(o+=e);var n=zf("span",[h],o);return f&&(n.title=f),a.pre.appendChild(n)}a.pre.appendChild(h)}}function le(a,c,d,e,f){for(var g=a.cm.options.lineWrapping,h=0;h<c.length;++h){for(var i=0==h,j=h+1;j<c.length&&yf(c.charAt(j));)++j;var k=c.slice(h,j);h=j-1,h&&g&&Ff(c,h)&&a.pre.appendChild(zf("wbr"));var l=a.measure[a.pos],m=a.measure[a.pos]=ke(a,k,d,i&&e,h==c.length-1&&f);l&&(m.leftSide=l.leftSide||l),b&&g&&" "==k&&h&&!/\s/.test(c.charAt(h-1))&&h<c.length-1&&!/\s/.test(c.charAt(h+1))&&(m.style.whiteSpace="normal"),a.pos+=k.length}c.length&&(a.measuredSomething=!0)}function me(a){function b(a){for(var b=" ",c=0;c<a.length-2;++c)b+=c%2?" ":"\xa0";return b+=" "}return function(c,d,e,f,g,h){return a(c,d.replace(/ {3,}/g,b),e,f,g,h)}}function ne(a,b,c,d){var e=!d&&c.replacedWith;if(e&&(a.copyWidgets&&(e=e.cloneNode(!0)),a.pre.appendChild(e),a.measure)){if(b)a.measure[a.pos]=e;else{var f=Jf(a.cm.display.measure);if("bookmark"!=c.type||c.insertLeft){if(a.measure[a.pos])return;a.measure[a.pos]=a.pre.insertBefore(f,e)}else a.measure[a.pos]=a.pre.appendChild(f)}a.measuredSomething=!0}a.pos+=b}function oe(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var k,m,n,o,p,q,h=e.length,i=0,g=1,j="",l=0;;){if(l==i){m=n=o=p="",q=null,l=1/0;for(var r=[],s=0;s<d.length;++s){var t=d[s],u=t.marker;t.from<=i&&(null==t.to||t.to>i)?(null!=t.to&&l>t.to&&(l=t.to,n=""),u.className&&(m+=" "+u.className),u.startStyle&&t.from==i&&(o+=" "+u.startStyle),u.endStyle&&t.to==l&&(n+=" "+u.endStyle),u.title&&!p&&(p=u.title),u.collapsed&&(!q||Md(q.marker,u)<0)&&(q=t)):t.from>i&&l>t.from&&(l=t.from),"bookmark"==u.type&&t.from==i&&u.replacedWith&&r.push(u)}if(q&&(q.from||0)==i&&(ne(b,(null==q.to?h:q.to)-i,q.marker,null==q.from),null==q.to))return q.marker.find();if(!q&&r.length)for(var s=0;s<r.length;++s)ne(b,0,r[s])}if(i>=h)break;for(var v=Math.min(h,l);;){if(j){var w=i+j.length;if(!q){var x=w>v?j.slice(0,v-i):j;b.addToken(b,x,k?k+m:m,o,i+x.length==l?n:"",p)}if(w>=v){j=j.slice(v-i),i=v;break}i=w,o=""}j=e.slice(f,f=c[g++]),k=he(c[g++],b)}}else for(var g=1;g<c.length;g+=2)b.addToken(b,e.slice(f,f=c[g]),he(c[g+1],b))}function pe(a,b,c,d,e){function f(a){return c?c[a]:null}function g(a,c,d){_d(a,c,d,e),bf(a,"change",a,b)}var h=b.from,i=b.to,j=b.text,k=ye(a,h.line),l=ye(a,i.line),m=nf(j),n=f(j.length-1),o=i.line-h.line;if(0!=h.ch||0!=i.ch||""!=m||a.cm&&!a.cm.options.wholeLineUpdateBefore)if(k==l)if(1==j.length)g(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{for(var r=[],p=1,q=j.length-1;q>p;++p)r.push(new $d(j[p],f(p),e));r.push(new $d(m+k.text.slice(i.ch),n,e)),g(k,k.text.slice(0,h.ch)+j[0],f(0)),a.insert(h.line+1,r)}else if(1==j.length)g(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),f(0)),a.remove(h.line+1,o);else{g(k,k.text.slice(0,h.ch)+j[0],f(0)),g(l,m+l.text.slice(i.ch),n);for(var p=1,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,r)}else{for(var p=0,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));g(l,l.text,n),o&&a.remove(h.line,o),r.length&&a.insert(h.line,r)}bf(a,"change",a,b),Rc(a,d.anchor,d.head,null,!0)}function qe(a){this.lines=a,this.parent=null;for(var b=0,c=a.length,d=0;c>b;++b)a[b].parent=this,d+=a[b].height;this.height=d}function re(a){this.children=a;for(var b=0,c=0,d=0,e=a.length;e>d;++d){var f=a[d];b+=f.chunkSize(),c+=f.height,f.parent=this}this.size=b,this.height=c,this.parent=null}function we(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;(!c||i)&&(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function xe(a,b){if(b.cm)throw new Error("This document is already in use.");a.doc=b,b.cm=a,F(a),B(a),a.options.lineWrapping||L(a),a.options.mode=b.modeOption,Lb(a)}function ye(a,b){for(b-=a.first;!a.lines;)for(var c=0;;++c){var d=a.children[c],e=d.chunkSize();if(e>b){a=d;break}b-=e}return a.lines[b]}function ze(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function Ae(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function Be(a,b){for(var c=b-a.height,d=a;d;d=d.parent)d.height+=c}function Ce(a){if(null==a.parent)return null;for(var b=a.parent,c=pf(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function De(a,b){var c=a.first;a:do{for(var d=0,e=a.children.length;e>d;++d){var f=a.children[d],g=f.height;if(g>b){a=f;continue a}b-=g,c+=f.chunkSize()}return c}while(!a.lines);for(var d=0,e=a.lines.length;e>d;++d){var h=a.lines[d],i=h.height;if(i>b)break;b-=i}return c+d}function Ee(a,b){b=Rd(a.doc,b);for(var c=0,d=b.parent,e=0;e<d.lines.length;++e){var f=d.lines[e];if(f==b)break;c+=f.height}for(var g=d.parent;g;d=g,g=d.parent)for(var e=0;e<g.children.length;++e){var h=g.children[e];if(h==d)break;c+=h.height}return c}function Fe(a){var b=a.order;return null==b&&(b=a.order=_f(a.text)),b}function Ge(a){return{done:[],undone:[],undoDepth:1/0,lastTime:0,lastOp:null,lastOrigin:null,generation:a||1,maxGeneration:a||1}}function He(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))[f]=c.markedSpans),++f})}function Ie(a,b){var c={line:b.from.line,ch:b.from.ch},d={from:c,to:vc(b),text:ze(a,b.from,b.to)};return He(a,d,b.from.line,b.to.line+1),we(a,function(a){He(a,d,b.from.line,b.to.line+1)},!0),d}function Je(a,b,c,d){var e=a.history;e.undone.length=0;var f=+new Date,g=nf(e.done);if(g&&(e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastTime>f-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))){var h=nf(g.changes);Hc(b.from,b.to)&&Hc(b.from,h.to)?h.to=vc(b):g.changes.push(Ie(a,b)),g.anchorAfter=c.anchor,g.headAfter=c.head}else for(g={changes:[Ie(a,b)],generation:e.generation,anchorBefore:a.sel.anchor,headBefore:a.sel.head,anchorAfter:c.anchor,headAfter:c.head},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift();e.generation=++e.maxGeneration,e.lastTime=f,e.lastOp=d,e.lastOrigin=b.origin,h||$e(a,"historyAdded")}function Ke(a){if(!a)return null;for(var c,b=0;b<a.length;++b)a[b].marker.explicitlyCleared?c||(c=a.slice(0,b)):c&&c.push(a[b]);return c?c.length?c:null:a}function Le(a,b){var c=b["spans_"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(Ke(c[d]));return e}function Me(a,b){for(var c=0,d=[];c<a.length;++c){var e=a[c],f=e.changes,g=[];d.push({changes:g,anchorBefore:e.anchorBefore,headBefore:e.headBefore,anchorAfter:e.anchorAfter,headAfter:e.headAfter});for(var h=0;h<f.length;++h){var j,i=f[h];if(g.push({from:i.from,to:i.to,text:i.text}),b)for(var k in i)(j=k.match(/^spans_(\d+)$/))&&pf(b,Number(j[1]))>-1&&(nf(g)[k]=i[k],delete i[k])}}return d}function Ne(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function Oe(a,b,c,d){for(var e=0;e<a.length;++e){for(var f=a[e],g=!0,h=0;h<f.changes.length;++h){var i=f.changes[h];if(f.copied||(i.from=Kc(i.from),i.to=Kc(i.to)),c<i.from.line)i.from.line+=d,i.to.line+=d;else if(b<=i.to.line){g=!1;break}}f.copied||(f.anchorBefore=Kc(f.anchorBefore),f.headBefore=Kc(f.headBefore),f.anchorAfter=Kc(f.anchorAfter),f.readAfter=Kc(f.headAfter),f.copied=!0),g?(Ne(f.anchorBefore),Ne(f.headBefore),Ne(f.anchorAfter),Ne(f.headAfter)):(a.splice(0,e+1),e=0)}}function Pe(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;Oe(a.done,c,d,e),Oe(a.undone,c,d,e)}function Qe(){Ve(this)}function Re(a){return a.stop||(a.stop=Qe),a}function Se(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function Te(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}function Ue(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function Ve(a){Se(a),Te(a)}function We(a){return a.target||a.srcElement}function Xe(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),s&&a.ctrlKey&&1==b&&(b=3),b}function Ye(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var d=a._handlers||(a._handlers={}),e=d[b]||(d[b]=[]);e.push(c)}}function Ze(a,b,c){if(a.removeEventListener)a.removeEventListener(b,c,!1);else if(a.detachEvent)a.detachEvent("on"+b,c);else{var d=a._handlers&&a._handlers[b];if(!d)return;for(var e=0;e<d.length;++e)if(d[e]==c){d.splice(e,1);break}}}function $e(a,b){var c=a._handlers&&a._handlers[b];if(c)for(var d=Array.prototype.slice.call(arguments,2),e=0;e<c.length;++e)c[e].apply(null,d)}function bf(a,b){function e(a){return function(){a.apply(null,d)}}var c=a._handlers&&a._handlers[b];if(c){var d=Array.prototype.slice.call(arguments,2);_e||(++af,_e=[],setTimeout(df,0));for(var f=0;f<c.length;++f)_e.push(e(c[f]))}}function cf(a,b,c){return $e(a,c||b.type,a,b),Ue(b)||b.codemirrorIgnore}function df(){--af;var a=_e;_e=null;for(var b=0;b<a.length;++b)a[b]()}function ef(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function ff(a){a.prototype.on=function(a,b){Ye(this,a,b)},a.prototype.off=function(a,b){Ze(this,a,b)}}function jf(){this.id=null}function kf(a,b,c,d,e){null==b&&(b=a.search(/[^\s\u00a0]/),-1==b&&(b=a.length));for(var f=d||0,g=e||0;b>f;++f)"	"==a.charAt(f)?g+=c-g%c:++g;return g}function mf(a){for(;lf.length<=a;)lf.push(nf(lf)+" ");return lf[a]}function nf(a){return a[a.length-1]}function of(a){if(q)a.selectionStart=0,a.selectionEnd=a.value.length;else try{a.select()}catch(b){}}function pf(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;d>c;++c)if(a[c]==b)return c;return-1}function qf(a,b){function c(){}c.prototype=a;var d=new c;return b&&rf(b,d),d}function rf(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function sf(a){for(var b=[],c=0;a>c;++c)b.push(void 0);return b}function tf(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function vf(a){return/\w/.test(a)||a>"\x80"&&(a.toUpperCase()!=a.toLowerCase()||uf.test(a))}function wf(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function yf(a){return a.charCodeAt(0)>=768&&xf.test(a)}function zf(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)Cf(e,b);else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function Af(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function Bf(a,b){return Af(a).appendChild(b)}function Cf(a,b){d?(a.innerHTML="",a.appendChild(document.createTextNode(b))):a.textContent=b}function Df(a){return a.getBoundingClientRect()}function Ff(){return!1}function Hf(a){if(null!=Gf)return Gf;var b=zf("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");return Bf(a,b),b.offsetWidth&&(Gf=b.offsetHeight-b.clientHeight),Gf||0}function Jf(a){if(null==If){var b=zf("span","\u200b");Bf(a,zf("span",[b,document.createTextNode("x")])),0!=a.firstChild.offsetHeight&&(If=b.offsetWidth<=1&&b.offsetHeight>2&&!c)}return If?zf("span","\u200b"):zf("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px")}function Of(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function Pf(a){return a.level%2?a.to:a.from}function Qf(a){return a.level%2?a.from:a.to}function Rf(a){var b=Fe(a);return b?Pf(b[0]):0}function Sf(a){var b=Fe(a);return b?Qf(nf(b)):a.text.length}function Tf(a,b){var c=ye(a.doc,b),d=Rd(a.doc,c);d!=c&&(b=Ce(d));var e=Fe(d),f=e?e[0].level%2?Sf(d):Rf(d):0;return Gc(b,f)}function Uf(a,b){for(var c,d;c=Pd(d=ye(a.doc,b));)b=c.find().to.line;var e=Fe(d),f=e?e[0].level%2?Rf(d):Sf(d):d.text.length;return Gc(b,f)}function Vf(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function Xf(a,b){Wf=null;for(var d,c=0;c<a.length;++c){var e=a[c];if(e.from<b&&e.to>b)return c;if(e.from==b||e.to==b){if(null!=d)return Vf(a,e.level,a[d].level)?(e.from!=e.to&&(Wf=d),c):(e.from!=e.to&&(Wf=c),d);d=c}}return d}function Yf(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&yf(a.text.charAt(b)));return b}function Zf(a,b,c,d){var e=Fe(a);if(!e)return $f(a,b,c,d);for(var f=Xf(e,b),g=e[f],h=Yf(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h<g.to)return h;if(h==g.from||h==g.to)return Xf(e,h)==f?h:(g=e[f+=c],c>0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?Yf(a,g.to,-1,d):Yf(a,g.from,1,d)}}function $f(a,b,c,d){var e=b+c;if(d)for(;e>0&&yf(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var a=/gecko\/\d/i.test(navigator.userAgent),b=/MSIE \d/.test(navigator.userAgent),c=b&&(null==document.documentMode||document.documentMode<8),d=b&&(null==document.documentMode||document.documentMode<9),e=b&&(null==document.documentMode||document.documentMode<10),f=/Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent),g=b||f,h=/WebKit\//.test(navigator.userAgent),i=h&&/Qt\/\d+\.\d+/.test(navigator.userAgent),j=/Chrome\//.test(navigator.userAgent),k=/Opera\//.test(navigator.userAgent),l=/Apple Computer/.test(navigator.vendor),m=/KHTML\//.test(navigator.userAgent),n=/Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent),o=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),p=/PhantomJS/.test(navigator.userAgent),q=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),r=q||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),s=q||/Mac/.test(navigator.platform),t=/win/i.test(navigator.platform),u=k&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);u&&(u=Number(u[1])),u&&u>=15&&(k=!1,h=!0);var Cb,Wb,Xb,v=s&&(i||k&&(null==u||12.11>u)),w=a||g&&!d,x=!1,y=!1,Fb=0,ac=0,fc=0,gc=null;g?gc=-.53:a?gc=15:j?gc=-.7:l&&(gc=-1/3);var kc,tc,oc=null,vc=z.changeEnd=function(a){return a.text?Gc(a.from.line+a.text.length-1,nf(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};z.Pos=Gc,z.prototype={constructor:z,focus:function(){window.focus(),Qb(this),Nb(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,ed.hasOwnProperty(a)&&Ib(this,ed[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](a)},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c<b.length;++c)if(b[c]==a||"string"!=typeof b[c]&&b[c].name==a)return b.splice(c,1),!0},addOverlay:Ib(null,function(a,b){var c=a.token?a:z.getMode(this.options,a);if(c.startState)throw new Error("Overlays may not be stateful.");this.state.overlays.push({mode:c,modeSpec:a,opaque:b&&b.opaque}),this.state.modeGen++,Lb(this)}),removeOverlay:Ib(null,function(a){for(var b=this.state.overlays,c=0;c<b.length;++c){var d=b[c].modeSpec;if(d==a||"string"==typeof a&&d.name==a)return b.splice(c,1),this.state.modeGen++,Lb(this),void 0}}),indentLine:Ib(null,function(a,b,c){"string"!=typeof b&&"number"!=typeof b&&(b=null==b?this.options.smartIndent?"smart":"prev":b?"add":"subtract"),Oc(this.doc,a)&&$c(this,a,b,c)}),indentSelection:Ib(null,function(a){var b=this.doc.sel;if(Hc(b.from,b.to))return $c(this,b.from.line,a,!0);for(var c=b.to.line-(b.to.ch?0:1),d=b.from.line;c>=d;++d)$c(this,d,a)}),getTokenAt:function(a,b){var c=this.doc;a=Mc(c,a);for(var d=hb(this,a.line,b),e=this.doc.mode,f=ye(c,a.line),g=new vd(f.text,this.options.tabSize);g.pos<a.ch&&!g.eol();){g.start=g.pos;var h=e.token(g,d)}return{start:g.start,end:g.pos,string:g.current(),className:h||null,type:h||null,state:d}},getTokenTypeAt:function(a){a=Mc(this.doc,a);var b=de(this,ye(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)return b[2];for(;;){var f=c+d>>1;if((f?b[2*f-1]:0)>=e)d=f;else{if(!(b[2*f+1]<e))return b[2*f+2];c=f+1}}},getModeAt:function(a){var b=this.doc.mode;return b.innerMode?z.innerMode(b,this.getTokenAt(a).state).mode:b},getHelper:function(a,b){return this.getHelpers(a,b)[0]},getHelpers:function(a,b){var c=[];if(!md.hasOwnProperty(b))return md;var d=md[b],e=this.getModeAt(a);if("string"==typeof e[b])d[e[b]]&&c.push(d[e[b]]);else if(e[b])for(var f=0;f<e[b].length;f++){var g=d[e[b][f]];g&&c.push(g)}else e.helperType&&d[e.helperType]?c.push(d[e.helperType]):d[e.name]&&c.push(d[e.name]);for(var f=0;f<d._global.length;f++){var h=d._global[f];h.pred(e,this)&&-1==pf(c,h.val)&&c.push(h.val)}return c},getStateAfter:function(a,b){var c=this.doc;return a=Lc(c,null==a?c.first+c.size-1:a),hb(this,a+1,b)},cursorCoords:function(a,b){var c,d=this.doc.sel;return c=null==a?d.head:"object"==typeof a?Mc(this.doc,a):a?d.from:d.to,yb(this,c,b||"page")},charCoords:function(a,b){return xb(this,Mc(this.doc,a),b||"page")},coordsChar:function(a,b){return a=wb(this,a,b||"page"),Ab(this,a.left,a.top)},lineAtHeight:function(a,b){return a=wb(this,{top:a,left:0},b||"page").top,De(this.doc,a+this.display.viewOffset)},heightAtLine:function(a,b){var c=!1,d=this.doc.first+this.doc.size-1;a<this.doc.first?a=this.doc.first:a>d&&(a=d,c=!0);var e=ye(this.doc,a);return vb(this,ye(this.doc,a),{top:0,left:0},b||"page").top+(c?e.height:0)},defaultTextHeight:function(){return Db(this.display)},defaultCharWidth:function(){return Eb(this.display)},setGutterMarker:Ib(null,function(a,b,c){return _c(this,a,function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&wf(d)&&(a.gutterMarkers=null),!0})}),clearGutter:Ib(null,function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,Lb(b,d,d+1),wf(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass";if(a[d]){if(new RegExp("(?:^|\\s)"+c+"(?:$|\\s)").test(a[d]))return!1;a[d]+=" "+c}else a[d]=c;return!0})}),removeLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass",e=a[d];if(!e)return!1;if(null==c)a[d]=null;else{var f=e.match(new RegExp("(?:^|\\s+)"+c+"(?:$|\\s+)"));if(!f)return!1;var g=f.index+f[0].length;a[d]=e.slice(0,f.index)+(f.index&&g!=e.length?" ":"")+e.slice(g)||null}return!0})}),addLineWidget:Ib(null,function(a,b,c){return Zd(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if("number"==typeof a){if(!Oc(this.doc,a))return null;var b=a;if(a=ye(this.doc,a),!a)return null}else{var b=Ce(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.showingFrom,to:this.display.showingTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=yb(this,Mc(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&Wc(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:Ib(null,pc),triggerOnKeyPress:Ib(null,qc),triggerOnKeyUp:Ib(null,nc),execCommand:function(a){return pd.hasOwnProperty(a)?pd[a](this):void 0},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=Mc(this.doc,a);b>f&&(g=ad(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:Ib(null,function(a,b){var d,c=this.doc.sel;d=c.shift||c.extend||Hc(c.from,c.to)?ad(this.doc,c.head,a,b,this.options.rtlMoveVisually):0>a?c.from:c.to,Pc(this.doc,d,d,a)}),deleteH:Ib(null,function(a,b){var c=this.doc.sel;Hc(c.from,c.to)?Fc(this.doc,"",c.from,ad(this.doc,c.head,a,b,!1),"+delete"):Fc(this.doc,"",c.from,c.to,"+delete"),this.curOp.userSelChange=!0}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=Mc(this.doc,a);b>g;++g){var i=yb(this,h,"div");if(null==f?f=i.left:i.left=f,h=bd(this,i,e,c),h.hitSide)break}return h},moveV:Ib(null,function(a,b){var d,e,c=this.doc.sel;if(c.shift||c.extend||Hc(c.from,c.to)){var f=yb(this,c.head,"div");null!=c.goalColumn&&(f.left=c.goalColumn),d=bd(this,f,a,b),"page"==b&&Zc(this,0,xb(this,d,"div").top-f.top),e=f.left}else d=0>a?c.from:c.to;Pc(this.doc,d,d,a),null!=e&&(c.goalColumn=e)}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?this.display.cursor.className+=" CodeMirror-overwrite":this.display.cursor.className=this.display.cursor.className.replace(" CodeMirror-overwrite",""),$e(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return document.activeElement==this.display.input},scrollTo:Ib(null,function(a,b){Yc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller,b=gf;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:Ib(null,function(a,b){null==a?a={from:this.doc.sel.head,to:null}:"number"==typeof a?a={from:Gc(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),b||(b=0);var c=a;null!=a.from.line&&(this.curOp.scrollToPos={from:a.from,to:a.to,margin:b},c={from:yb(this,a.from),to:yb(this,a.to)});var d=Xc(this,Math.min(c.from.left,c.to.left),Math.min(c.from.top,c.to.top)-b,Math.max(c.from.right,c.to.right),Math.max(c.from.bottom,c.to.bottom)+b);Yc(this,d.scrollLeft,d.scrollTop)}),setSize:Ib(null,function(a,b){function c(a){return"number"==typeof a||/^\d+$/.test(String(a))?a+"px":a}null!=a&&(this.display.wrapper.style.width=c(a)),null!=b&&(this.display.wrapper.style.height=c(b)),this.options.lineWrapping&&(this.display.measureLineCache.length=this.display.measureLineCachePos=0),this.curOp.forceUpdate=!0,$e(this,"refresh",this)}),operation:function(a){return Kb(this,a)},refresh:Ib(null,function(){var a=this.display.cachedTextHeight;sb(this),Yc(this,this.doc.scrollLeft,this.doc.scrollTop),Lb(this),(null==a||Math.abs(a-Db(this.display))>.5)&&F(this),$e(this,"refresh",this)}),swapDoc:Ib(null,function(a){var b=this.doc;return b.cm=null,xe(this,a),sb(this),Pb(this,!0),Yc(this,a.scrollLeft,a.scrollTop),bf(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},ff(z);var ed=z.optionHandlers={},fd=z.defaults={},hd=z.Init={toString:function(){return"CodeMirror.Init"}};gd("value","",function(a,b){a.setValue(b)},!0),gd("mode",null,function(a,b){a.doc.modeOption=b,B(a)},!0),gd("indentUnit",2,B,!0),gd("indentWithTabs",!1),gd("smartIndent",!0),gd("tabSize",4,function(a){C(a),sb(a),Lb(a)},!0),gd("specialChars",/[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g,function(a,b){a.options.specialChars=new RegExp(b.source+(b.test("	")?"":"|	"),"g"),a.refresh()},!0),gd("specialCharPlaceholder",je,function(a){a.refresh()},!0),gd("electricChars",!0),gd("rtlMoveVisually",!t),gd("wholeLineUpdateBefore",!0),gd("theme","default",function(a){H(a),I(a)},!0),gd("keyMap","default",G),gd("extraKeys",null),gd("onKeyEvent",null),gd("onDragEvent",null),gd("lineWrapping",!1,D,!0),gd("gutters",[],function(a){M(a.options),I(a)},!0),gd("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?S(a.display)+"px":"0",a.refresh()},!0),gd("coverGutterNextToScrollbar",!1,N,!0),gd("lineNumbers",!1,function(a){M(a.options),I(a)},!0),gd("firstLineNumber",1,I,!0),gd("lineNumberFormatter",function(a){return a},I,!0),gd("showCursorWhenSelecting",!1,ab,!0),gd("resetSelectionOnContextMenu",!0),gd("readOnly",!1,function(a,b){"nocursor"==b?(sc(a),a.display.input.blur(),a.display.disabled=!0):(a.display.disabled=!1,b||Pb(a,!0))}),gd("disableInput",!1,function(a,b){b||Pb(a,!0)},!0),gd("dragDrop",!0),gd("cursorBlinkRate",530),gd("cursorScrollMargin",0),gd("cursorHeight",1),gd("workTime",100),gd("workDelay",100),gd("flattenSpans",!0,C,!0),gd("addModeClass",!1,C,!0),gd("pollInterval",100),gd("undoDepth",40,function(a,b){a.doc.history.undoDepth=b}),gd("historyEventDelay",500),gd("viewportMargin",10,function(a){a.refresh()},!0),gd("maxHighlightLength",1e4,C,!0),gd("crudeMeasuringFrom",1e4),gd("moveInputWithCursor",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),gd("tabindex",null,function(a,b){a.display.input.tabIndex=b||""}),gd("autofocus",null);var id=z.modes={},jd=z.mimeModes={};z.defineMode=function(a,b){if(z.defaults.mode||"null"==a||(z.defaults.mode=a),arguments.length>2){b.dependencies=[];for(var c=2;c<arguments.length;++c)b.dependencies.push(arguments[c])}id[a]=b},z.defineMIME=function(a,b){jd[a]=b},z.resolveMode=function(a){if("string"==typeof a&&jd.hasOwnProperty(a))a=jd[a];else if(a&&"string"==typeof a.name&&jd.hasOwnProperty(a.name)){var b=jd[a.name];"string"==typeof b&&(b={name:b}),a=qf(b,a),a.name=b.name}else if("string"==typeof a&&/^[\w\-]+\/[\w\-]+\+xml$/.test(a))return z.resolveMode("application/xml");return"string"==typeof a?{name:a}:a||{name:"null"}},z.getMode=function(a,b){var b=z.resolveMode(b),c=id[b.name];if(!c)return z.getMode(a,"text/plain");var d=c(a,b);if(kd.hasOwnProperty(b.name)){var e=kd[b.name];for(var f in e)e.hasOwnProperty(f)&&(d.hasOwnProperty(f)&&(d["_"+f]=d[f]),d[f]=e[f])}if(d.name=b.name,b.helperType&&(d.helperType=b.helperType),b.modeProps)for(var f in b.modeProps)d[f]=b.modeProps[f];return d},z.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),z.defineMIME("text/plain","null");var kd=z.modeExtensions={};z.extendMode=function(a,b){var c=kd.hasOwnProperty(a)?kd[a]:kd[a]={};rf(b,c)},z.defineExtension=function(a,b){z.prototype[a]=b},z.defineDocExtension=function(a,b){te.prototype[a]=b},z.defineOption=gd;var ld=[];z.defineInitHook=function(a){ld.push(a)};var md=z.helpers={};z.registerHelper=function(a,b,c){md.hasOwnProperty(a)||(md[a]=z[a]={_global:[]}),md[a][b]=c},z.registerGlobalHelper=function(a,b,c,d){z.registerHelper(a,b,d),md[a]._global.push({pred:c,val:d})},z.isWordChar=vf,z.copyState=nd,z.startState=od,z.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var pd=z.commands={selectAll:function(a){a.setSelection(Gc(a.firstLine(),0),Gc(a.lastLine()))},killLine:function(a){var b=a.getCursor(!0),c=a.getCursor(!1),d=!Hc(b,c);d||a.getLine(b.line).length!=b.ch?a.replaceRange("",b,d?c:Gc(b.line),"+delete"):a.replaceRange("",b,Gc(b.line+1,0),"+delete")},deleteLine:function(a){var b=a.getCursor().line;a.replaceRange("",Gc(b,0),Gc(b+1,0),"+delete")},delLineLeft:function(a){var b=a.getCursor();a.replaceRange("",Gc(b.line,0),b,"+delete")},undo:function(a){a.undo()},redo:function(a){a.redo()},goDocStart:function(a){a.extendSelection(Gc(a.firstLine(),0))},goDocEnd:function(a){a.extendSelection(Gc(a.lastLine()))},goLineStart:function(a){a.extendSelection(Tf(a,a.getCursor().line))},goLineStartSmart:function(a){var b=a.getCursor(),c=Tf(a,b.line),d=a.getLineHandle(c.line),e=Fe(d);if(e&&0!=e[0].level)a.extendSelection(c);else{var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;a.extendSelection(Gc(c.line,g?0:f))}},goLineEnd:function(a){a.extendSelection(Uf(a,a.getCursor().line))},goLineRight:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:b},"div"))},goLineLeft:function(a){var b=a.charCoords(a.getCursor(),"div").top+5;a.extendSelection(a.coordsChar({left:0,top:b},"div"))},goLineUp:function(a){a.moveV(-1,"line")},goLineDown:function(a){a.moveV(1,"line")},goPageUp:function(a){a.moveV(-1,"page")},goPageDown:function(a){a.moveV(1,"page")},goCharLeft:function(a){a.moveH(-1,"char")},goCharRight:function(a){a.moveH(1,"char")},goColumnLeft:function(a){a.moveH(-1,"column")},goColumnRight:function(a){a.moveH(1,"column")},goWordLeft:function(a){a.moveH(-1,"word")},goGroupRight:function(a){a.moveH(1,"group")},goGroupLeft:function(a){a.moveH(-1,"group")},goWordRight:function(a){a.moveH(1,"word")},delCharBefore:function(a){a.deleteH(-1,"char")},delCharAfter:function(a){a.deleteH(1,"char")},delWordBefore:function(a){a.deleteH(-1,"word")},delWordAfter:function(a){a.deleteH(1,"word")},delGroupBefore:function(a){a.deleteH(-1,"group")},delGroupAfter:function(a){a.deleteH(1,"group")},indentAuto:function(a){a.indentSelection("smart")},indentMore:function(a){a.indentSelection("add")},indentLess:function(a){a.indentSelection("subtract")},insertTab:function(a){a.replaceSelection("	","end","+input")},defaultTab:function(a){a.somethingSelected()?a.indentSelection("add"):a.replaceSelection("	","end","+input")},transposeChars:function(a){var b=a.getCursor(),c=a.getLine(b.line);b.ch>0&&b.ch<c.length-1&&a.replaceRange(c.charAt(b.ch)+c.charAt(b.ch-1),Gc(b.line,b.ch-1),Gc(b.line,b.ch+1))},newlineAndIndent:function(a){Ib(a,function(){a.replaceSelection("\n","end","+input"),a.indentLine(a.getCursor().line,null,!0)})()},toggleOverwrite:function(a){a.toggleOverwrite()}},qd=z.keyMap={};qd.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite"},qd.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-Up":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Down":"goDocEnd","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore",fallthrough:"basic"},qd.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineStart","Cmd-Right":"goLineEnd","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delLineLeft",fallthrough:["basic","emacsy"]},qd["default"]=s?qd.macDefault:qd.pcDefault,qd.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars"},z.lookupKey=sd,z.isModifierKey=td,z.keyName=ud,z.fromTextArea=function(a,b){function e(){a.value=i.getValue()}if(b||(b={}),b.value=a.value,!b.tabindex&&a.tabindex&&(b.tabindex=a.tabindex),!b.placeholder&&a.placeholder&&(b.placeholder=a.placeholder),null==b.autofocus){var c=document.body;try{c=document.activeElement}catch(d){}b.autofocus=c==a||null!=a.getAttribute("autofocus")&&c==document.body}if(a.form&&(Ye(a.form,"submit",e),!b.leaveSubmitMethodAlone)){var f=a.form,g=f.submit;try{var h=f.submit=function(){e(),f.submit=g,f.submit(),f.submit=h}}catch(d){}}a.style.display="none";var i=z(function(b){a.parentNode.insertBefore(b,a.nextSibling)},b);return i.save=e,i.getTextArea=function(){return a
-},i.toTextArea=function(){e(),a.parentNode.removeChild(i.getWrapperElement()),a.style.display="",a.form&&(Ze(a.form,"submit",e),"function"==typeof a.form.submit&&(a.form.submit=g))},i},vd.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.pos<this.string.length?this.string.charAt(this.pos++):void 0},eat:function(a){var b=this.string.charAt(this.pos);if("string"==typeof a)var c=b==a;else var c=b&&(a.test?a.test(b):a(b));return c?(++this.pos,b):void 0},eatWhile:function(a){for(var b=this.pos;this.eat(a););return this.pos>b},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=kf(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?kf(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return kf(this.string,null,this.tabSize)-(this.lineStart?kf(this.string,this.lineStart,this.tabSize):0)},match:function(a,b,c){if("string"!=typeof a){var f=this.string.slice(this.pos).match(a);return f&&f.index>0?null:(f&&b!==!1&&(this.pos+=f[0].length),f)}var d=function(a){return c?a.toLowerCase():a},e=this.string.substr(this.pos,a.length);return d(e)==d(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}}},z.StringStream=vd,z.TextMarker=wd,ff(wd),wd.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Gb(a),ef(this,"clear")){var c=this.find();c&&bf(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;f<this.lines.length;++f){var g=this.lines[f],h=Bd(g.markedSpans,this);null!=h.to&&(e=Ce(g)),g.markedSpans=Cd(g.markedSpans,h),null!=h.from?d=Ce(g):this.collapsed&&!Sd(this.doc,g)&&a&&Be(g,Db(a.display))}if(a&&this.collapsed&&!a.options.lineWrapping)for(var f=0;f<this.lines.length;++f){var i=Rd(a.doc,this.lines[f]),j=K(a.doc,i);j>a.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&Lb(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&Sc(a)),bf(a,"markerCleared",a,this),b&&Hb(a)}},wd.prototype.find=function(a){for(var b,c,d=0;d<this.lines.length;++d){var e=this.lines[d],f=Bd(e.markedSpans,this);if(null!=f.from||null!=f.to){var g=Ce(e);null!=f.from&&(b=Gc(g,f.from)),null!=f.to&&(c=Gc(g,f.to))}}return"bookmark"!=this.type||a?b&&{from:b,to:c}:b},wd.prototype.changed=function(){var a=this.find(),b=this.doc.cm;if(a&&b){"bookmark"!=this.type&&(a=a.from);var c=ye(this.doc,a.line);if(nb(b,c),a.line>=b.display.showingFrom&&a.line<b.display.showingTo){for(var d=b.display.lineDiv.firstChild;d;d=d.nextSibling)if(d.lineObj==c){d.offsetHeight!=c.height&&Be(c,d.offsetHeight);break}Kb(b,function(){b.curOp.selectionChanged=b.curOp.forceUpdate=b.curOp.updateMaxLine=!0})}}},wd.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&-1!=pf(b.maybeHiddenMarkers,this)||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},wd.prototype.detachLine=function(a){if(this.lines.splice(pf(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}};var xd=0;z.SharedTextMarker=zd,ff(zd),zd.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var a=0;a<this.markers.length;++a)this.markers[a].clear();bf(this,"clear")}},zd.prototype.find=function(){return this.primary.find()};var Wd=z.LineWidget=function(a,b,c){if(c)for(var d in c)c.hasOwnProperty(d)&&(this[d]=c[d]);this.cm=a,this.node=b};ff(Wd),Wd.prototype.clear=Xd(function(){var a=this.line.widgets,b=Ce(this.line);if(null!=b&&a){for(var c=0;c<a.length;++c)a[c]==this&&a.splice(c--,1);a.length||(this.line.widgets=null);var d=Ee(this.cm,this.line)<this.cm.doc.scrollTop;Be(this.line,Math.max(0,this.line.height-Yd(this))),d&&Zc(this.cm,0,-this.height),Lb(this.cm,b,b+1)}}),Wd.prototype.changed=Xd(function(){var a=this.height;this.height=null;var b=Yd(this)-a;if(b){Be(this.line,this.line.height+b);var c=Ce(this.line);Lb(this.cm,c,c+1)}});var $d=z.Line=function(a,b,c){this.text=a,Vd(this,b),this.height=c?c(this):1};ff($d),$d.prototype.lineNo=function(){return Ce(this)};var fe={},ge={};qe.prototype={chunkSize:function(){return this.lines.length},removeInner:function(a,b){for(var c=a,d=a+b;d>c;++c){var e=this.lines[c];this.height-=e.height,ae(e),bf(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.splice.apply(a,[a.length,0].concat(this.lines))},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0,e=b.length;e>d;++d)b[d].parent=this},iterN:function(a,b,c){for(var d=a+b;d>a;++a)if(c(this.lines[a]))return!0}},re.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;c<this.children.length;++c){var d=this.children[c],e=d.chunkSize();if(e>a){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25){var h=[];this.collapse(h),this.children=[new qe(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0,c=this.children.length;c>b;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>=a){if(f.insertInner(a,b,c),f.lines&&f.lines.length>50){for(;f.lines.length>50;){var h=f.lines.splice(f.lines.length-25,25),i=new qe(h);f.height-=i.height,this.children.splice(d+1,0,i),i.parent=this}this.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new re(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=pf(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new re(a.children);d.parent=a,a.children=[d,c],a=d}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>a){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var se=0,te=z.Doc=function(a,b,c){if(!(this instanceof te))return new te(a,b,c);null==c&&(c=0),re.call(this,[new qe([new $d("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.history=Ge(),this.cleanGeneration=1,this.frontier=c;var d=Gc(c,0);this.sel={from:d,to:d,head:d,anchor:d,shift:!1,extend:!1,goalColumn:null},this.id=++se,this.modeOption=b,"string"==typeof a&&(a=Kf(a)),pe(this,{from:d,to:d,text:a},null,{head:d,anchor:d})};te.prototype=qf(re.prototype,{constructor:te,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0,e=b.length;e>d;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=Ae(this,this.first,this.first+this.size);return a===!1?b:b.join(a||"\n")},setValue:function(a){var b=Gc(this.first,0),c=this.first+this.size-1;zc(this,{from:b,to:Gc(c,ye(this,c).text.length),text:Kf(a),origin:"setValue"},{head:b,anchor:b},!0)},replaceRange:function(a,b,c,d){b=Mc(this,b),c=c?Mc(this,c):b,Fc(this,a,b,c,d)},getRange:function(a,b,c){var d=ze(this,Mc(this,a),Mc(this,b));return c===!1?d:d.join(c||"\n")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},setLine:function(a,b){Oc(this,a)&&Fc(this,b,Gc(a,0),Mc(this,Gc(a)))},removeLine:function(a){a?Fc(this,"",Mc(this,Gc(a-1)),Mc(this,Gc(a))):Fc(this,"",Gc(0,0),Mc(this,Gc(1,0)))},getLineHandle:function(a){return Oc(this,a)?ye(this,a):void 0},getLineNumber:function(a){return Ce(a)},getLineHandleVisualStart:function(a){return"number"==typeof a&&(a=ye(this,a)),Rd(this,a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return Mc(this,a)},getCursor:function(a){var c,b=this.sel;return c=null==a||"head"==a?b.head:"anchor"==a?b.anchor:"end"==a||a===!1?b.to:b.from,Kc(c)},somethingSelected:function(){return!Hc(this.sel.head,this.sel.anchor)},setCursor:Jb(function(a,b,c){var d=Mc(this,"number"==typeof a?Gc(a,b||0):a);c?Pc(this,d):Rc(this,d,d)}),setSelection:Jb(function(a,b,c){Rc(this,Mc(this,a),Mc(this,b||a),c)}),extendSelection:Jb(function(a,b,c){Pc(this,Mc(this,a),b&&Mc(this,b),c)}),getSelection:function(a){return this.getRange(this.sel.from,this.sel.to,a)},replaceSelection:function(a,b,c){zc(this,{from:this.sel.from,to:this.sel.to,text:Kf(a),origin:c},b||"around")},undo:Jb(function(){Bc(this,"undo")}),redo:Jb(function(){Bc(this,"redo")}),setExtending:function(a){this.sel.extend=a},historySize:function(){var a=this.history;return{undo:a.done.length,redo:a.undone.length}},clearHistory:function(){this.history=Ge(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(a){return a&&(this.history.lastOp=this.history.lastOrigin=null),this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:Me(this.history.done),undone:Me(this.history.undone)}},setHistory:function(a){var b=this.history=Ge(this.history.maxGeneration);b.done=a.done.slice(0),b.undone=a.undone.slice(0)},markText:function(a,b,c){return yd(this,Mc(this,a),Mc(this,b),c,"range")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft,clearWhenEmpty:!1};return a=Mc(this,a),yd(this,a,a,c,"bookmark")},findMarksAt:function(a){a=Mc(this,a);var b=[],c=ye(this,a.line).markedSpans;if(c)for(var d=0;d<c.length;++d){var e=c[d];(null==e.from||e.from<=a.ch)&&(null==e.to||e.to>=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b){a=Mc(this,a),b=Mc(this,b);var c=[],d=a.line;return this.iter(a.line,b.line+1,function(e){var f=e.markedSpans;if(f)for(var g=0;g<f.length;g++){var h=f[g];d==a.line&&a.ch>h.to||null==h.from&&d!=a.line||d==b.line&&h.from>b.ch||c.push(h.marker.parent||h.marker)}++d}),c},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;d<c.length;++d)null!=c[d].from&&a.push(c[d].marker)}),a},posFromIndex:function(a){var b,c=this.first;return this.iter(function(d){var e=d.text.length+1;return e>a?(b=a,!0):(a-=e,++c,void 0)}),Mc(this,Gc(c,b))},indexFromPos:function(a){a=Mc(this,a);var b=a.ch;return a.line<this.first||a.ch<0?0:(this.iter(this.first,a.line,function(a){b+=a.text.length+1}),b)},copy:function(a){var b=new te(Ae(this,this.first,this.first+this.size),this.modeOption,this.first);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel={from:this.sel.from,to:this.sel.to,head:this.sel.head,anchor:this.sel.anchor,shift:this.sel.shift,extend:!1,goalColumn:this.sel.goalColumn},a&&(b.history.undoDepth=this.history.undoDepth,b.setHistory(this.getHistory())),b},linkedDoc:function(a){a||(a={});var b=this.first,c=this.first+this.size;null!=a.from&&a.from>b&&(b=a.from),null!=a.to&&a.to<c&&(c=a.to);var d=new te(Ae(this,b,c),a.mode||this.modeOption,b);return a.sharedHist&&(d.history=this.history),(this.linked||(this.linked=[])).push({doc:d,sharedHist:a.sharedHist}),d.linked=[{doc:this,isParent:!0,sharedHist:a.sharedHist}],d},unlinkDoc:function(a){if(a instanceof z&&(a=a.doc),this.linked)for(var b=0;b<this.linked.length;++b){var c=this.linked[b];if(c.doc==a){this.linked.splice(b,1),a.unlinkDoc(this);break}}if(a.history==this.history){var d=[a.id];we(a,function(a){d.push(a.id)},!0),a.history=Ge(),a.history.done=Me(this.history.done,d),a.history.undone=Me(this.history.undone,d)}},iterLinkedDocs:function(a){we(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),te.prototype.eachLine=te.prototype.iter;var ue="iter insert remove copy getEditor".split(" ");for(var ve in te.prototype)te.prototype.hasOwnProperty(ve)&&pf(ue,ve)<0&&(z.prototype[ve]=function(a){return function(){return a.apply(this.doc,arguments)}}(te.prototype[ve]));ff(te),z.e_stop=Ve,z.e_preventDefault=Se,z.e_stopPropagation=Te;var _e,af=0;z.on=Ye,z.off=Ze,z.signal=$e;var gf=30,hf=z.Pass={toString:function(){return"CodeMirror.Pass"}};jf.prototype={set:function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)}},z.countColumn=kf;var lf=[""],uf=/[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,xf=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;z.replaceGetRect=function(a){Df=a};var Ef=function(){if(d)return!1;var a=zf("div");return"draggable"in a||"dragDrop"in a}();a?Ff=function(a,b){return 36==a.charCodeAt(b-1)&&39==a.charCodeAt(b)}:l&&!/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)?Ff=function(a,b){return/\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(a.slice(b-1,b+1))}:h&&/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent)?Ff=function(a,b){var c=a.charCodeAt(b-1);return c>=8208&&8212>=c}:h&&(Ff=function(a,b){if(b>1&&45==a.charCodeAt(b-1)){if(/\w/.test(a.charAt(b-2))&&/[^\-?\.]/.test(a.charAt(b)))return!0;if(b>2&&/[\d\.,]/.test(a.charAt(b-2))&&/[\d\.,]/.test(a.charAt(b)))return!1}return/[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|\u2026[\w~`@#$%\^&*(_=+{[><]/.test(a.slice(b-1,b+1))});var Gf,If,Kf=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)};z.splitLines=Kf;var Lf=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},Mf=function(){var a=zf("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),Nf={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};z.keyNames=Nf,function(){for(var a=0;10>a;a++)Nf[a+48]=Nf[a+96]=String(a);for(var a=65;90>=a;a++)Nf[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Nf[a+111]=Nf[a+63235]="F"+a}();var Wf,_f=function(){function c(c){return 255>=c?a.charAt(c):c>=1424&&1524>=c?"R":c>=1536&&1791>=c?b.charAt(c-1536):c>=1792&&2220>=c?"r":"L"}var a="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL",b="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(a){if(!d.test(a))return!1;for(var l,b=a.length,j=[],k=0;b>k;++k)j.push(l=c(a.charCodeAt(k)));for(var k=0,m=i;b>k;++k){var l=j[k];"m"==l?j[k]=m:m=l}for(var k=0,n=i;b>k;++k){var l=j[k];"1"==l&&"r"==n?j[k]="n":f.test(l)&&(n=l,"r"==l&&(j[k]="R"))}for(var k=1,m=j[0];b-1>k;++k){var l=j[k];"+"==l&&"1"==m&&"1"==j[k+1]?j[k]="1":","!=l||m!=j[k+1]||"1"!=m&&"n"!=m||(j[k]=m),m=l}for(var k=0;b>k;++k){var l=j[k];if(","==l)j[k]="N";else if("%"==l){for(var o=k+1;b>o&&"%"==j[o];++o);for(var p=k&&"!"==j[k-1]||b>o&&"1"==j[o]?"1":"N",q=k;o>q;++q)j[q]=p;k=o-1}}for(var k=0,n=i;b>k;++k){var l=j[k];"L"==n&&"1"==l?j[k]="L":f.test(l)&&(n=l)}for(var k=0;b>k;++k)if(e.test(j[k])){for(var o=k+1;b>o&&e.test(j[o]);++o);for(var r="L"==(k?j[k-1]:i),s="L"==(b>o?j[o]:i),p=r||s?"L":"R",q=k;o>q;++q)j[q]=p;k=o-1}for(var u,t=[],k=0;b>k;)if(g.test(j[k])){var v=k;for(++k;b>k&&g.test(j[k]);++k);t.push({from:v,to:k,level:0})}else{var w=k,x=t.length;for(++k;b>k&&"L"!=j[k];++k);for(var q=w;k>q;)if(h.test(j[q])){q>w&&t.splice(x,0,{from:w,to:q,level:1});var y=q;for(++q;k>q&&h.test(j[q]);++q);t.splice(x,0,{from:y,to:q,level:2}),w=q}else++q;k>w&&t.splice(x,0,{from:w,to:k,level:1})}return 1==t[0].level&&(u=a.match(/^\s+/))&&(t[0].from=u[0].length,t.unshift({from:0,to:u[0].length,level:0})),1==nf(t).level&&(u=a.match(/\s+$/))&&(nf(t).to-=u[0].length,t.push({from:b-u[0].length,to:b,level:0})),t[0].level!=nf(t).level&&t.push({from:b,to:b,level:t[0].level}),t}}();return z.version="3.22.1",z}(),CodeMirror.defineMode("javascript",function(a,b){function k(a){for(var c,b=!1,d=!1;null!=(c=a.next());){if(!b){if("/"==c&&!d)return;"["==c?d=!0:d&&"]"==c&&(d=!1)}b=!b&&"\\"==c}}function n(a,b,c){return l=a,m=c,b}function o(a,b){var c=a.next();if('"'==c||"'"==c)return b.tokenize=p(c),b.tokenize(a,b);if("."==c&&a.match(/^\d+(?:[eE][+\-]?\d+)?/))return n("number","number");if("."==c&&a.match(".."))return n("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(c))return n(c);if("="==c&&a.eat(">"))return n("=>","operator");if("0"==c&&a.eat(/x/i))return a.eatWhile(/[\da-f]/i),n("number","number");if(/\d/.test(c))return a.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/),n("number","number");if("/"==c)return a.eat("*")?(b.tokenize=q,q(a,b)):a.eat("/")?(a.skipToEnd(),n("comment","comment")):"operator"==b.lastType||"keyword c"==b.lastType||"sof"==b.lastType||/^[\[{}\(,;:]$/.test(b.lastType)?(k(a),a.eatWhile(/[gimy]/),n("regexp","string-2")):(a.eatWhile(i),n("operator","operator",a.current()));if("`"==c)return b.tokenize=r,r(a,b);if("#"==c)return a.skipToEnd(),n("error","error");if(i.test(c))return a.eatWhile(i),n("operator","operator",a.current());a.eatWhile(/[\w\$_]/);var d=a.current(),e=h.propertyIsEnumerable(d)&&h[d];return e&&"."!=b.lastType?n(e.type,e.style,d):n("variable","variable",d)}function p(a){return function(b,c){var f,d=!1;if(e&&"@"==b.peek()&&b.match(j))return c.tokenize=o,n("jsonld-keyword","meta");for(;null!=(f=b.next())&&(f!=a||d);)d=!d&&"\\"==f;return d||(c.tokenize=o),n("string","string")}}function q(a,b){for(var d,c=!1;d=a.next();){if("/"==d&&c){b.tokenize=o;break}c="*"==d}return n("comment","comment")}function r(a,b){for(var d,c=!1;null!=(d=a.next());){if(!c&&("`"==d||"$"==d&&a.eat("{"))){b.tokenize=o;break}c=!c&&"\\"==d}return n("quasi","string-2",a.current())}function t(a,b){b.fatArrowAt&&(b.fatArrowAt=null);var c=a.string.indexOf("=>",a.start);if(!(0>c)){for(var d=0,e=!1,f=c-1;f>=0;--f){var g=a.string.charAt(f),h=s.indexOf(g);if(h>=0&&3>h){if(!d){++f;break}if(0==--d)break}else if(h>=3&&6>h)++d;else if(/[$\w]/.test(g))e=!0;else if(e&&!d){++f;break}}e&&!d&&(b.fatArrowAt=f)}}function v(a,b,c,d,e,f){this.indented=a,this.column=b,this.type=c,this.prev=e,this.info=f,null!=d&&(this.align=d)}function w(a,b){for(var c=a.localVars;c;c=c.next)if(c.name==b)return!0;for(var d=a.context;d;d=d.prev)for(var c=d.vars;c;c=c.next)if(c.name==b)return!0}function x(a,b,c,d,e){var g=a.cc;for(y.state=a,y.stream=e,y.marked=null,y.cc=g,a.lexical.hasOwnProperty("align")||(a.lexical.align=!0);;){var h=g.length?g.pop():f?J:I;if(h(c,d)){for(;g.length&&g[g.length-1].lex;)g.pop()();return y.marked?y.marked:"variable"==c&&w(a,d)?"variable-2":b}}}function z(){for(var a=arguments.length-1;a>=0;a--)y.cc.push(arguments[a])}function A(){return z.apply(null,arguments),!0}function B(a){function c(b){for(var c=b;c;c=c.next)if(c.name==a)return!0;return!1}var d=y.state;if(d.context){if(y.marked="def",c(d.localVars))return;d.localVars={name:a,next:d.localVars}}else{if(c(d.globalVars))return;b.globalVars&&(d.globalVars={name:a,next:d.globalVars})}}function D(){y.state.context={prev:y.state.context,vars:y.state.localVars},y.state.localVars=C}function E(){y.state.localVars=y.state.context.vars,y.state.context=y.state.context.prev}function F(a,b){var c=function(){var c=y.state,d=c.indented;"stat"==c.lexical.type&&(d=c.lexical.indented),c.lexical=new v(d,y.stream.column(),a,null,c.lexical,b)};return c.lex=!0,c}function G(){var a=y.state;a.lexical.prev&&(")"==a.lexical.type&&(a.indented=a.lexical.indented),a.lexical=a.lexical.prev)}function H(a){return function(b){return b==a?A():";"==a?z():A(arguments.callee)}}function I(a,b){return"var"==a?A(F("vardef",b.length),cb,H(";"),G):"keyword a"==a?A(F("form"),J,I,G):"keyword b"==a?A(F("form"),I,G):"{"==a?A(F("}"),_,G):";"==a?A():"if"==a?A(F("form"),J,I,G,hb):"function"==a?A(nb):"for"==a?A(F("form"),ib,I,G):"variable"==a?A(F("stat"),U):"switch"==a?A(F("form"),J,F("}","switch"),H("{"),_,G,G):"case"==a?A(J,H(":")):"default"==a?A(H(":")):"catch"==a?A(F("form"),D,H("("),ob,H(")"),I,G,E):"module"==a?A(F("form"),D,sb,E,G):"class"==a?A(F("form"),pb,rb,G):"export"==a?A(F("form"),tb,G):"import"==a?A(F("form"),ub,G):z(F("stat"),J,H(";"),G)}function J(a){return L(a,!1)}function K(a){return L(a,!0)}function L(a,b){if(y.state.fatArrowAt==y.stream.start){var c=b?T:S;if("("==a)return A(D,F(")"),Z(db,")"),G,H("=>"),c,E);if("variable"==a)return z(D,db,H("=>"),c,E)}var d=b?P:O;return u.hasOwnProperty(a)?A(d):"function"==a?A(nb):"keyword c"==a?A(b?N:M):"("==a?A(F(")"),M,zb,H(")"),G,d):"operator"==a||"spread"==a?A(b?K:J):"["==a?A(F("]"),xb,G,d):"{"==a?$(W,"}",null,d):A()}function M(a){return a.match(/[;\}\)\],]/)?z():z(J)}function N(a){return a.match(/[;\}\)\],]/)?z():z(K)}function O(a,b){return","==a?A(J):P(a,b,!1)}function P(a,b,c){var d=0==c?O:P,e=0==c?J:K;return"=>"==b?A(D,c?T:S,E):"operator"==a?/\+\+|--/.test(b)?A(d):"?"==b?A(J,H(":"),e):A(e):"quasi"==a?(y.cc.push(d),Q(b)):";"!=a?"("==a?$(K,")","call",d):"."==a?A(V,d):"["==a?A(F("]"),M,H("]"),G,d):void 0:void 0}function Q(a){return"${"!=a.slice(a.length-2)?A():A(J,R)}function R(a){return"}"==a?(y.marked="string-2",y.state.tokenize=r,A()):void 0}function S(a){return t(y.stream,y.state),"{"==a?z(I):z(J)}function T(a){return t(y.stream,y.state),"{"==a?z(I):z(K)}function U(a){return":"==a?A(G,I):z(O,H(";"),G)}function V(a){return"variable"==a?(y.marked="property",A()):void 0}function W(a,b){if("variable"==a){if(y.marked="property","get"==b||"set"==b)return A(X)}else if("number"==a||"string"==a)y.marked=e?"property":a+" property";else if("["==a)return A(J,H("]"),Y);return u.hasOwnProperty(a)?A(Y):void 0}function X(a){return"variable"!=a?z(Y):(y.marked="property",A(nb))}function Y(a){return":"==a?A(K):"("==a?z(nb):void 0}function Z(a,b){function c(d){if(","==d){var e=y.state.lexical;return"call"==e.info&&(e.pos=(e.pos||0)+1),A(a,c)}return d==b?A():A(H(b))}return function(d){return d==b?A():z(a,c)}}function $(a,b,c){for(var d=3;d<arguments.length;d++)y.cc.push(arguments[d]);return A(F(b,c),Z(a,b),G)}function _(a){return"}"==a?A():z(I,_)}function ab(a){return g&&":"==a?A(bb):void 0}function bb(a){return"variable"==a?(y.marked="variable-3",A()):void 0}function cb(){return z(db,ab,fb,gb)}function db(a,b){return"variable"==a?(B(b),A()):"["==a?$(db,"]"):"{"==a?$(eb,"}"):void 0}function eb(a,b){return"variable"!=a||y.stream.match(/^\s*:/,!1)?("variable"==a&&(y.marked="property"),A(H(":"),db,fb)):(B(b),A(fb))}function fb(a,b){return"="==b?A(K):void 0}function gb(a){return","==a?A(cb):void 0}function hb(a,b){return"keyword b"==a&&"else"==b?A(F("form"),I,G):void 0}function ib(a){return"("==a?A(F(")"),jb,H(")"),G):void 0}function jb(a){return"var"==a?A(cb,H(";"),lb):";"==a?A(lb):"variable"==a?A(kb):z(J,H(";"),lb)}function kb(a,b){return"in"==b||"of"==b?(y.marked="keyword",A(J)):A(O,lb)}function lb(a,b){return";"==a?A(mb):"in"==b||"of"==b?(y.marked="keyword",A(J)):z(J,H(";"),mb)}function mb(a){")"!=a&&A(J)}function nb(a,b){return"*"==b?(y.marked="keyword",A(nb)):"variable"==a?(B(b),A(nb)):"("==a?A(D,F(")"),Z(ob,")"),G,I,E):void 0}function ob(a){return"spread"==a?A(ob):z(db,ab)}function pb(a,b){return"variable"==a?(B(b),A(qb)):void 0}function qb(a,b){return"extends"==b?A(J):void 0}function rb(a){return"{"==a?$(W,"}"):void 0}function sb(a,b){return"string"==a?A(I):"variable"==a?(B(b),A(wb)):void 0}function tb(a,b){return"*"==b?(y.marked="keyword",A(wb,H(";"))):"default"==b?(y.marked="keyword",A(J,H(";"))):z(I)}function ub(a){return"string"==a?A():z(vb,wb)}function vb(a,b){return"{"==a?$(vb,"}"):("variable"==a&&B(b),A())}function wb(a,b){return"from"==b?(y.marked="keyword",A(J)):void 0}function xb(a){return"]"==a?A():z(K,yb)}function yb(a){return"for"==a?z(zb,H("]")):","==a?A(Z(K,"]")):z(Z(K,"]"))}function zb(a){return"for"==a?A(ib,zb):"if"==a?A(J,zb):void 0}var l,m,c=a.indentUnit,d=b.statementIndent,e=b.jsonld,f=b.json||e,g=b.typescript,h=function(){function a(a){return{type:a,style:"keyword"}}var b=a("keyword a"),c=a("keyword b"),d=a("keyword c"),e=a("operator"),f={type:"atom",style:"atom"},h={"if":a("if"),"while":b,"with":b,"else":c,"do":c,"try":c,"finally":c,"return":d,"break":d,"continue":d,"new":d,"delete":d,"throw":d,"debugger":d,"var":a("var"),"const":a("var"),let:a("var"),"function":a("function"),"catch":a("catch"),"for":a("for"),"switch":a("switch"),"case":a("case"),"default":a("default"),"in":e,"typeof":e,"instanceof":e,"true":f,"false":f,"null":f,undefined:f,NaN:f,Infinity:f,"this":a("this"),module:a("module"),"class":a("class"),"super":a("atom"),yield:d,"export":a("export"),"import":a("import"),"extends":d};if(g){var i={type:"variable",style:"variable-3"},j={"interface":a("interface"),"extends":a("extends"),constructor:a("constructor"),"public":a("public"),"private":a("private"),"protected":a("protected"),"static":a("static"),string:i,number:i,bool:i,any:i};for(var k in j)h[k]=j[k]}return h}(),i=/[+\-*&%=<>!?|~^]/,j=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/,s="([{}])",u={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,"this":!0,"jsonld-keyword":!0},y={state:null,column:null,marked:null,cc:null},C={name:"this",next:{name:"arguments"}};return G.lex=!0,{startState:function(a){var d={tokenize:o,lastType:"sof",cc:[],lexical:new v((a||0)-c,0,"block",!1),localVars:b.localVars,context:b.localVars&&{vars:b.localVars},indented:0};return b.globalVars&&(d.globalVars=b.globalVars),d},token:function(a,b){if(a.sol()&&(b.lexical.hasOwnProperty("align")||(b.lexical.align=!1),b.indented=a.indentation(),t(a,b)),b.tokenize!=q&&a.eatSpace())return null;var c=b.tokenize(a,b);return"comment"==l?c:(b.lastType="operator"!=l||"++"!=m&&"--"!=m?l:"incdec",x(b,c,l,m,a))},indent:function(a,e){if(a.tokenize==q)return CodeMirror.Pass;if(a.tokenize!=o)return 0;for(var f=e&&e.charAt(0),g=a.lexical,h=a.cc.length-1;h>=0;--h){var i=a.cc[h];if(i==G)g=g.prev;else if(i!=hb)break}"stat"==g.type&&"}"==f&&(g=g.prev),d&&")"==g.type&&"stat"==g.prev.type&&(g=g.prev);var j=g.type,k=f==j;return"vardef"==j?g.indented+("operator"==a.lastType||","==a.lastType?g.info+1:0):"form"==j&&"{"==f?g.indented:"form"==j?g.indented+c:"stat"==j?g.indented+("operator"==a.lastType||","==a.lastType?d||c:0):"switch"!=g.info||k||0==b.doubleIndentSwitch?g.align?g.column+(k?0:1):g.indented+(k?0:c):g.indented+(/^(?:case|default)\b/.test(e)?c:2*c)},electricChars:":{}",blockCommentStart:f?null:"/*",blockCommentEnd:f?null:"*/",lineComment:f?null:"//",fold:"brace",helperType:f?"json":"javascript",jsonldMode:e,jsonMode:f}}),CodeMirror.defineMIME("text/javascript","javascript"),CodeMirror.defineMIME("text/ecmascript","javascript"),CodeMirror.defineMIME("application/javascript","javascript"),CodeMirror.defineMIME("application/ecmascript","javascript"),CodeMirror.defineMIME("application/json",{name:"javascript",json:!0}),CodeMirror.defineMIME("application/x-json",{name:"javascript",json:!0}),CodeMirror.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),CodeMirror.defineMIME("text/typescript",{name:"javascript",typescript:!0}),CodeMirror.defineMIME("application/typescript",{name:"javascript",typescript:!0}),function(){function d(a,d,e){function r(d,e,f){if(d.text){var h=m?0:d.text.length-1,i=m?d.text.length:-1;if(d.text.length>g)return null;for(null!=f&&(h=f+n);h!=i;h+=n){var j=d.text.charAt(h);if(q.test(j)&&a.getTokenTypeAt(b(e,h+1))==o){var k=c[j];if(">"==k.charAt(1)==m)p.push(j);else{if(p.pop()!=k.charAt(0))return{pos:h,match:!1};if(!p.length)return{pos:h,match:!0}}}}}}var f=a.state.matchBrackets,g=f&&f.maxScanLineLength||1e4,h=f&&f.maxScanLines||100,i=d||a.getCursor(),j=a.getLineHandle(i.line),k=i.ch-1,l=k>=0&&c[j.text.charAt(k)]||c[j.text.charAt(++k)];if(!l)return null;var m=">"==l.charAt(1),n=m?1:-1;if(e&&m!=(k==i.ch))return null;for(var t,o=a.getTokenTypeAt(b(i.line,k+1)),p=[j.text.charAt(k)],q=/[(){}[\]]/,s=i.line,u=m?Math.min(s+h,a.lineCount()):Math.max(-1,s-h);s!=u&&!(t=s==i.line?r(j,s,k):r(a.getLineHandle(s),s));s+=n);return{from:b(i.line,k),to:t&&b(s,t.pos),match:t&&t.match,forward:m}}function e(c,e){var f=c.state.matchBrackets.maxHighlightLineLength||1e3,g=d(c);if(!(!g||c.getLine(g.from.line).length>f||g.to&&c.getLine(g.to.line).length>f)){var h=g.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",i=c.markText(g.from,b(g.from.line,g.from.ch+1),{className:h}),j=g.to&&c.markText(g.to,b(g.to.line,g.to.ch+1),{className:h});a&&c.state.focused&&c.display.input.focus();var k=function(){c.operation(function(){i.clear(),j&&j.clear()})};return e?(setTimeout(k,800),void 0):k
-}}function g(a){a.operation(function(){f&&(f(),f=null),a.somethingSelected()||(f=e(a,!1))})}var a=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),b=CodeMirror.Pos,c={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},f=null;CodeMirror.defineOption("matchBrackets",!1,function(a,b,c){c&&c!=CodeMirror.Init&&a.off("cursorActivity",g),b&&(a.state.matchBrackets="object"==typeof b?b:{},a.on("cursorActivity",g))}),CodeMirror.defineExtension("matchBrackets",function(){e(this,!0)}),CodeMirror.defineExtension("findMatchingBracket",function(a,b){return d(this,a,b)})}(),CodeMirror.runMode=function(a,b,c,d){var e=CodeMirror.getMode(CodeMirror.defaults,b),f=/MSIE \d/.test(navigator.userAgent),g=f&&(null==document.documentMode||document.documentMode<9);if(1==c.nodeType){var h=d&&d.tabSize||CodeMirror.defaults.tabSize,i=c,j=0;i.innerHTML="",c=function(a,b){if("\n"==a)return i.appendChild(document.createTextNode(g?"\r":a)),j=0,void 0;for(var c="",d=0;;){var e=a.indexOf("	",d);if(-1==e){c+=a.slice(d),j+=a.length-d;break}j+=e-d,c+=a.slice(d,e);var f=h-j%h;j+=f;for(var k=0;f>k;++k)c+=" ";d=e+1}if(b){var l=i.appendChild(document.createElement("span"));l.className="cm-"+b.replace(/ +/g," cm-"),l.appendChild(document.createTextNode(c))}else i.appendChild(document.createTextNode(c))}}for(var k=CodeMirror.splitLines(a),l=d&&d.state||CodeMirror.startState(e),m=0,n=k.length;n>m;++m){m&&c("\n");for(var o=new CodeMirror.StringStream(k[m]);!o.eol();){var p=e.token(o,l);c(o.current(),p,m,o.start,l),o.start=o.pos}}};
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/data/codemirror.css
+++ /dev/null
@@ -1,264 +0,0 @@
-/* BASICS */
-
-.CodeMirror {
-  /* Set height, width, borders, and global font properties here */
-  font-family: monospace;
-  height: 300px;
-}
-.CodeMirror-scroll {
-  /* Set scrolling behaviour here */
-  overflow: auto;
-}
-
-/* PADDING */
-
-.CodeMirror-lines {
-  padding: 4px 0; /* Vertical padding around content */
-}
-.CodeMirror pre {
-  padding: 0 4px; /* Horizontal padding of content */
-}
-
-.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-  background-color: white; /* The little square between H and V scrollbars */
-}
-
-/* GUTTER */
-
-.CodeMirror-gutters {
-  border-right: 1px solid #ddd;
-  background-color: #f7f7f7;
-  white-space: nowrap;
-}
-.CodeMirror-linenumbers {}
-.CodeMirror-linenumber {
-  padding: 0 3px 0 5px;
-  min-width: 20px;
-  text-align: right;
-  color: #999;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-}
-
-/* CURSOR */
-
-.CodeMirror div.CodeMirror-cursor {
-  border-left: 1px solid black;
-  z-index: 3;
-}
-/* Shown when moving in bi-directional text */
-.CodeMirror div.CodeMirror-secondarycursor {
-  border-left: 1px solid silver;
-}
-.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
-  width: auto;
-  border: 0;
-  background: #7e7;
-  z-index: 1;
-}
-/* Can style cursor different in overwrite (non-insert) mode */
-.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
-
-.cm-tab { display: inline-block; }
-
-.CodeMirror-ruler {
-  border-left: 1px solid #ccc;
-  position: absolute;
-}
-
-/* DEFAULT THEME */
-
-.cm-s-default .cm-keyword {color: #708;}
-.cm-s-default .cm-atom {color: #219;}
-.cm-s-default .cm-number {color: #164;}
-.cm-s-default .cm-def {color: #00f;}
-.cm-s-default .cm-variable {color: black;}
-.cm-s-default .cm-variable-2 {color: #05a;}
-.cm-s-default .cm-variable-3 {color: #085;}
-.cm-s-default .cm-property {color: black;}
-.cm-s-default .cm-operator {color: black;}
-.cm-s-default .cm-comment {color: #a50;}
-.cm-s-default .cm-string {color: #a11;}
-.cm-s-default .cm-string-2 {color: #f50;}
-.cm-s-default .cm-meta {color: #555;}
-.cm-s-default .cm-qualifier {color: #555;}
-.cm-s-default .cm-builtin {color: #30a;}
-.cm-s-default .cm-bracket {color: #997;}
-.cm-s-default .cm-tag {color: #170;}
-.cm-s-default .cm-attribute {color: #00c;}
-.cm-s-default .cm-header {color: blue;}
-.cm-s-default .cm-quote {color: #090;}
-.cm-s-default .cm-hr {color: #999;}
-.cm-s-default .cm-link {color: #00c;}
-
-.cm-negative {color: #d44;}
-.cm-positive {color: #292;}
-.cm-header, .cm-strong {font-weight: bold;}
-.cm-em {font-style: italic;}
-.cm-link {text-decoration: underline;}
-
-.cm-s-default .cm-error {color: #f00;}
-.cm-invalidchar {color: #f00;}
-
-div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
-div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
-.CodeMirror-activeline-background {background: #e8f2ff;}
-
-/* STOP */
-
-/* The rest of this file contains styles related to the mechanics of
-   the editor. You probably shouldn't touch them. */
-
-.CodeMirror {
-  line-height: 1;
-  position: relative;
-  overflow: hidden;
-  background: white;
-  color: black;
-}
-
-.CodeMirror-scroll {
-  /* 30px is the magic margin used to hide the element's real scrollbars */
-  /* See overflow: hidden in .CodeMirror */
-  margin-bottom: -30px; margin-right: -30px;
-  padding-bottom: 30px;
-  height: 100%;
-  outline: none; /* Prevent dragging from highlighting the element */
-  position: relative;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-}
-.CodeMirror-sizer {
-  position: relative;
-  border-right: 30px solid transparent;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-}
-
-/* The fake, visible scrollbars. Used to force redraw during scrolling
-   before actuall scrolling happens, thus preventing shaking and
-   flickering artifacts. */
-.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-  position: absolute;
-  z-index: 6;
-  display: none;
-}
-.CodeMirror-vscrollbar {
-  right: 0; top: 0;
-  overflow-x: hidden;
-  overflow-y: scroll;
-}
-.CodeMirror-hscrollbar {
-  bottom: 0; left: 0;
-  overflow-y: hidden;
-  overflow-x: scroll;
-}
-.CodeMirror-scrollbar-filler {
-  right: 0; bottom: 0;
-}
-.CodeMirror-gutter-filler {
-  left: 0; bottom: 0;
-}
-
-.CodeMirror-gutters {
-  position: absolute; left: 0; top: 0;
-  padding-bottom: 30px;
-  z-index: 3;
-}
-.CodeMirror-gutter {
-  white-space: normal;
-  height: 100%;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-  padding-bottom: 30px;
-  margin-bottom: -32px;
-  display: inline-block;
-  /* Hack to make IE7 behave */
-  *zoom:1;
-  *display:inline;
-}
-.CodeMirror-gutter-elt {
-  position: absolute;
-  cursor: default;
-  z-index: 4;
-}
-
-.CodeMirror-lines {
-  cursor: text;
-}
-.CodeMirror pre {
-  /* Reset some styles that the rest of the page might have set */
-  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
-  border-width: 0;
-  background: transparent;
-  font-family: inherit;
-  font-size: inherit;
-  margin: 0;
-  white-space: pre;
-  word-wrap: normal;
-  line-height: inherit;
-  color: inherit;
-  z-index: 2;
-  position: relative;
-  overflow: visible;
-}
-.CodeMirror-wrap pre {
-  word-wrap: break-word;
-  white-space: pre-wrap;
-  word-break: normal;
-}
-
-.CodeMirror-linebackground {
-  position: absolute;
-  left: 0; right: 0; top: 0; bottom: 0;
-  z-index: 0;
-}
-
-.CodeMirror-linewidget {
-  position: relative;
-  z-index: 2;
-  overflow: auto;
-}
-
-.CodeMirror-widget {}
-
-.CodeMirror-wrap .CodeMirror-scroll {
-  overflow-x: hidden;
-}
-
-.CodeMirror-measure {
-  position: absolute;
-  width: 100%;
-  height: 0;
-  overflow: hidden;
-  visibility: hidden;
-}
-.CodeMirror-measure pre { position: static; }
-
-.CodeMirror div.CodeMirror-cursor {
-  position: absolute;
-  visibility: hidden;
-  border-right: none;
-  width: 0;
-}
-.CodeMirror-focused div.CodeMirror-cursor {
-  visibility: visible;
-}
-
-.CodeMirror-selected { background: #d9d9d9; }
-.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
-
-.cm-searching {
-  background: #ffa;
-  background: rgba(255, 255, 0, .4);
-}
-
-/* IE7 hack to prevent it from returning funny offsetTops on the spans */
-.CodeMirror span { *vertical-align: text-bottom; }
-
-@media print {
-  /* Hide the cursor when printing */
-  .CodeMirror div.CodeMirror-cursor {
-    visibility: hidden;
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/data/index.html
+++ /dev/null
@@ -1,147 +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>
-      <link rel="stylesheet" href="./codemirror.css">
-      <link rel="stylesheet" href="./main.css">
-      <script src="./codemirror-compressed.js"></script>
-      <views>
-          <section class="task cm-s-default">
-            <pre class="request "></pre>
-            <pre class="response"><span class="one"></span><span class="two"></span><span class="three"></span></pre>
-          </section>
-       </views>
-  </head>
-  <body>
-      <pre class="input"></pre>
-  </body>
-  <script>
-      function debounce(fn, ms) {
-        var id;
-        return function(...args) {
-          clearTimeout(id);
-          id = setTimeout(fn, ms, ...args);
-        };
-      }
-
-      function Try(fn) {
-        return function(...args) {
-          try { return fn(...args); }
-          catch (error) { return null; }
-        };
-      }
-
-      var parse = Try(JSON.parse);
-
-      var CommandHistory = {
-        init: function() {
-          this._state = {};
-          this._state.els = document.querySelectorAll("body > section.task > .request");
-          this._state.idx = this._state.els.length;
-        },
-        get prev() {
-          if (!!this._state.els && this._state.idx > 0) {
-            this._state.idx--;
-            return this._state.els[this._state.idx].textContent;
-          }
-
-          return "";
-        },
-        get next() {
-          if (!!this._state.els && this._state.idx < this._state.els.length-1) {
-            this._state.idx++;
-            return this._state.els[this._state.idx].textContent;
-          }
-
-          return "";
-        }
-      }
-
-      function cmdHistory(fn, editor) {
-        editor.setValue(fn());
-        document.querySelector(".input").scrollIntoView();
-      }
-
-      var cmdHistoryNext = cmdHistory.bind(null, () => CommandHistory.next);
-      var cmdHistoryBack = cmdHistory.bind(null, () => CommandHistory.prev);
-
-      function send(editor) {
-          var input = editor.getWrapperElement().parentNode;
-          var code = editor.getValue().trim();
-          var packet = parse(code);
-          if (packet) {
-            var task = document.querySelector("views .task").cloneNode(true);
-            var request = task.querySelector(".request");
-            var response = task.querySelector(".response");
-
-            input.parentNode.insertBefore(task, input);
-
-            CodeMirror.runMode(JSON.stringify(packet, 2, 2),
-                               "application/json",
-                               request);
-            response.classList.add("pending");
-
-            editor.setValue("");
-
-            document.querySelector(".input").scrollIntoView();
-
-            port.postMessage(packet);
-          }
-      }
-
-      var editor = CodeMirror(document.querySelector(".input"), {
-        autofocus: true,
-        mode: "application/json",
-        matchBrackets: true,
-        value: '{"to": "root", "type": "requestTypes"}',
-        extraKeys: {"Cmd-Enter": send,
-                    "Ctrl-Enter": send,
-                    "Cmd-Down": cmdHistoryNext,
-                    "Ctrl-Down": cmdHistoryNext,
-                    "Cmd-Up": cmdHistoryBack,
-                    "Ctrl-Up": cmdHistoryBack}
-      });
-      editor.on("change", debounce(function(editor) {
-          var input = editor.getWrapperElement().parentNode;
-          if (parse(editor.getValue().trim())) {
-            input.classList.remove("invalid");
-          } else {
-            input.classList.add("invalid");
-          }
-      }, 800));
-  </script>
-  <script>
-    window.addEventListener("message", event => {
-      window.port = event.ports[0];
-      port.onmessage = onMessage;
-    });
-
-    var onMessage = (event) => {
-      var packet = event.data;
-      var code = JSON.stringify(packet, 2, 2);
-
-      var input = document.querySelector(".input");
-      var response = document.querySelector(".task .response.pending");
-
-      if (!response) {
-        message = document.querySelector("views .task").cloneNode(true);
-        response = message.querySelector(".response");
-        response.classList.add("message");
-
-        input.parentNode.insertBefore(message, input);
-      }
-
-      if (packet.error) {
-        response.classList.add("error");
-      }
-
-      CodeMirror.runMode(code, "application/json", response);
-      response.classList.remove("pending");
-
-      document.querySelector(".input").scrollIntoView();
-
-      CommandHistory.init();
-    };
-  </script>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/data/main.css
+++ /dev/null
@@ -1,117 +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/. */
-
-body
-{
-  position: absolute;
-  width: 100%;
-  margin: 0;
-  padding: 0;
-  background: white;
-}
-
-
-pre
-{
-  margin: 0;
-}
-
-section
-{
-  border-top: 1px solid rgba(150, 150, 150, 0.5);
-}
-
-.CodeMirror {
-  height: auto;
-}
-.CodeMirror-scroll {
-  overflow-y: hidden;
-  overflow-x: auto;
-}
-
-.request,
-.response,
-.input
-{
-  border-left: 5px solid;
-  padding-left: 10px;
-}
-
-.request:not(:empty),
-.response.pending
-{
-  padding: 5px;
-}
-
-.input
-{
-  padding-left: 6px;
-  border-color: lightgreen;
-}
-.input.invalid
-{
-  border-color: orange;
-}
-
-.request
-{
-  border-color: lightgrey;
-}
-
-.response
-{
-  border-color: grey;
-}
-.response.error
-{
-  border-color: red;
-}
-
-.response.message
-{
-    border-color: lightblue;
-}
-
-.response .one,
-.response .two,
-.response .three
-{
-  width: 0;
-  height: auto;
-}
-
-
-
-.response.pending .one,
-.response.pending .two,
-.response.pending .three
-{
-  width: 10px;
-  height: 10px;
-  background-color: rgba(150, 150, 150, 0.5);
-
-  border-radius: 100%;
-  display: inline-block;
-  animation: bouncedelay 1.4s infinite ease-in-out;
-  /* Prevent first frame from flickering when animation starts */
-  animation-fill-mode: both;
-}
-
-.response.pending .one
-{
-  animation-delay: -0.32s;
-}
-
-.response.pending .two
-{
-  animation-delay: -0.16s;
-}
-
-@keyframes bouncedelay {
-  0%, 80%, 100% {
-    transform: scale(0.0);
-  } 40% {
-    transform: scale(1.0);
-  }
-}
deleted file mode 100644
index 983516f981f2e0c2110e27d0c42961a5a6bb3d1d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/index.js
+++ /dev/null
@@ -1,37 +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 { Panel } = require("dev/panel");
-const { Tool } = require("dev/toolbox");
-const { Class } = require("sdk/core/heritage");
-
-
-const REPLPanel = Class({
-  extends: Panel,
-  label: "Actor REPL",
-  tooltip: "Firefox debugging protocol REPL",
-  icon: "./robot.png",
-  url: "./index.html",
-  setup: function({debuggee}) {
-    this.debuggee = debuggee;
-  },
-  dispose: function() {
-    this.debuggee = null;
-  },
-  onReady: function() {
-    console.log("repl panel document is interactive");
-    this.debuggee.start();
-    this.postMessage("RDP", [this.debuggee]);
-  },
-  onLoad: function() {
-    console.log("repl panel document is fully loaded");
-  }
-});
-exports.REPLPanel = REPLPanel;
-
-
-const replTool = new Tool({
-  panels: { repl: REPLPanel }
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "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"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/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);
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/data/client.js
+++ /dev/null
@@ -1,816 +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/. */
-(function(exports) {
-"use strict";
-
-
-var describe = Object.getOwnPropertyDescriptor;
-var Class = fields => {
-  var constructor = fields.constructor || function() {};
-  var ancestor = fields.extends || Object;
-
-
-
-  var descriptor = {};
-  for (var key of Object.keys(fields))
-    descriptor[key] = describe(fields, key);
-
-  var prototype = Object.create(ancestor.prototype, descriptor);
-
-  constructor.prototype = prototype;
-  prototype.constructor = constructor;
-
-  return constructor;
-};
-
-
-var bus = function Bus() {
-  var parser = new DOMParser();
-  return parser.parseFromString("<EventTarget/>", "application/xml").documentElement;
-}();
-
-var GUID = new WeakMap();
-GUID.id = 0;
-var guid = x => GUID.get(x);
-var setGUID = x => {
-  GUID.set(x, ++ GUID.id);
-};
-
-var Emitter = Class({
-  extends: EventTarget,
-  constructor: function() {
-   this.setupEmitter();
-  },
-  setupEmitter: function() {
-    setGUID(this);
-  },
-  addEventListener: function(type, listener, capture) {
-    bus.addEventListener(type + "@" + guid(this),
-                         listener, capture);
-  },
-  removeEventListener: function(type, listener, capture) {
-    bus.removeEventListener(type + "@" + guid(this),
-                            listener, capture);
-  }
-});
-
-function dispatch(target, type, data) {
-  var event = new MessageEvent(type + "@" + guid(target), {
-    bubbles: true,
-    cancelable: false,
-    data: data
-  });
-  bus.dispatchEvent(event);
-}
-
-var supervisedWorkers = new WeakMap();
-var supervised = supervisor => {
-  if (!supervisedWorkers.has(supervisor)) {
-    supervisedWorkers.set(supervisor, new Map());
-    supervisor.connection.addActorPool(supervisor);
-  }
-  return supervisedWorkers.get(supervisor);
-};
-
-var Supervisor = Class({
-  extends: Emitter,
-  constructor: function(...params) {
-    this.setupEmitter(...params);
-    this.setupSupervisor(...params);
-  },
-  Supervisor: function(connection) {
-    this.connection = connection;
-  },
-  /**
-   * Return the parent pool for this client.
-   */
-  supervisor: function() {
-    return this.connection.poolFor(this.actorID);
-  },
-  /**
-   * Override this if you want actors returned by this actor
-   * to belong to a different actor by default.
-   */
-  marshallPool: function() { return this; },
-    /**
-   * Add an actor as a child of this pool.
-   */
-  supervise: function(actor) {
-    if (!actor.actorID)
-      actor.actorID = this.connection.allocID(actor.actorPrefix ||
-                                              actor.typeName);
-
-    supervised(this).set(actor.actorID, actor);
-    return actor;
-  },
-  /**
-   * Remove an actor as a child of this pool.
-   */
-  abandon: function(actor) {
-    supervised(this).delete(actor.actorID);
-  },
-  // true if the given actor ID exists in the pool.
-  has: function(actorID) {
-    return supervised(this).has(actorID);
-  },
-  // Same as actor, should update debugger connection to use 'actor'
-  // and then remove this.
-  get: function(actorID) {
-    return supervised(this).get(actorID);
-  },
-  actor: function(actorID) {
-    return supervised(this).get(actorID);
-  },
-  isEmpty: function() {
-    return supervised(this).size === 0;
-  },
-  /**
-   * For getting along with the debugger server pools, should be removable
-   * eventually.
-   */
-  cleanup: function() {
-    this.destroy();
-  },
-  destroy: function() {
-    var supervisor = this.supervisor();
-    if (supervisor)
-      supervisor.abandon(this);
-
-    for (var actor of supervised(this).values()) {
-      if (actor !== this) {
-        var destroy = actor.destroy;
-        // Disconnect destroy while we're destroying in case of (misbehaving)
-        // circular ownership.
-        if (destroy) {
-          actor.destroy = null;
-          destroy.call(actor);
-          actor.destroy = destroy;
-        }
-      }
-    }
-
-    this.connection.removeActorPool(this);
-    supervised(this).clear();
-  }
-
-});
-
-
-
-
-var mailbox = new WeakMap();
-var clientRequests = new WeakMap();
-
-var inbox = client => mailbox.get(client).inbox;
-var outbox = client => mailbox.get(client).outbox;
-var requests = client => clientRequests.get(client);
-
-
-var Receiver = Class({
-  receive: function(packet) {
-    if (packet.error)
-      this.reject(packet.error);
-    else
-      this.resolve(this.read(packet));
-  }
-});
-
-var Connection = Class({
-  constructor: function() {
-    // Queue of the outgoing messages.
-    this.outbox = [];
-    // Map of pending requests.
-    this.pending = new Map();
-    this.pools = new Set();
-  },
-  isConnected: function() {
-    return !!this.port
-  },
-  connect: function(port) {
-    this.port = port;
-    port.addEventListener("message", this);
-    port.start();
-
-    this.flush();
-  },
-  addPool: function(pool) {
-    this.pools.add(pool);
-  },
-  removePool: function(pool) {
-    this.pools.delete(pool);
-  },
-  poolFor: function(id) {
-    for (let pool of this.pools.values()) {
-      if (pool.has(id))
-        return pool;
-    }
-  },
-  get: function(id) {
-    var pool = this.poolFor(id);
-    return pool && pool.get(id);
-  },
-  disconnect: function() {
-    this.port.stop();
-    this.port = null;
-    for (var request of this.pending.values()) {
-      request.catch(new Error("Connection closed"));
-    }
-    this.pending.clear();
-
-    var requests = this.outbox.splice(0);
-    for (var request of request) {
-      requests.catch(new Error("Connection closed"));
-    }
-  },
-  handleEvent: function(event) {
-    this.receive(event.data);
-  },
-  flush: function() {
-    if (this.isConnected()) {
-      for (var request of this.outbox) {
-        if (!this.pending.has(request.to)) {
-          this.outbox.splice(this.outbox.indexOf(request), 1);
-          this.pending.set(request.to, request);
-          this.send(request.packet);
-        }
-      }
-    }
-  },
-  send: function(packet) {
-    this.port.postMessage(packet);
-  },
-  request: function(packet) {
-    return new Promise(function(resolve, reject) {
-      this.outbox.push({
-        to: packet.to,
-        packet: packet,
-        receive: resolve,
-        catch: reject
-      });
-      this.flush();
-    });
-  },
-  receive: function(packet) {
-    var { from, type, why } = packet;
-    var receiver = this.pending.get(from);
-    if (!receiver) {
-      console.warn("Unable to handle received packet", data);
-    } else {
-      this.pending.delete(from);
-      if (packet.error)
-        receiver.catch(packet.error);
-      else
-        receiver.receive(packet);
-    }
-    this.flush();
-  },
-});
-
-/**
- * Base class for client-side actor fronts.
- */
-var Client = Class({
-  extends: Supervisor,
-  constructor: function(from=null, detail=null, connection=null) {
-    this.Client(from, detail, connection);
-  },
-  Client: function(form, detail, connection) {
-    this.Supervisor(connection);
-
-    if (form) {
-      this.actorID = form.actor;
-      this.from(form, detail);
-    }
-  },
-  connect: function(port) {
-    this.connection = new Connection(port);
-  },
-  actorID: null,
-  actor: function() {
-    return this.actorID;
-  },
-  /**
-   * Update the actor from its representation.
-   * Subclasses should override this.
-   */
-  form: function(form) {
-  },
-  /**
-   * Method is invokeid when packet received constitutes an
-   * event. By default such packets are demarshalled and
-   * dispatched on the client instance.
-   */
-  dispatch: function(packet) {
-  },
-  /**
-   * Method is invoked when packet is returned in response to
-   * a request. By default respond delivers response to a first
-   * request in a queue.
-   */
-  read: function(input) {
-    throw new TypeError("Subclass must implement read method");
-  },
-  write: function(input) {
-    throw new TypeError("Subclass must implement write method");
-  },
-  respond: function(packet) {
-    var [resolve, reject] = requests(this).shift();
-    if (packet.error)
-      reject(packet.error);
-    else
-      resolve(this.read(packet));
-  },
-  receive: function(packet) {
-    if (this.isEventPacket(packet)) {
-      this.dispatch(packet);
-    }
-    else if (requests(this).length) {
-      this.respond(packet);
-    }
-    else {
-      this.catch(packet);
-    }
-  },
-  send: function(packet) {
-    Promise.cast(packet.to || this.actor()).then(id => {
-      packet.to = id;
-      this.connection.send(packet);
-    })
-  },
-  request: function(packet) {
-    return this.connection.request(packet);
-  }
-});
-
-
-var Destructor = method => {
-  return function(...args) {
-    return method.apply(this, args).then(result => {
-      this.destroy();
-      return result;
-    });
-  };
-};
-
-var Profiled = (method, id) => {
-  return function(...args) {
-    var start = new Date();
-    return method.apply(this, args).then(result => {
-      var end = new Date();
-      this.telemetry.add(id, +end - start);
-      return result;
-    });
-  };
-};
-
-var Method = (request, response) => {
-  return response ? new BidirectionalMethod(request, response) :
-         new UnidirecationalMethod(request);
-};
-
-var UnidirecationalMethod = request => {
-  return function(...args) {
-    var packet = request.write(args, this);
-    this.connection.send(packet);
-    return Promise.resolve(void(0));
-  };
-};
-
-var BidirectionalMethod = (request, response) => {
-  return function(...args) {
-    var packet = request.write(args, this);
-    return this.connection.request(packet).then(packet => {
-      return response.read(packet, this);
-    });
-  };
-};
-
-
-Client.from = ({category, typeName, methods, events}) => {
-  var proto = {
-    constructor: function(...args) {
-      this.Client(...args);
-    },
-    extends: Client,
-    name: typeName
-  };
-
-  methods.forEach(({telemetry, request, response, name, oneway, release}) => {
-    var [reader, writer] = oneway ? [, new Request(request)] :
-                           [new Request(request), new Response(response)];
-    var method = new Method(request, response);
-    var profiler = telemetry ? new Profiler(method) : method;
-    var destructor = release ? new Destructor(profiler) : profiler;
-    proto[name] = destructor;
-  });
-
-  return Class(proto);
-};
-
-
-var defineType = (client, descriptor) => {
-  var type = void(0)
-  if (typeof(descriptor) === "string") {
-    if (name.indexOf(":") > 0)
-      type = makeCompoundType(descriptor);
-    else if (name.indexOf("#") > 0)
-      type = new ActorDetail(descriptor);
-    else if (client.specification[descriptor])
-      type = makeCategoryType(client.specification[descriptor]);
-  } else {
-    type = makeCategoryType(descriptor);
-  }
-
-  if (type)
-    client.types.set(type.name, type);
-  else
-    throw TypeError("Invalid type: " + descriptor);
-};
-
-
-var makeCompoundType = name => {
-  var index = name.indexOf(":");
-  var [baseType, subType] = [name.slice(0, index), parts.slice(1)];
-  return baseType === "array" ? new ArrayOf(subType) :
-         baseType === "nullable" ? new Maybe(subType) :
-         null;
-};
-
-var makeCategoryType = (descriptor) => {
-  var { category } = descriptor;
-  return category === "dict" ? new Dictionary(descriptor) :
-         category === "actor" ? new Actor(descriptor) :
-         null;
-};
-
-
-var typeFor = (client, type="primitive") => {
-  if (!client.types.has(type))
-    defineType(client, type);
-
-  return client.types.get(type);
-};
-
-
-var Client = Class({
-  constructor: function() {
-  },
-  setupTypes: function(specification) {
-    this.specification = specification;
-    this.types = new Map();
-  },
-  read: function(input, type) {
-    return typeFor(this, type).read(input, this);
-  },
-  write: function(input, type) {
-    return typeFor(this, type).write(input, this);
-  }
-});
-
-
-var Type = Class({
-  get name() {
-    return this.category ? this.category + ":" + this.type :
-           this.type;
-  },
-  read: function(input, client) {
-    throw new TypeError("`Type` subclass must implement `read`");
-  },
-  write: function(input, client) {
-    throw new TypeError("`Type` subclass must implement `write`");
-  }
-});
-
-
-var Primitve = Class({
-  extends: Type,
-  constuctor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input;
-  },
-  write: function(input, client) {
-    return input;
-  }
-});
-
-var Maybe = Class({
-  extends: Type,
-  category: "nullable",
-  constructor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input === null ? null :
-           input === void(0) ? void(0) :
-           client.read(input, this.type);
-  },
-  write: function(input, client) {
-    return input === null ? null :
-           input === void(0) ? void(0) :
-           client.write(input, this.type);
-  }
-});
-
-var ArrayOf = Class({
-  extends: Type,
-  category: "array",
-  constructor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input.map($ => client.read($, this.type));
-  },
-  write: function(input, client) {
-    return input.map($ => client.write($, this.type));
-  }
-});
-
-var Dictionary = Class({
-  exteds: Type,
-  category: "dict",
-  get name() { return this.type; },
-  constructor: function({typeName, specializations}) {
-    this.type = typeName;
-    this.types = specifications;
-  },
-  read: function(input, client) {
-    var output = {};
-    for (var key in input) {
-      output[key] = client.read(input[key], this.types[key]);
-    }
-    return output;
-  },
-  write: function(input, client) {
-    var output = {};
-    for (var key in input) {
-      output[key] = client.write(value, this.types[key]);
-    }
-    return output;
-  }
-});
-
-var Actor = Class({
-  exteds: Type,
-  category: "actor",
-  get name() { return this.type; },
-  constructor: function({typeName}) {
-    this.type = typeName;
-  },
-  read: function(input, client, detail) {
-    var id = value.actor;
-    var actor = void(0);
-    if (client.connection.has(id)) {
-      return client.connection.get(id).form(input, detail, client);
-    } else {
-      actor = Client.from(detail, client);
-      actor.actorID = id;
-      client.supervise(actor);
-    }
-  },
-  write: function(input, client, detail) {
-    if (input instanceof Actor) {
-      if (!input.actorID) {
-        client.supervise(input);
-      }
-      return input.from(detail);
-    }
-    return input.actorID;
-  }
-});
-
-var Root = Client.from({
-  "category": "actor",
-  "typeName": "root",
-  "methods": [
-    {"name": "listTabs",
-     "request": {},
-     "response": {
-     }
-    },
-    {"name": "listAddons"
-    },
-    {"name": "echo",
-
-    },
-    {"name": "protocolDescription",
-
-    }
-  ]
-});
-
-
-var ActorDetail = Class({
-  extends: Actor,
-  constructor: function(name, actor, detail) {
-    this.detail = detail;
-    this.actor = actor;
-  },
-  read: function(input, client) {
-    this.actor.read(input, client, this.detail);
-  },
-  write: function(input, client) {
-    this.actor.write(input, client, this.detail);
-  }
-});
-
-var registeredLifetimes = new Map();
-var LifeTime = Class({
-  extends: Type,
-  category: "lifetime",
-  constructor: function(lifetime, type) {
-    this.name = lifetime + ":" + type.name;
-    this.field = registeredLifetimes.get(lifetime);
-  },
-  read: function(input, client) {
-    return this.type.read(input, client[this.field]);
-  },
-  write: function(input, client) {
-    return this.type.write(input, client[this.field]);
-  }
-});
-
-var primitive = new Primitve("primitive");
-var string = new Primitve("string");
-var number = new Primitve("number");
-var boolean = new Primitve("boolean");
-var json = new Primitve("json");
-var array = new Primitve("array");
-
-
-var TypedValue = Class({
-  extends: Type,
-  constructor: function(name, type) {
-    this.TypedValue(name, type);
-  },
-  TypedValue: function(name, type) {
-    this.name = name;
-    this.type = type;
-  },
-  read: function(input, client) {
-    return this.client.read(input, this.type);
-  },
-  write: function(input, client) {
-    return this.client.write(input, this.type);
-  }
-});
-
-var Return = Class({
-  extends: TypedValue,
-  constructor: function(type) {
-    this.type = type
-  }
-});
-
-var Argument = Class({
-  extends: TypedValue,
-  constructor: function(...args) {
-    this.Argument(...args);
-  },
-  Argument: function(index, type) {
-    this.index = index;
-    this.TypedValue("argument[" + index + "]", type);
-  },
-  read: function(input, client, target) {
-    return target[this.index] = client.read(input, this.type);
-  }
-});
-
-var Option = Class({
-  extends: Argument,
-  constructor: function(...args) {
-    return this.Argument(...args);
-  },
-  read: function(input, client, target, name) {
-    var param = target[this.index] || (target[this.index] = {});
-    param[name] = input === void(0) ? input : client.read(input, this.type);
-  },
-  write: function(input, client, name) {
-    var value = input && input[name];
-    return value === void(0) ? value : client.write(value, this.type);
-  }
-});
-
-var Request = Class({
-  extends: Type,
-  constructor: function(template={}) {
-    this.type = template.type;
-    this.template = template;
-    this.params = findPlaceholders(template, Argument);
-  },
-  read: function(packet, client) {
-    var args = [];
-    for (var param of this.params) {
-      var {placeholder, path} = param;
-      var name = path[path.length - 1];
-      placeholder.read(getPath(packet, path), client, args, name);
-      // TODO:
-      // args[placeholder.index] = placeholder.read(query(packet, path), client);
-    }
-    return args;
-  },
-  write: function(input, client) {
-    return JSON.parse(JSON.stringify(this.template, (key, value) => {
-      return value instanceof Argument ? value.write(input[value.index],
-                                                     client, key) :
-             value;
-    }));
-  }
-});
-
-var Response = Class({
-  extends: Type,
-  constructor: function(template={}) {
-    this.template = template;
-    var [x] = findPlaceholders(template, Return);
-    var {placeholder, path} = x;
-    this.return = placeholder;
-    this.path = path;
-  },
-  read: function(packet, client) {
-    var value = query(packet, this.path);
-    return this.return.read(value, client);
-  },
-  write: function(input, client) {
-    return JSON.parse(JSON.stringify(this.template, (key, value) => {
-      return value instanceof Return ? value.write(input) :
-             input
-    }));
-  }
-});
-
-// Returns array of values for the given object.
-var values = object => Object.keys(object).map(key => object[key]);
-// Returns [key, value] pairs for the given object.
-var pairs = object => Object.keys(object).map(key => [key, object[key]]);
-// Queries an object for the field nested with in it.
-var query = (object, path) => path.reduce((object, entry) => object && object[entry],
-                                          object);
-
-
-var Root = Client.from({
-  "category": "actor",
-  "typeName": "root",
-  "methods": [
-    {
-      "name": "echo",
-      "request": {
-        "string": { "_arg": 0, "type": "string" }
-      },
-      "response": {
-        "string": { "_retval": "string" }
-      }
-    },
-    {
-      "name": "listTabs",
-      "request": {},
-      "response": { "_retval": "tablist" }
-    },
-    {
-      "name": "actorDescriptions",
-      "request": {},
-      "response": { "_retval": "json" }
-    }
-  ],
-  "events": {
-    "tabListChanged": {}
-  }
-});
-
-var Tab = Client.from({
-  "category": "dict",
-  "typeName": "tab",
-  "specifications": {
-    "title": "string",
-    "url": "string",
-    "outerWindowID": "number",
-    "console": "console",
-    "inspectorActor": "inspector",
-    "callWatcherActor": "call-watcher",
-    "canvasActor": "canvas",
-    "webglActor": "webgl",
-    "webaudioActor": "webaudio",
-    "styleSheetsActor": "stylesheets",
-    "styleEditorActor": "styleeditor",
-    "storageActor": "storage",
-    "gcliActor": "gcli",
-    "memoryActor": "memory",
-    "eventLoopLag": "eventLoopLag",
-
-    "trace": "trace", // missing
-  }
-});
-
-var tablist = Client.from({
-  "category": "dict",
-  "typeName": "tablist",
-  "specializations": {
-    "selected": "number",
-    "tabs": "array:tab"
-  }
-});
-
-})(this);
-
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/data/index.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>
-      <script src="resource://sdk/dev/volcan.js"></script>
-      <script src="./task.js"></script>
-  </head>
-  <body>
-  </body>
-  <script>
-    const wait = (target, type, capture) => new Promise((resolve, reject) => {
-      const listener = event => {
-        target.removeEventListener(type, listener, capture);
-        resolve(event);
-      };
-      target.addEventListener(type, listener, capture);
-    });
-
-    const display = message =>
-      document.body.innerHTML += message + "<br/>";
-
-    Task.spawn(function*() {
-      var event = yield wait(window, "message");
-      var port = event.ports[0];
-
-      display("Port received");
-      var root = yield volcan.connect(port);
-
-      display("Connected to a debugger");
-
-      var message = yield root.echo("hello")
-
-      display("Received echo for: " + message);
-
-      var list = yield root.listTabs();
-
-      display("You have " + list.tabs.length + " open tabs");
-
-      var activeTab = list.tabs[list.selected];
-
-      display("Your active tab url is: " + activeTab.url);
-
-      var sheets = yield activeTab.styleSheetsActor.getStyleSheets();
-
-      display("Page in active tab has " + sheets.length + " stylesheets");
-
-    });
-  </script>
-</html>
deleted file mode 100644
index 6a364a30a852c1cd9f54feba54220ef5605c1bb3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/data/task.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-(function(exports) {
-"use strict";
-
-const spawn = (task, ...args) => {
-  return new Promise((resolve, reject) => {
-    try {
-      const routine = task(...args);
-      const raise = error => routine.throw(error);
-      const step = data => {
-        const { done, value } = routine.next(data);
-        if (done)
-          resolve(value);
-        else
-          Promise.resolve(value).then(step, raise);
-      }
-      step();
-    } catch(error) {
-      reject(error);
-    }
-  });
-}
-exports.spawn = spawn;
-
-})(Task = {});
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/index.js
+++ /dev/null
@@ -1,33 +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 { Panel } = require("dev/panel");
-const { Tool } = require("dev/toolbox");
-const { Class } = require("sdk/core/heritage");
-
-
-const LadybugPanel = Class({
-  extends: Panel,
-  label: "Ladybug",
-  tooltip: "Debug client example",
-  icon: "./plugin.png",
-  url: "./index.html",
-  setup: function({debuggee}) {
-    this.debuggee = debuggee;
-  },
-  dispose: function() {
-    delete this.debuggee;
-  },
-  onReady: function() {
-    this.debuggee.start();
-    this.postMessage("RDP", [this.debuggee]);
-  },
-});
-exports.LadybugPanel = LadybugPanel;
-
-
-const ladybug = new Tool({
-  panels: { ladybug: LadybugPanel }
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "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"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/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);
deleted file mode 100644
index 4ba89a2c1ef900e9363746d45820f0b9e857e51f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/reading-data/data/sample.html
+++ /dev/null
@@ -1,7 +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><body>
-<h1>Hello World</h1>
-</body></html>
deleted file mode 100644
--- a/addon-sdk/source/examples/reading-data/lib/main.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var self = require("sdk/self");
-var { Panel } = require("sdk/panel");
-var { ToggleButton } = require("sdk/ui");
-
-function replaceMom(html) {
-  return html.replace("World", "Mom");
-}
-exports.replaceMom = replaceMom;
-
-exports.main = function(options, callbacks) {
-  console.log("My ID is " + self.id);
-
-  // Load the sample HTML into a string.
-  var helloHTML = self.data.load("sample.html");
-
-  // Let's now modify it...
-  helloHTML = replaceMom(helloHTML);
-
-  // ... and then create a panel that displays it.
-  var myPanel = Panel({
-    contentURL: "data:text/html," + helloHTML,
-    onHide: handleHide
-  });
-
-  // Create a widget that displays the image.  We'll attach the panel to it.
-  // When you click the widget, the panel will pop up.
-  var button = ToggleButton({
-    id: "test-widget",
-    label: "Mom",
-    icon: './mom.png',
-    onChange: handleChange
-  });
-
-  // If you run cfx with --static-args='{"quitWhenDone":true}' this program
-  // will automatically quit Firefox when it's done.
-  if (options.staticArgs.quitWhenDone)
-    callbacks.quit();
-}
-
-function handleChange(state) {
-  if (state.checked) {
-    myPanel.show({ position: button });
-  }
-}
-
-function handleHide() {
-  button.state('window', { checked: false });
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/reading-data/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "name": "reading-data",
-    "description": "A demonstration of reading bundled data.",
-    "keywords": [],
-    "author": "Brian Warner",
-    "contributors": [],
-    "license": "MPL-2.0",
-    "id": "reading-data-example@jetpack.mozillalabs.com"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/reading-data/tests/test-main.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var m = require("main");
-var self = require("sdk/self");
-
-exports.testReplace = function(test) {
-  var input = "Hello World";
-  var output = m.replaceMom(input);
-  test.assertEqual(output, "Hello Mom");
-  var callbacks = { quit: function() {} };
-
-  // Make sure it doesn't crash...
-  m.main({ staticArgs: {} }, callbacks);
-};
-
-exports.testID = function(test) {
-  // The ID is randomly generated during tests, so we cannot compare it against
-  // anything in particular.  Just assert that it is not empty.
-  test.assert(self.id.length > 0);
-  test.assertEqual(self.data.url("sample.html"),
-                   "resource://reading-data-example-at-jetpack-dot-mozillalabs-dot-com/reading-data/data/sample.html");
-};
deleted file mode 100644
index 72327f77b67a4ede4fa787f67c5a810c077195b7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/theme/data/index.html
+++ /dev/null
@@ -1,9 +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>
-  </head>
-  <body>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/theme/data/theme.css
+++ /dev/null
@@ -1,7 +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/. */
-
-#devtools-theme-box {
-  background-color: red !important;
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/theme/lib/main.js
+++ /dev/null
@@ -1,37 +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 { Tool } = require("dev/toolbox");
-const { Class } = require("sdk/core/heritage");
-const { onEnable, onDisable } = require("dev/theme/hooks");
-const { Theme, LightTheme } = require("dev/theme");
-
-/**
- * This object represents a new theme registered within the Toolbox.
- * You can activate it by clicking on "My Light Theme" theme option
- * in the Options panel.
- * Note that the new theme derives styles from built-in Light theme.
- */
-const MyTheme = Theme({
-  name: "mytheme",
-  label: "My Light Theme",
-  styles: [LightTheme, "./theme.css"],
-
-  onEnable: function(window, oldTheme) {
-    console.log("myTheme.onEnable; method override " +
-      window.location.href);
-  },
-  onDisable: function(window, newTheme) {
-    console.log("myTheme.onDisable; method override " +
-      window.location.href);
-  },
-});
-
-// Registration
-
-const mytheme = new Tool({
-  name: "My Tool",
-  themes: { mytheme: MyTheme }
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/theme/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "name": "theme",
-  "title": "theme",
-  "id": "theme@jetpack",
-  "description": "How to create new theme for devtools",
-  "author": "Jan Odvarko",
-  "license": "MPL-2.0",
-  "version": "0.1.0",
-  "main": "lib/main"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/theme/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);
deleted file mode 100644
index ae5084bc03888f4e21da00633b349507248780ac..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/toolbar-api/data/index.html
+++ /dev/null
@@ -1,21 +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>
-  <body>
-    <button id=post>post!</button>
-  </body>
-  <script>
-    window.addEventListener("message", event => {
-      console.log("Document message", event, event.data, event.source !== window && event.source === window.parent);
-    });
-    window.addEventListener("click", event => {
-      if (event.target.id === "post") {
-          console.log("click!")
-          window.parent.postMessage("ping!", "*");
-      }
-    });
-    console.log(window.parent === window)
-  </script>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/toolbar-api/lib/main.js
+++ /dev/null
@@ -1,48 +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 { Toolbar } = require("sdk/ui/toolbar");
-const { Frame } = require("sdk/ui/frame");
-const { ActionButton } = require("sdk/ui/button/action");
-
-var button = new ActionButton({
-  id: "button",
-  label: "send!",
-  icon: "./favicon.ico",
-  onClick: () => {
-    frame.postMessage({
-      hello: "content"
-    });
-  }
-});
-
-var frame = new Frame({
-    url: "./index.html",
-    onAttach: () => {
-      console.log("frame was attached");
-    },
-    onReady: () => {
-      console.log("frame document was loaded");
-    },
-    onLoad: () => {
-      console.log("frame load complete");
-    },
-    onMessage: (event) => {
-      console.log("got message from frame content", event);
-      if (event.data === "ping!")
-        event.source.postMessage("pong!", event.source.origin);
-    }
-});
-var toolbar = new Toolbar({
-  items: [frame],
-  title: "Addon Demo",
-  hidden: false,
-  onShow: () => {
-    console.log("toolbar was shown");
-  },
-  onHide: () => {
-    console.log("toolbar was hidden");
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/toolbar-api/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "toolbar-api",
-  "title": "Toolbar API",
-  "main": "./lib/main.js",
-  "description": "a toolbar api example",
-  "author": "",
-  "license": "MPL-2.0",
-  "version": "0.1.1",
-  "engines": {
-    "firefox": ">=27.0 <=30.0"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/toolbar-api/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);
deleted file mode 100644
--- a/addon-sdk/source/examples/ui-button-apis/lib/main.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var data = require('sdk/self').data;
-var tabs = require('sdk/tabs');
-var { notify } = require('sdk/notifications');
-var { ActionButton, ToggleButton } = require('sdk/ui');
-
-var icon = 'chrome://mozapps/skin/extensions/extensionGeneric.svg';
-exports.icon = icon;
-
-// your basic action button
-var action = ActionButton({
-  id: 'test-action-button',
-  label: 'Action Button',
-  icon: icon,
-  onClick: function (state) {
-    notify({
-      title: "Action!",
-      text: "This notification was triggered from an action button!",
-    });
-  }
-});
-exports.actionButton = action;
-
-var toggle = ToggleButton({
-  id: 'test-toggle-button',
-  label: 'Toggle Button',
-  icon: icon,
-  onClick: function (state) {
-    notify({
-      title: "Toggled!",
-      text: "The current state of the button is " + state.checked,
-    });
-  }
-});
-exports.toggleButton = toggle;
deleted file mode 100644
--- a/addon-sdk/source/examples/ui-button-apis/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "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",
-  "version": "0.1.1",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/ui-button-apis/tests/test-main.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";
-
-try {
-  // CFX use case..
-  var { actionButton, toggleButton, icon } = require("main");
-}
-catch (e) {
-  // JPM use case..
-  let mainURI = "../lib/main";
-  var { actionButton, toggleButton, icon } = require(mainURI);
-}
-var self = require("sdk/self");
-
-exports.testActionButton = function(assert) {
-  assert.equal(actionButton.id, "test-action-button", "action button id is correct");
-  assert.equal(actionButton.label, "Action Button", "action button label is correct");
-  assert.equal(actionButton.icon, icon, "action button icon is correct");
-}
-
-exports.testToggleButton = function(assert) {
-  assert.equal(toggleButton.id, "test-toggle-button", "toggle button id is correct");
-  assert.equal(toggleButton.label, "Toggle Button", "toggle button label is correct");
-  assert.equal(toggleButton.icon, icon, "toggle button icon is correct");
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/gulpfile.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var 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").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").catch(console.error).then(done);
-});
-
-gulp.task('test:modules', function(done) {
-  require("./bin/jpm-test").run("modules").catch(console.error).then(done);
-});
-
-gulp.task('test:ini', function(done) {
-  require("./bin/jpm-test").run("ini").catch(console.error).then(done);
-});
-
-gulp.task('test:firefox-bin', function(done) {
-  require("./bin/jpm-test").run("firefox-bin").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);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - 0.4
-  - 0.5
-  - 0.6
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/History.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changes
-
-## 1.0.1 / 2013-05-01
-
-  - Update method library version.
-
-## 1.0.0 / 2012-11-09
-
-  - Test integration for browsers.
-  - New method library.
-
-## 0.0.1 / 2012-10-22
-
-  - Initial release
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/License.md
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright 2012 Irakli Gozalishvili. All rights reserved.
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/Readme.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# diffpatcher
-
-[![Build Status](https://secure.travis-ci.org/Gozala/diffpatcher.png)](http://travis-ci.org/Gozala/diffpatcher)
-
-[![Browser support](https://ci.testling.com/Gozala/diffpatcher.png)](http://ci.testling.com/Gozala/diffpatcher)
-
-Diffpatcher is a small library that lets you treat hashes as if they were
-git repositories.
-
-## diff
-
-Diff function that takes two hashes and returns delta hash.
-
-```js
-var diff = require("diffpatcher/diff")
-
-diff({ a: { b: 1 }, c: { d: 2 } },      // hash#1
-     { a: { e: 3 }, c: { d: 4 } })      // hash#2
-
-// => {                                 // delta
-//      a: {
-//        b: null,        // -
-//        e: 3            // +
-//      },
-//      c: {
-//        d: 4            // ±
-//      }
-//    }
-```
-
-As you can see from the example above `delta` makes no real distinction between
-proprety upadate and property addition. Try to think of additions as an update
-from `undefined` to whatever it's being updated to.
-
-## patch
-
-Patch fuction takes a `hash` and a `delta` and returns a new `hash` which is
-just like orginial but with delta applied to it. Let's apply delta from the
-previous example to the first hash from the same example
-
-
-```js
-var patch = require("diffpatcher/patch")
-
-patch({ a: { b: 1 }, c: { d: 2 } },     // hash#1
-      {                                 // delta
-        a: {
-          b: null,        // -
-          e: 3            // +
-        },
-        c: {
-          d: 4            // ±
-        }
-      })
-
-// => { a: { e: 3 }, c: { d: 4 } }      // hash#2
-```
-
-That's about it really, just diffing hashes and applying thes diffs on them.
-
-
-### rebase
-
-And as Linus mentioned everything in git can be expressed with `rebase`, that
-also pretty much the case for `diffpatcher`. `rebase` takes `target` hash,
-and rebases `parent` onto it with `diff` applied.
-
-## Install
-
-    npm install diffpatcher
deleted file mode 100644
--- a/addon-sdk/source/lib/diffpatcher/package.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "name": "diffpatcher",
-  "id": "diffpatcher",
-  "version": "1.2.0",
-  "description": "Utilities for diff-ing & patch-ing hashes",
-  "keywords": [
-    "diff", "patch", "rebase", "hash", "changes", "versions"
-  ],
-  "author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
-  "homepage": "https://github.com/Gozala/diffpatcher",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/Gozala/diffpatcher.git",
-    "web": "https://github.com/Gozala/diffpatcher"
-  },
-  "bugs": {
-    "url": "http://github.com/Gozala/diffpatcher/issues/"
-  },
-  "dependencies": {
-    "method": "~2.0.0"
-  },
-  "devDependencies": {
-    "test": "~0.x.0",
-    "phantomify": "~0.x.0",
-    "retape": "~0.x.0",
-    "tape": "~0.1.5"
-  },
-  "main": "./index.js",
-  "scripts": {
-    "test": "npm run test-node && npm run test-browser",
-    "test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/common.js",
-    "test-node": "node ./test/common.js",
-    "test-tap": "node ./test/tap.js"
-  },
-  "testling": {
-    "files": "test/tap.js",
-    "browsers": [
-      "ie/9..latest",
-      "chrome/25..latest",
-      "firefox/20..latest",
-      "safari/6..latest",
-      "opera/11.0..latest",
-      "iphone/6..latest",
-      "ipad/6..latest",
-      "android-browser/4.2..latest"
-    ]
-  },
-  "licenses": [
-    {
-      "type": "MIT",
-      "url": "https://github.com/Gozala/diffpatcher/License.md"
-    }
-  ]
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/index.js
+++ /dev/null
@@ -1,3 +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/. */
deleted file mode 100644
--- a/addon-sdk/source/lib/jetpack-id/index.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * 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 || "");
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/jetpack-id/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "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": "*"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/method/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - 0.4
-  - 0.5
-  - 0.6
deleted file mode 100644
--- a/addon-sdk/source/lib/method/History.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Changes
-
-## 1.0.2 / 2012-12-26
-
-  - Delegate to polymorphic methods from `.define` and `.implement` so, they
-    can be overidden.
-
-## 1.0.1 / 2012-11-11
-
-  - Fix issues with different `Error` types as they all inherit from
-    `Error`.
-
-## 1.0.0 / 2012-11-09
-
-  - Add browser test integration.
-  - Fix cross-browser incompatibilities & test failures.
-  - Add support for host objects.
-  - Add optional `hint` argument for method to ease debugging.
-  - Remove default implementation at definition time.
-
-## 0.1.1 / 2012-10-15
-
- - Fix regression causing custom type implementation to be stored on objects.
-
-## 0.1.0 / 2012-10-15
-
- - Remove dependency on name module.
- - Implement fallback for engines that do not support ES5.
- - Add support for built-in type extensions without extending their prototypes.
- - Make API for default definitions more intuitive.
-   Skipping type argument now defines default:
-
-      isFoo.define(function(value) {
-        return false
-      })
-
- - Make exposed `define` and `implement` polymorphic.
- - Removed dev dependency on swank-js.
- - Primitive types `string, number, boolean` no longer inherit method
-   implementations from `Object`.
-
-## 0.0.3 / 2012-07-17
-
-  - Remove module boilerplate
-
-## 0.0.2 / 2012-06-26
-
-  - Name changes to make it less conflicting with other library conventions.
-  - Expose function version of `define` & `implement` methods.
-  - Expose `Null` and `Undefined` object holding implementations for an
-    associated types.
-
-## 0.0.1 / 2012-06-25
-
-  - Initial release
deleted file mode 100644
--- a/addon-sdk/source/lib/method/License.md
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright 2012 Irakli Gozalishvili. All rights reserved.
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
deleted file mode 100644
--- a/addon-sdk/source/lib/method/Readme.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# method
-
-[![Build Status](https://secure.travis-ci.org/Gozala/method.png)](http://travis-ci.org/Gozala/method)
-
-Library provides an API for defining polymorphic methods that dispatch on the
-first argument type. This provides a powerful way for decouple abstraction
-interface definition from an actual implementation per type, without risks
-of interference with other libraries.
-
-### Motivation
-
-  - Provide a high-performance, dynamic polymorphism construct as an
-    alternative to existing object methods that does not provides any
-    mechanics for guarding against name conflicts.
-  - Allow independent extension of types, and implementations of methods
-    on types, by different parties.
-
-## Install
-
-    npm install method
-
-## Use
-
-```js
-var method = require("method")
-
-// Define `isWatchable` method that can be implemented for any type.
-var isWatchable = method("isWatchable")
-
-// If you call it on any object it will
-// throw as nothing implements that method yet.
-//isWatchable({}) // => Exception: method is not implemented
-
-// If you define private method on `Object.prototype`
-// all objects will inherit it.
-Object.prototype[isWatchable] = function() {
-  return false;
-}
-
-isWatchable({}) // => false
-
-
-// Although `isWatchable` property above will be enumerable and there for
-// may damage some assumbtions made by other libraries. There for it"s
-// recomended to use built-in helpers methods that will define extension
-// without breaking assumbtions made by other libraries:
-
-isWatchable.define(Object, function() { return false })
-
-
-// There are primitive types in JS that won"t inherit methods from Object:
-isWatchable(null) // => Exception: method is not implemented
-
-// One could either implement methods for such types:
-isWatchable.define(null, function() { return false })
-isWatchable.define(undefined, function() { return false })
-
-// Or simply define default implementation:
-isWatchable.define(function() { return false })
-
-// Alternatively default implementation may be provided at creation:
-isWatchable = method(function() { return false })
-
-// Method dispatches on an first argument type. That allows us to create
-// new types with an alternative implementations:
-function Watchable() {}
-isWatchable.define(Watchable, function() { return true })
-
-// This will make all `Watchable` instances watchable!
-isWatchable(new Watchable()) // => true
-
-// Arbitrary objects can also be extended to implement given method. For example
-// any object can simply made watchable:
-function watchable(object) {
-  return isWatchable.implement(objct, function() { return true })
-}
-
-isWatchable(watchable({})) // => true
-
-// Full protocols can be defined with such methods:
-var observers = "observers@" + module.filename
-var watchers = method("watchers")
-var watch = method("watch")
-var unwatch = method("unwatch")
-
-watchers.define(Watchable, function(target) {
-  return target[observers] || (target[observers] = [])
-})
-
-watch.define(Watchable, function(target, watcher) {
-  var observers = watchers(target)
-  if (observers.indexOf(watcher) < 0) observers.push(watcher)
-  return target
-})
-unwatch.define(Watchable, function(target, watcher) {
-  var observers = watchers(target)
-  var index = observers.indexOf(watcher)
-  if (observers.indexOf(watcher) >= 0) observers.unshift(watcher)
-  return target
-})
-
-// Define type Port that inherits form Watchable
-
-function Port() {}
-Port.prototype = Object.create(Watchable.prototype)
-
-var emit = method("emit")
-emit.define(Port, function(port, message) {
-  watchers(port).slice().forEach(function(watcher) {
-    watcher(message)
-  })
-})
-
-var p = new Port()
-watch(p, console.log)
-emit(p, "hello world") // => info: "hello world"
-```
deleted file mode 100644
--- a/addon-sdk/source/lib/method/core.js
+++ /dev/null
@@ -1,225 +0,0 @@
-"use strict";
-
-var defineProperty = Object.defineProperty || function(object, name, property) {
-  object[name] = property.value
-  return object
-}
-
-// Shortcut for `Object.prototype.toString` for faster access.
-var typefy = Object.prototype.toString
-
-// Map to for jumping from typeof(value) to associated type prefix used
-// as a hash in the map of builtin implementations.
-var types = { "function": "Object", "object": "Object" }
-
-// Array is used to save method implementations for the host objects in order
-// to avoid extending them with non-primitive values that could cause leaks.
-var host = []
-// Hash map is used to save method implementations for builtin types in order
-// to avoid extending their prototypes. This also allows to share method
-// implementations for types across diff contexts / frames / compartments.
-var builtin = {}
-
-function Primitive() {}
-function ObjectType() {}
-ObjectType.prototype = new Primitive()
-function ErrorType() {}
-ErrorType.prototype = new ObjectType()
-
-var Default = builtin.Default = Primitive.prototype
-var Null = builtin.Null = new Primitive()
-var Void = builtin.Void = new Primitive()
-builtin.String = new Primitive()
-builtin.Number = new Primitive()
-builtin.Boolean = new Primitive()
-
-builtin.Object = ObjectType.prototype
-builtin.Error = ErrorType.prototype
-
-builtin.EvalError = new ErrorType()
-builtin.InternalError = new ErrorType()
-builtin.RangeError = new ErrorType()
-builtin.ReferenceError = new ErrorType()
-builtin.StopIteration = new ErrorType()
-builtin.SyntaxError = new ErrorType()
-builtin.TypeError = new ErrorType()
-builtin.URIError = new ErrorType()
-
-
-function Method(hint) {
-  /**
-  Private Method is a callable private name that dispatches on the first
-  arguments same named Method:
-
-      method(object, ...rest) => object[method](...rest)
-
-  Optionally hint string may be provided that will be used in generated names
-  to ease debugging.
-
-  ## Example
-
-      var foo = Method()
-
-      // Implementation for any types
-      foo.define(function(value, arg1, arg2) {
-        // ...
-      })
-
-      // Implementation for a specific type
-      foo.define(BarType, function(bar, arg1, arg2) {
-        // ...
-      })
-  **/
-
-  // Create an internal unique name if `hint` is provided it is used to
-  // prefix name to ease debugging.
-  var name = (hint || "") + "#" + Math.random().toString(32).substr(2)
-
-  function dispatch(value) {
-    // Method dispatches on type of the first argument.
-    // If first argument is `null` or `void` associated implementation is
-    // looked up in the `builtin` hash where implementations for built-ins
-    // are stored.
-    var type = null
-    var method = value === null ? Null[name] :
-                 value === void(0) ? Void[name] :
-                 // Otherwise attempt to use method with a generated private
-                 // `name` that is supposedly in the prototype chain of the
-                 // `target`.
-                 value[name] ||
-                 // Otherwise assume it's one of the built-in type instances,
-                 // in which case implementation is stored in a `builtin` hash.
-                 // Attempt to find a implementation for the given built-in
-                 // via constructor name and method name.
-                 ((type = builtin[(value.constructor || "").name]) &&
-                  type[name]) ||
-                 // Otherwise assume it's a host object. For host objects
-                 // actual method implementations are stored in the `host`
-                 // array and only index for the implementation is stored
-                 // in the host object's prototype chain. This avoids memory
-                 // leaks that otherwise could happen when saving JS objects
-                 // on host object.
-                 host[value["!" + name] || void(0)] ||
-                 // Otherwise attempt to lookup implementation for builtins by
-                 // a type of the value. This basically makes sure that all
-                 // non primitive values will delegate to an `Object`.
-                 ((type = builtin[types[typeof(value)]]) && type[name])
-
-
-    // If method implementation for the type is still not found then
-    // just fallback for default implementation.
-    method = method || Default[name]
-
-
-    // If implementation is still not found (which also means there is no
-    // default) just throw an error with a descriptive message.
-    if (!method) throw TypeError("Type does not implements method: " + name)
-
-    // If implementation was found then just delegate.
-    return method.apply(method, arguments)
-  }
-
-  // Make `toString` of the dispatch return a private name, this enables
-  // method definition without sugar:
-  //
-  //    var method = Method()
-  //    object[method] = function() { /***/ }
-  dispatch.toString = function toString() { return name }
-
-  // Copy utility methods for convenient API.
-  dispatch.implement = implementMethod
-  dispatch.define = defineMethod
-
-  return dispatch
-}
-
-// Create method shortcuts form functions.
-var defineMethod = function defineMethod(Type, lambda) {
-  return define(this, Type, lambda)
-}
-var implementMethod = function implementMethod(object, lambda) {
-  return implement(this, object, lambda)
-}
-
-// Define `implement` and `define` polymorphic methods to allow definitions
-// and implementations through them.
-var implement = Method("implement")
-var define = Method("define")
-
-
-function _implement(method, object, lambda) {
-  /**
-  Implements `Method` for the given `object` with a provided `implementation`.
-  Calling `Method` with `object` as a first argument will dispatch on provided
-  implementation.
-  **/
-  return defineProperty(object, method.toString(), {
-    enumerable: false,
-    configurable: false,
-    writable: false,
-    value: lambda
-  })
-}
-
-function _define(method, Type, lambda) {
-  /**
-  Defines `Method` for the given `Type` with a provided `implementation`.
-  Calling `Method` with a first argument of this `Type` will dispatch on
-  provided `implementation`. If `Type` is a `Method` default implementation
-  is defined. If `Type` is a `null` or `undefined` `Method` is implemented
-  for that value type.
-  **/
-
-  // Attempt to guess a type via `Object.prototype.toString.call` hack.
-  var type = Type && typefy.call(Type.prototype)
-
-  // If only two arguments are passed then `Type` is actually an implementation
-  // for a default type.
-  if (!lambda) Default[method] = Type
-  // If `Type` is `null` or `void` store implementation accordingly.
-  else if (Type === null) Null[method] = lambda
-  else if (Type === void(0)) Void[method] = lambda
-  // If `type` hack indicates built-in type and type has a name us it to
-  // store a implementation into associated hash. If hash for this type does
-  // not exists yet create one.
-  else if (type !== "[object Object]" && Type.name) {
-    var Bulitin = builtin[Type.name] || (builtin[Type.name] = new ObjectType())
-    Bulitin[method] = lambda
-  }
-  // If `type` hack indicates an object, that may be either object or any
-  // JS defined "Class". If name of the constructor is `Object`, assume it's
-  // built-in `Object` and store implementation accordingly.
-  else if (Type.name === "Object")
-    builtin.Object[method] = lambda
-  // Host objects are pain!!! Every browser does some crazy stuff for them
-  // So far all browser seem to not implement `call` method for host object
-  // constructors. If that is a case here, assume it's a host object and
-  // store implementation in a `host` array and store `index` in the array
-  // in a `Type.prototype` itself. This avoids memory leaks that could be
-  // caused by storing JS objects on a host objects.
-  else if (Type.call === void(0)) {
-    var index = host.indexOf(lambda)
-    if (index < 0) index = host.push(lambda) - 1
-    // Prefix private name with `!` so it can be dispatched from the method
-    // without type checks.
-    implement("!" + method, Type.prototype, index)
-  }
-  // If Got that far `Type` is user defined JS `Class`. Define private name
-  // as hidden property on it's prototype.
-  else
-    implement(method, Type.prototype, lambda)
-}
-
-// And provided implementations for a polymorphic equivalents.
-_define(define, _define)
-_define(implement, _implement)
-
-// Define exports on `Method` as it's only thing being exported.
-Method.implement = implement
-Method.define = define
-Method.Method = Method
-Method.method = Method
-Method.builtin = builtin
-Method.host = host
-
-module.exports = Method
deleted file mode 100644
--- a/addon-sdk/source/lib/method/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "name": "method",
-  "id": "method",
-  "version": "1.0.2",
-  "description": "Functional polymorphic method dispatch",
-  "keywords": [
-    "method",
-    "dispatch",
-    "protocol",
-    "polymorphism",
-    "type dispatch"
-  ],
-  "author": "Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
-  "homepage": "https://github.com/Gozala/method",
-  "main": "./core.js",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/Gozala/method.git",
-    "web": "https://github.com/Gozala/method"
-  },
-  "bugs": {
-    "url": "http://github.com/Gozala/method/issues/"
-  },
-  "devDependencies": {
-    "test": "~0.x.0",
-    "repl-utils": "~2.0.1",
-    "phantomify": "~0.1.0"
-  },
-  "scripts": {
-    "test": "npm run test-node && npm run test-browser",
-    "test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/browser.js",
-    "test-node": "node ./test/common.js",
-    "repl": "node node_modules/repl-utils"
-  },
-  "licenses": [
-    {
-      "type": "MIT",
-      "url": "https://github.com/Gozala/method/License.md"
-    }
-  ]
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/mozilla-toolkit-versioning/index.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-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;
deleted file mode 100644
--- a/addon-sdk/source/lib/mozilla-toolkit-versioning/lib/utils.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * 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;
deleted file mode 100644
--- a/addon-sdk/source/lib/mozilla-toolkit-versioning/package.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "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"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/node/os.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci } = require('chrome');
-const system = require('../sdk/system');
-const runtime = require('../sdk/system/runtime');
-const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
-const isWindows = system.platform === 'win32';
-const endianness = ((new Uint32Array((new Uint8Array([1,2,3,4])).buffer))[0] === 0x04030201) ? 'LE' : 'BE';
-
-XPCOMUtils.defineLazyGetter(this, "oscpu", () => {
-  try {
-    return Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).oscpu;
-  } catch (e) {
-    return "";
-  }
-});
-
-XPCOMUtils.defineLazyGetter(this, "hostname", () => {
-  try {
-    // On some platforms (Linux according to try), this service does not exist and fails.
-    return Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService).myHostName;
-  } catch (e) {
-    return "";
-  }
-});
-
-/**
- * Returns a path to a temp directory
- */
-exports.tmpdir = () => system.pathFor('TmpD');
-
-/**
- * Returns the endianness of the architecture: either 'LE' or 'BE'
- */
-exports.endianness = () => endianness;
-
-/**
- * Returns hostname of the machine
- */
-exports.hostname = () => hostname;
-
-/**
- * Name of the OS type
- * Possible values:
- * https://developer.mozilla.org/en/OS_TARGET
- */
-exports.type = () => runtime.OS;
-
-/**
- * Name of the OS Platform in lower case string.
- * Possible values:
- * https://developer.mozilla.org/en/OS_TARGET
- */
-exports.platform = () => system.platform;
-
-/**
- * Type of processor architecture running:
- * 'arm', 'ia32', 'x86', 'x64'
- */
-exports.arch = () => system.architecture;
-
-/**
- * Returns the operating system release.
- */
-exports.release = () => {
-  let match = oscpu.match(/(\d[\.\d]*)/);
-  return match && match.length > 1 ? match[1] : oscpu;
-};
-
-/**
- * Returns EOL character for the OS
- */
-exports.EOL = isWindows ? '\r\n' : '\n';
-
-/**
- * Returns [0, 0, 0], as this is not implemented.
- */
-exports.loadavg = () => [0, 0, 0];
-
-['uptime', 'totalmem', 'freemem', 'cpus'].forEach(method => {
-  exports[method] = () => { throw new Error('os.' + method + ' is not supported.'); };
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/addon/installer.js
+++ /dev/null
@@ -1,121 +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/. */
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cc, Ci, Cu } = require("chrome");
-const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
-const { defer } = require("../core/promise");
-const { setTimeout } = require("../timers");
-
-/**
- * `install` method error codes:
- *
- * https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors
- */
-exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE;
-exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH;
-exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE;
-exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS;
-
-/**
- * Immediatly install an addon.
- *
- * @param {String} xpiPath
- *   file path to an xpi file to install
- * @return {Promise}
- *   A promise resolved when the addon is finally installed.
- *   Resolved with addon id as value or rejected with an error code.
- */
-exports.install = function install(xpiPath) {
-  let { promise, resolve, reject } = defer();
-
-  // Create nsIFile for the xpi file
-  let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
-  try {
-    file.initWithPath(xpiPath);
-  }
-  catch(e) {
-    reject(exports.ERROR_FILE_ACCESS);
-    return promise;
-  }
-
-  // Listen for installation end
-  let listener = {
-    onInstallEnded: function(aInstall, aAddon) {
-      aInstall.removeListener(listener);
-      // Bug 749745: on FF14+, onInstallEnded is called just before `startup()`
-      // is called, but we expect to resolve the promise only after it.
-      // As startup is called synchronously just after onInstallEnded,
-      // a simple setTimeout(0) is enough
-      setTimeout(resolve, 0, aAddon.id);
-    },
-    onInstallFailed: function (aInstall) {
-      aInstall.removeListener(listener);
-      reject(aInstall.error);
-    },
-    onDownloadFailed: function(aInstall) {
-      this.onInstallFailed(aInstall);
-    }
-  };
-
-  // Order AddonManager to install the addon
-  AddonManager.getInstallForFile(file, function(install) {
-    if (install.error == 0) {
-      install.addListener(listener);
-      install.install();
-    } else {
-      reject(install.error);
-    }
-  });
-
-  return promise;
-};
-
-exports.uninstall = function uninstall(addonId) {
-  let { promise, resolve, reject } = defer();
-
-  // Listen for uninstallation end
-  let listener = {
-    onUninstalled: function onUninstalled(aAddon) {
-      if (aAddon.id != addonId)
-        return;
-      AddonManager.removeAddonListener(listener);
-      resolve();
-    }
-  };
-  AddonManager.addAddonListener(listener);
-
-  // Order Addonmanager to uninstall the addon
-  getAddon(addonId).then(addon => addon.uninstall(), reject);
-
-  return promise;
-};
-
-exports.disable = function disable(addonId) {
-  return getAddon(addonId).then(addon => {
-    addon.userDisabled = true;
-    return addonId;
-  });
-};
-
-exports.enable = function enabled(addonId) {
-  return getAddon(addonId).then(addon => {
-    addon.userDisabled = false;
-    return addonId;
-  });
-};
-
-exports.isActive = function isActive(addonId) {
-  return getAddon(addonId).then(addon => addon.isActive && !addon.appDisabled);
-};
-
-const getAddon = function getAddon (id) {
-  let { promise, resolve, reject } = defer();
-  AddonManager.getAddonByID(id, addon => addon ? resolve(addon) : reject());
-  return promise;
-}
-exports.getAddon = getAddon;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/addon/window.js
+++ /dev/null
@@ -1,81 +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 { Ci, Cc, Cu } = require("chrome");
-const { when: unload } = require("../system/unload");
-const prefs = require("../preferences/service");
-
-if (!prefs.get("extensions.usehiddenwindow", false)) {
-  const {HiddenFrame} = require("resource://gre/modules/HiddenFrame.jsm", {});
-  let hiddenFrame = new HiddenFrame();
-  exports.window = hiddenFrame.getWindow();
-  exports.ready = hiddenFrame.get();
-
-  // Still destroy frame on unload to claim memory back early.
-  // NOTE: this doesn't seem to work and just doesn't get called. :-\
-  unload(function() {
-    hiddenFrame.destroy();
-    hiddenFrame = null;
-  });
-} else {
-  const { make: makeWindow, getHiddenWindow } = require("../window/utils");
-  const { create: makeFrame, getDocShell } = require("../frame/utils");
-  const { defer } = require("../core/promise");
-  const cfxArgs = require("../test/options");
-
-  var addonPrincipal = Cc["@mozilla.org/systemprincipal;1"].
-                       createInstance(Ci.nsIPrincipal);
-
-  var hiddenWindow = getHiddenWindow();
-
-  if (cfxArgs.parseable) {
-    console.info("hiddenWindow document.documentURI:" +
-      hiddenWindow.document.documentURI);
-    console.info("hiddenWindow document.readyState:" +
-      hiddenWindow.document.readyState);
-  }
-
-  // Once Bug 565388 is fixed and shipped we'll be able to make invisible,
-  // permanent docShells. Meanwhile we create hidden top level window and
-  // use it's docShell.
-  var frame = makeFrame(hiddenWindow.document, {
-    nodeName: "iframe",
-    namespaceURI: "http://www.w3.org/1999/xhtml",
-    allowJavascript: true,
-    allowPlugins: true
-  })
-  var docShell = getDocShell(frame);
-  var eventTarget = docShell.chromeEventHandler;
-
-  // We need to grant docShell system principals in order to load XUL document
-  // from data URI into it.
-  docShell.createAboutBlankContentViewer(addonPrincipal);
-
-  // Get a reference to the DOM window of the given docShell and load
-  // such document into that would allow us to create XUL iframes, that
-  // are necessary for hidden frames etc..
-  var window = docShell.contentViewer.DOMDocument.defaultView;
-  window.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
-
-  // Create a promise that is delivered once add-on window is interactive,
-  // used by add-on runner to defer add-on loading until window is ready.
-  var { promise, resolve } = defer();
-  eventTarget.addEventListener("DOMContentLoaded", function(event) {
-    resolve();
-  }, {once: true});
-
-  exports.ready = promise;
-  exports.window = window;
-
-  // Still close window on unload to claim memory back early.
-  unload(function() {
-    window.close()
-    frame.remove();
-  });
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/base64.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cu } = require("chrome");
-
-// Passing an empty object as second argument to avoid scope's pollution
-// (devtools loader injects these symbols as global and prevent using
-// const here)
-var { atob, btoa } = Cu.import("resource://gre/modules/Services.jsm", {});
-
-function isUTF8(charset) {
-  let type = typeof charset;
-
-  if (type === "undefined")
-    return false;
-
-  if (type === "string" && charset.toLowerCase() === "utf-8")
-    return true;
-
-  throw new Error("The charset argument can be only 'utf-8'");
-}
-
-function toOctetChar(c) {
-  return String.fromCharCode(c.charCodeAt(0) & 0xFF);
-}
-
-exports.decode = function (data, charset) {
-  if (isUTF8(charset))
-    return decodeURIComponent(escape(atob(data)))
-
-  return atob(data);
-}
-
-exports.encode = function (data, charset) {
-  if (isUTF8(charset))
-    return btoa(unescape(encodeURIComponent(data)))
-
-  data = data.replace(/[^\x00-\xFF]/g, toOctetChar);
-  return btoa(data);
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/console/traceback.js
+++ /dev/null
@@ -1,86 +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 { Ci, components } = require("chrome");
-const { parseStack, sourceURI } = require("toolkit/loader");
-lazyRequire(this, "../net/url", "readURISync");
-
-function safeGetFileLine(path, line) {
-  try {
-    var scheme = require("../url").URL(path).scheme;
-    // TODO: There should be an easier, more accurate way to figure out
-    // what's the case here.
-    if (!(scheme == "http" || scheme == "https"))
-      return readURISync(path).split("\n")[line - 1];
-  } catch (e) {}
-  return null;
-}
-
-function nsIStackFramesToJSON(frame) {
-  var stack = [];
-
-  while (frame) {
-    if (frame.filename) {
-      stack.unshift({
-        fileName: sourceURI(frame.filename),
-        lineNumber: frame.lineNumber,
-        name: frame.name
-      });
-    }
-    frame = frame.caller;
-  }
-
-  return stack;
-};
-
-var fromException = exports.fromException = function fromException(e) {
-  if (e instanceof Ci.nsIException)
-    return nsIStackFramesToJSON(e.location);
-  if (e.stack && e.stack.length)
-    return parseStack(e.stack);
-  if (e.fileName && typeof(e.lineNumber == "number"))
-    return [{fileName: sourceURI(e.fileName),
-             lineNumber: e.lineNumber,
-             name: null}];
-  return [];
-};
-
-var get = exports.get = function get() {
-  return nsIStackFramesToJSON(components.stack.caller);
-};
-
-var format = exports.format = function format(tbOrException) {
-  if (tbOrException === undefined) {
-    tbOrException = get();
-    tbOrException.pop();
-  }
-
-  var tb;
-  if (typeof(tbOrException) == "object" &&
-      tbOrException.constructor.name == "Array")
-    tb = tbOrException;
-  else
-    tb = fromException(tbOrException);
-
-  var lines = ["Traceback (most recent call last):"];
-
-  tb.forEach(
-    function(frame) {
-      if (!(frame.fileName || frame.lineNumber || frame.name))
-      	return;
-
-      lines.push('  File "' + frame.fileName + '", line ' +
-                 frame.lineNumber + ', in ' + frame.name);
-      var sourceLine = safeGetFileLine(frame.fileName, frame.lineNumber);
-      if (sourceLine)
-        lines.push('    ' + sourceLine.trim());
-    });
-
-  return lines.join("\n");
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/core/disposable.js
+++ /dev/null
@@ -1,187 +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 { Class } = require("./heritage");
-const { Observer, subscribe, unsubscribe, observe } = require("./observer");
-
-lazyRequire(this, "./reference", "isWeak");
-lazyRequireModule(this, "../lang/weak-set", "SDKWeakSet");
-
-const method = require("../../method/core");
-
-const unloadSubject = require('@loader/unload');
-const addonUnloadTopic = "sdk:loader:destroy";
-
-const uninstall = method("disposable/uninstall");
-exports.uninstall = uninstall;
-
-const shutdown = method("disposable/shutdown");
-exports.shutdown = shutdown;
-
-const disable = method("disposable/disable");
-exports.disable = disable;
-
-const upgrade = method("disposable/upgrade");
-exports.upgrade = upgrade;
-
-const downgrade = method("disposable/downgrade");
-exports.downgrade = downgrade;
-
-const unload = method("disposable/unload");
-exports.unload = unload;
-
-const dispose = method("disposable/dispose");
-exports.dispose = dispose;
-dispose.define(Object, object => object.dispose());
-
-const setup = method("disposable/setup");
-exports.setup = setup;
-setup.define(Object, (object, ...args) => object.setup(...args));
-
-// DisposablesUnloadObserver is the class which subscribe the
-// Observer Service to be notified when the add-on loader is
-// unloading to be able to dispose all the existent disposables.
-const DisposablesUnloadObserver = Class({
-  implements: [Observer],
-  initialize: function(...args) {
-    // Set of the non-weak disposables registered to be disposed.
-    this.disposables = new Set();
-    // Target of the weak disposables registered to be disposed
-    // (and tracked on this target using the SDK weak-set module).
-    this.weakDisposables = {};
-  },
-  subscribe(disposable) {
-    if (isWeak(disposable)) {
-      SDKWeakSet.add(this.weakDisposables, disposable);
-    } else {
-      this.disposables.add(disposable);
-    }
-  },
-  unsubscribe(disposable) {
-    if (isWeak(disposable)) {
-      SDKWeakSet.remove(this.weakDisposables, disposable);
-    } else {
-      this.disposables.delete(disposable);
-    }
-  },
-  tryUnloadDisposable(disposable) {
-    try {
-      if (disposable) {
-        unload(disposable);
-      }
-    } catch(e) {
-      console.error("Error unloading a",
-                    isWeak(disposable) ? "weak disposable" : "disposable",
-                    disposable, e);
-    }
-  },
-  unloadAll() {
-    // Remove all the subscribed disposables.
-    for (let disposable of this.disposables) {
-      this.tryUnloadDisposable(disposable);
-    }
-
-    this.disposables.clear();
-
-    // Remove all the subscribed weak disposables.
-    for (let disposable of SDKWeakSet.iterator(this.weakDisposables)) {
-      this.tryUnloadDisposable(disposable);
-    }
-
-    SDKWeakSet.clear(this.weakDisposables);
-  }
-});
-const disposablesUnloadObserver = new DisposablesUnloadObserver();
-
-// The DisposablesUnloadObserver instance is the only object which subscribes
-// the Observer Service directly, it observes add-on unload notifications in
-// order to trigger `unload` on all its subscribed disposables.
-observe.define(DisposablesUnloadObserver, (obj, subject, topic, data) => {
-  const isUnloadTopic = topic === addonUnloadTopic;
-  const isUnloadSubject = subject.wrappedJSObject === unloadSubject;
-  if (isUnloadTopic && isUnloadSubject) {
-    unsubscribe(disposablesUnloadObserver, addonUnloadTopic);
-    disposablesUnloadObserver.unloadAll();
-  }
-});
-
-subscribe(disposablesUnloadObserver, addonUnloadTopic, false);
-
-// Set's up disposable instance.
-const setupDisposable = disposable => {
-  disposablesUnloadObserver.subscribe(disposable);
-};
-exports.setupDisposable = setupDisposable;
-
-// Tears down disposable instance.
-const disposeDisposable = disposable => {
-  disposablesUnloadObserver.unsubscribe(disposable);
-};
-exports.disposeDisposable = disposeDisposable;
-
-// Base type that takes care of disposing it's instances on add-on unload.
-// Also makes sure to remove unload listener if it's already being disposed.
-const Disposable = Class({
-  initialize: function(...args) {
-    // First setup instance before initializing it's disposal. If instance
-    // fails to initialize then there is no instance to be disposed at the
-    // unload.
-    setup(this, ...args);
-    setupDisposable(this);
-  },
-  destroy: function(reason) {
-    // Destroying disposable removes unload handler so that attempt to dispose
-    // won't be made at unload & delegates to dispose.
-    disposeDisposable(this);
-    unload(this, reason);
-  },
-  setup: function() {
-    // Implement your initialize logic here.
-  },
-  dispose: function() {
-    // Implement your cleanup logic here.
-  }
-});
-exports.Disposable = Disposable;
-
-const unloaders = {
-  destroy: dispose,
-  uninstall: uninstall,
-  shutdown: shutdown,
-  disable: disable,
-  upgrade: upgrade,
-  downgrade: downgrade
-};
-
-const unloaded = new WeakMap();
-unload.define(Disposable, (disposable, reason) => {
-  if (!unloaded.get(disposable)) {
-    unloaded.set(disposable, true);
-    // Pick an unload handler associated with an unload
-    // reason (falling back to destroy if not found) and
-    // delegate unloading to it.
-    const unload = unloaders[reason] || unloaders.destroy;
-    unload(disposable);
-  }
-});
-
-// If add-on is disabled manually, it's being upgraded, downgraded
-// or uninstalled `dispose` is invoked to undo any changes that
-// has being done by it in this session.
-disable.define(Disposable, dispose);
-downgrade.define(Disposable, dispose);
-upgrade.define(Disposable, dispose);
-uninstall.define(Disposable, dispose);
-
-// If application is shut down no dispose is invoked as undo-ing
-// changes made by instance is likely to just waste of resources &
-// increase shutdown time. Although specefic components may choose
-// to implement shutdown handler that does something better.
-shutdown.define(Disposable, disposable => {});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/core/namespace.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const create = Object.create;
-const prototypeOf = Object.getPrototypeOf;
-
-/**
- * Returns a new namespace, function that may can be used to access an
- * namespaced object of the argument argument. Namespaced object are associated
- * with owner objects via weak references. Namespaced objects inherit from the
- * owners ancestor namespaced object. If owner's ancestor is `null` then
- * namespaced object inherits from given `prototype`. Namespaces can be used
- * to define internal APIs that can be shared via enclosing `namespace`
- * function.
- * @examples
- *    const internals = ns();
- *    internals(object).secret = secret;
- */
-function ns() {
-  const map = new WeakMap();
-  return function namespace(target) {
-    if (!target)        // If `target` is not an object return `target` itself.
-      return target;
-    // If target has no namespaced object yet, create one that inherits from
-    // the target prototype's namespaced object.
-    if (!map.has(target))
-      map.set(target, create(namespace(prototypeOf(target) || null)));
-
-    return map.get(target);
-  };
-};
-
-// `Namespace` is a e4x function in the scope, so we export the function also as
-// `ns` as alias to avoid clashing.
-exports.ns = ns;
-exports.Namespace = ns;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/core/observer.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-
-const { Cc, Ci, Cr, Cu } = require("chrome");
-const { Class } = require("./heritage");
-lazyRequire(this, "./reference", "isWeak");
-const method = require("../../method/core");
-
-const observerService = Cc['@mozilla.org/observer-service;1'].
-                          getService(Ci.nsIObserverService);
-
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
-const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
-
-// This is a method that will be invoked when notification observer
-// subscribed to occurs.
-const observe = method("observer/observe");
-exports.observe = observe;
-
-// Method to subscribe to the observer notification.
-const subscribe = method("observe/subscribe");
-exports.subscribe = subscribe;
-
-
-// Method to unsubscribe from the observer notifications.
-const unsubscribe = method("observer/unsubscribe");
-exports.unsubscribe = unsubscribe;
-
-
-// This is wrapper class that takes a `delegate` and produces
-// instance of `nsIObserver` which will delegate to a given
-// object when observer notification occurs.
-const ObserverDelegee = Class({
-  initialize: function(delegate) {
-    this.delegate = delegate;
-  },
-  QueryInterface: function(iid) {
-    if (!iid.equals(Ci.nsIObserver) &&
-        !iid.equals(Ci.nsISupportsWeakReference) &&
-        !iid.equals(Ci.nsISupports))
-      throw Cr.NS_ERROR_NO_INTERFACE;
-
-    return this;
-  },
-  observe: function(subject, topic, data) {
-    observe(this.delegate, subject, topic, data);
-  }
-});
-
-
-// Class that can be either mixed in or inherited from in
-// order to subscribe / unsubscribe for observer notifications.
-const Observer = Class({});
-exports.Observer = Observer;
-
-// Weak maps that associates instance of `ObserverDelegee` with
-// an actual observer. It ensures that `ObserverDelegee` instance
-// won't be GC-ed until given `observer` is.
-const subscribers = new WeakMap();
-
-// Implementation of `subscribe` for `Observer` type just registers
-// observer for an observer service. If `isWeak(observer)` is `true`
-// observer service won't hold strong reference to a given `observer`.
-subscribe.define(Observer, (observer, topic) => {
-  if (!subscribers.has(observer)) {
-    const delegee = new ObserverDelegee(observer);
-    subscribers.set(observer, delegee);
-    addObserver(delegee, topic, isWeak(observer));
-  }
-});
-
-// Unsubscribes `observer` from observer notifications for the
-// given `topic`.
-unsubscribe.define(Observer, (observer, topic) => {
-  const delegee = subscribers.get(observer);
-  if (delegee) {
-    subscribers.delete(observer);
-    removeObserver(delegee, topic);
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/core/promise.js
+++ /dev/null
@@ -1,118 +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';
-
-/*
- * 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
- * https://github.com/kriskowal/q
- */
-const PROMISE_URI = 'resource://gre/modules/Promise.jsm';
-
-getEnvironment.call(this, function ({ require, exports, module, Cu }) {
-
-const Promise = Cu.import(PROMISE_URI, {}).Promise;
-const { Debugging, defer, resolve, all, reject, race } = Promise;
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-var promised = (function() {
-  // Note: Define shortcuts and utility functions here in order to avoid
-  // slower property accesses and unnecessary closure creations on each
-  // call of this popular function.
-
-  var call = Function.call;
-  var concat = Array.prototype.concat;
-
-  // Utility function that does following:
-  // execute([ f, self, args...]) => f.apply(self, args)
-  function execute (args) {
-    return call.apply(call, args);
-  }
-
-  // Utility function that takes promise of `a` array and maybe promise `b`
-  // as arguments and returns promise for `a.concat(b)`.
-  function promisedConcat(promises, unknown) {
-    return promises.then(function (values) {
-      return resolve(unknown)
-        .then(value => values.concat([value]));
-    });
-  }
-
-  return function promised(f, prototype) {
-    /**
-    Returns a wrapped `f`, which when called returns a promise that resolves to
-    `f(...)` passing all the given arguments to it, which by the way may be
-    promises. Optionally second `prototype` argument may be provided to be used
-    a prototype for a returned promise.
-
-    ## Example
-
-    var promise = promised(Array)(1, promise(2), promise(3))
-    promise.then(console.log) // => [ 1, 2, 3 ]
-    **/
-
-    return function promised(...args) {
-      // create array of [ f, this, args... ]
-      return [f, this, ...args].
-        // reduce it via `promisedConcat` to get promised array of fulfillments
-        reduce(promisedConcat, resolve([], prototype)).
-        // finally map that to promise of `f.apply(this, args...)`
-        then(execute);
-    };
-  };
-})();
-
-exports.promised = promised;
-exports.all = all;
-exports.defer = defer;
-exports.resolve = resolve;
-exports.reject = reject;
-exports.race = race;
-exports.Promise = Promise;
-exports.Debugging = Debugging;
-});
-
-function getEnvironment (callback) {
-  let Cu, _exports, _module, _require;
-
-  // CommonJS / SDK
-  if (typeof(require) === 'function') {
-    Cu = require('chrome').Cu;
-    _exports = exports;
-    _module = module;
-    _require = require;
-  }
-  // JSM
-  else if (String(this).indexOf('BackstagePass') >= 0) {
-    Cu = this['Components'].utils;
-    _exports = this.Promise = {};
-    _module = { uri: __URI__, id: 'promise/core' };
-    _require = uri => {
-      let imports = {};
-      Cu.import(uri, imports);
-      return imports;
-    };
-    this.EXPORTED_SYMBOLS = ['Promise'];
-  // mozIJSSubScriptLoader.loadSubscript
-  } else if (~String(this).indexOf('Sandbox')) {
-    Cu = this['Components'].utils;
-    _exports = this;
-    _module = { id: 'promise/core' };
-    _require = uri => {};
-  }
-
-  callback({
-    Cu: Cu,
-    exports: _exports,
-    module: _module,
-    require: _require
-  });
-}
-
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/core/reference.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";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const method = require("../../method/core");
-const { Class } = require("./heritage");
-
-// Object that inherit or mix WeakRefence inn will register
-// weak observes for system notifications.
-const WeakReference = Class({});
-exports.WeakReference = WeakReference;
-
-
-// If `isWeak(object)` is `true` observer installed
-// for such `object` will be weak, meaning that it will
-// be GC-ed if nothing else but observer is observing it.
-// By default everything except `WeakReference` will return
-// `false`.
-const isWeak = method("reference/weak?");
-exports.isWeak = isWeak;
-
-isWeak.define(Object, _ => false);
-isWeak.define(WeakReference, _ => true);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test-finder.js
+++ /dev/null
@@ -1,199 +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 file = require("../io/file");
-const { Loader } = require("../test/loader");
-
-const { isNative } = require('@loader/options');
-
-const cuddlefish = isNative ? require("toolkit/loader") : require("../loader/cuddlefish");
-
-const { defer, resolve } = require("../core/promise");
-const { getAddon } = require("../addon/installer");
-const { id } = require("sdk/self");
-const { newURI } = require('sdk/url/utils');
-const { getZipReader } = require("../zip/utils");
-
-const { Cc, Ci, Cu } = require("chrome");
-const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
-var ios = Cc['@mozilla.org/network/io-service;1']
-          .getService(Ci.nsIIOService);
-
-const CFX_TEST_REGEX = /(([^\/]+\/)(?:lib\/)?)?(tests?\/test-[^\.\/]+)\.js$/;
-const JPM_TEST_REGEX = /^()(tests?\/test-[^\.\/]+)\.js$/;
-
-const { mapcat, map, filter, fromEnumerator } = require("sdk/util/sequence");
-
-const toFile = x => x.QueryInterface(Ci.nsIFile);
-const isTestFile = ({leafName}) => leafName.substr(0, 5) == "test-" && leafName.substr(-3, 3) == ".js";
-const getFileURI = x => ios.newFileURI(x).spec;
-
-const getDirectoryEntries = file => map(toFile, fromEnumerator(_ => file.directoryEntries));
-const getTestFiles = directory => filter(isTestFile, getDirectoryEntries(directory));
-const getTestURIs = directory => map(getFileURI, getTestFiles(directory));
-
-const isDirectory = x => x.isDirectory();
-const getTestEntries = directory => mapcat(entry =>
-  /^tests?$/.test(entry.leafName) ? getTestURIs(entry) : getTestEntries(entry),
-  filter(isDirectory, getDirectoryEntries(directory)));
-
-const removeDups = (array) => array.reduce((result, value) => {
-  if (value != result[result.length - 1]) {
-    result.push(value);
-  }
-  return result;
-}, []);
-
-const getSuites = function getSuites({ id, filter }) {
-  const TEST_REGEX = isNative ? JPM_TEST_REGEX : CFX_TEST_REGEX;
-
-  return getAddon(id).then(addon => {
-    let fileURI = addon.getResourceURI("tests/");
-    let isPacked = fileURI.scheme == "jar";
-    let xpiURI = addon.getResourceURI();
-    let file = xpiURI.QueryInterface(Ci.nsIFileURL).file;
-    let suites = [];
-    let addEntry = (entry) => {
-      if (filter(entry) && TEST_REGEX.test(entry)) {
-        let suite = (isNative ? "./" : "") + (RegExp.$2 || "") + RegExp.$3;
-        suites.push(suite);
-      }
-    }
-
-    if (isPacked) {
-      return getZipReader(file).then(zip => {
-        let entries = zip.findEntries(null);
-        while (entries.hasMore()) {
-          let entry = entries.getNext();
-          addEntry(entry);
-        }
-        zip.close();
-
-        // sort and remove dups
-        suites = removeDups(suites.sort());
-        return suites;
-      })
-    }
-    else {
-      let tests = [...getTestEntries(file)];
-      let rootURI = addon.getResourceURI("/");
-      tests.forEach((entry) => {
-        addEntry(entry.replace(rootURI.spec, ""));
-      });
-    }
-
-    // sort and remove dups
-    suites = removeDups(suites.sort());
-    return suites;
-  });
-}
-exports.getSuites = getSuites;
-
-const makeFilters = function makeFilters(options) {
-  options = options || {};
-
-  // A filter string is {fileNameRegex}[:{testNameRegex}] - ie, a colon
-  // optionally separates a regex for the test fileName from a regex for the
-  // testName.
-  if (options.filter) {
-    let colonPos = options.filter.indexOf(':');
-    let filterFileRegex, filterNameRegex;
-
-    if (colonPos === -1) {
-      filterFileRegex = new RegExp(options.filter);
-      filterNameRegex = { test: () => true }
-    }
-    else {
-      filterFileRegex = new RegExp(options.filter.substr(0, colonPos));
-      filterNameRegex = new RegExp(options.filter.substr(colonPos + 1));
-    }
-
-    return {
-      fileFilter: (name) => filterFileRegex.test(name),
-      testFilter: (name) => filterNameRegex.test(name)
-    }
-  }
-
-  return {
-    fileFilter: () => true,
-    testFilter: () => true
-  };
-}
-exports.makeFilters = makeFilters;
-
-var loader = Loader(module);
-const NOT_TESTS = ['setup', 'teardown'];
-
-var TestFinder = exports.TestFinder = function TestFinder(options) {
-  this.filter = options.filter;
-  this.testInProcess = options.testInProcess === false ? false : true;
-  this.testOutOfProcess = options.testOutOfProcess === true ? true : false;
-};
-
-TestFinder.prototype = {
-  findTests: function findTests() {
-    let { fileFilter, testFilter } = makeFilters({ filter: this.filter });
-
-    return getSuites({ id: id, filter: fileFilter }).then(suites => {
-      let testsRemaining = [];
-
-      let getNextTest = () => {
-        if (testsRemaining.length) {
-          return testsRemaining.shift();
-        }
-
-        if (!suites.length) {
-          return null;
-        }
-
-        let suite = suites.shift();
-
-        // Load each test file as a main module in its own loader instance
-        // `suite` is defined by cuddlefish/manifest.py:ManifestBuilder.build
-        let suiteModule;
-
-        try {
-          suiteModule = cuddlefish.main(loader, suite);
-        }
-        catch (e) {
-          if (/Unsupported Application/i.test(e.message)) {
-            // If `Unsupported Application` error thrown during test,
-            // skip the test suite
-            suiteModule = {
-              'test suite skipped': assert => assert.pass(e.message)
-            };
-          }
-          else {
-            console.exception(e);
-            throw e;
-          }
-        }
-
-        if (this.testInProcess) {
-          for (let name of Object.keys(suiteModule).sort()) {
-            if (NOT_TESTS.indexOf(name) === -1 && testFilter(name)) {
-              testsRemaining.push({
-                setup: suiteModule.setup,
-                teardown: suiteModule.teardown,
-                testFunction: suiteModule[name],
-                name: suite + "." + name
-              });
-            }
-          }
-        }
-
-        return getNextTest();
-      };
-
-      return {
-        getNext: () => resolve(getNextTest())
-      };
-    });
-  }
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ /dev/null
@@ -1,568 +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"
-};
-
-lazyRequireModule(this, "../timers", "timer");
-const cfxArgs = require("../test/options");
-lazyRequire(this, "../tabs/utils", "getTabs", "closeTab", "getURI", "getTabId", "getSelectedTab");
-lazyRequire(this, "../window/utils", "windows", "isBrowser", "getMostRecentBrowserWindow");
-const { defer, all, Debugging: PromiseDebugging, resolve } = require("../core/promise");
-lazyRequire(this, "../window/utils", "getInnerId");
-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
-  });
-  var runner = new TestRunner({fs: options.fs});
-  finder.findTests().then(tests => {
-    runner.startMany({
-      tests: tests,
-      stopOnError: options.stopOnError,
-      onDone: options.onDone
-    });
-  });
-};
-exports.findAndRunTests = findAndRunTests;
-
-var runnerWindows = new WeakMap();
-
-const TestRunner = function TestRunner(options) {
-  options = options || {};
-
-  // remember the id's for the open window and tab
-  let window = getMostRecentBrowserWindow();
-  runnerWindows.set(this, getInnerId(window));
-
-  this.fs = options.fs;
-  this.console = options.console || console;
-  this.passed = 0;
-  this.failed = 0;
-  this.testRunSummary = [];
-  this.expectFailNesting = 0;
-  this.done = TestRunner.prototype.done.bind(this);
-};
-
-TestRunner.prototype = {
-  toString: function toString() {
-    return "[object TestRunner]";
-  },
-
-  DEFAULT_PAUSE_TIMEOUT: (cfxArgs.parseable ? 300000 : 15000), //Five minutes (5*60*1000ms)
-  PAUSE_DELAY: 500,
-
-  _logTestFailed: function _logTestFailed(why) {
-    if (!(why in this.test.errors))
-      this.test.errors[why] = 0;
-    this.test.errors[why]++;
-  },
-
-  _uncaughtErrorObserver: function({message, date, fileName, stack, lineNumber}) {
-    this.fail("There was an uncaught Promise rejection: " + message + " @ " +
-              fileName + ":" + lineNumber + "\n" + stack);
-  },
-
-  pass: function pass(message) {
-    if(!this.expectFailure) {
-      if ("testMessage" in this.console)
-        this.console.testMessage(true, true, this.test.name, message);
-      else
-        this.console.info("pass:", message);
-      this.passed++;
-      this.test.passed++;
-      this.test.last = message;
-    }
-    else {
-      this.expectFailure = false;
-      this._logTestFailed("failure");
-      if ("testMessage" in this.console) {
-        this.console.testMessage(true, false, this.test.name, message);
-      }
-      else {
-        this.console.error("fail:", 'Failure Expected: ' + message)
-        this.console.trace();
-      }
-      this.failed++;
-      this.test.failed++;
-    }
-  },
-
-  fail: function fail(message) {
-    if(!this.expectFailure) {
-      this._logTestFailed("failure");
-      if ("testMessage" in this.console) {
-        this.console.testMessage(false, false, this.test.name, message);
-      }
-      else {
-        this.console.error("fail:", message)
-        this.console.trace();
-      }
-      this.failed++;
-      this.test.failed++;
-    }
-    else {
-      this.expectFailure = false;
-      if ("testMessage" in this.console)
-        this.console.testMessage(false, true, this.test.name, message);
-      else
-        this.console.info("pass:", message);
-      this.passed++;
-      this.test.passed++;
-      this.test.last = message;
-    }
-  },
-
-  expectFail: function(callback) {
-    this.expectFailure = true;
-    callback();
-    this.expectFailure = false;
-  },
-
-  exception: function exception(e) {
-    this._logTestFailed("exception");
-    if (cfxArgs.parseable)
-      this.console.print("TEST-UNEXPECTED-FAIL | " + this.test.name + " | " + e + "\n");
-    this.console.exception(e);
-    this.failed++;
-    this.test.failed++;
-  },
-
-  assertMatches: function assertMatches(string, regexp, message) {
-    if (regexp.test(string)) {
-      if (!message)
-        message = uneval(string) + " matches " + uneval(regexp);
-      this.pass(message);
-    } else {
-      var no = uneval(string) + " doesn't match " + uneval(regexp);
-      if (!message)
-        message = no;
-      else
-        message = message + " (" + no + ")";
-      this.fail(message);
-    }
-  },
-
-  assertRaises: function assertRaises(func, predicate, message) {
-    try {
-      func();
-      if (message)
-        this.fail(message + " (no exception thrown)");
-      else
-        this.fail("function failed to throw exception");
-    } catch (e) {
-      var errorMessage;
-      if (typeof(e) == "string")
-        errorMessage = e;
-      else
-        errorMessage = e.message;
-      if (typeof(predicate) == "string")
-        this.assertEqual(errorMessage, predicate, message);
-      else
-        this.assertMatches(errorMessage, predicate, message);
-    }
-  },
-
-  assert: function assert(a, message) {
-    if (!a) {
-      if (!message)
-        message = "assertion failed, value is " + a;
-      this.fail(message);
-    } else
-      this.pass(message || "assertion successful");
-  },
-
-  assertNotEqual: function assertNotEqual(a, b, message) {
-    if (a != b) {
-      if (!message)
-        message = "a != b != " + uneval(a);
-      this.pass(message);
-    } else {
-      var equality = uneval(a) + " == " + uneval(b);
-      if (!message)
-        message = equality;
-      else
-        message += " (" + equality + ")";
-      this.fail(message);
-    }
-  },
-
-  assertEqual: function assertEqual(a, b, message) {
-    if (a == b) {
-      if (!message)
-        message = "a == b == " + uneval(a);
-      this.pass(message);
-    } else {
-      var inequality = uneval(a) + " != " + uneval(b);
-      if (!message)
-        message = inequality;
-      else
-        message += " (" + inequality + ")";
-      this.fail(message);
-    }
-  },
-
-  assertNotStrictEqual: function assertNotStrictEqual(a, b, message) {
-    if (a !== b) {
-      if (!message)
-        message = "a !== b !== " + uneval(a);
-      this.pass(message);
-    } else {
-      var equality = uneval(a) + " === " + uneval(b);
-      if (!message)
-        message = equality;
-      else
-        message += " (" + equality + ")";
-      this.fail(message);
-    }
-  },
-
-  assertStrictEqual: function assertStrictEqual(a, b, message) {
-    if (a === b) {
-      if (!message)
-        message = "a === b === " + uneval(a);
-      this.pass(message);
-    } else {
-      var inequality = uneval(a) + " !== " + uneval(b);
-      if (!message)
-        message = inequality;
-      else
-        message += " (" + inequality + ")";
-      this.fail(message);
-    }
-  },
-
-  assertFunction: function assertFunction(a, message) {
-    this.assertStrictEqual('function', typeof a, message);
-  },
-
-  assertUndefined: function(a, message) {
-    this.assertStrictEqual('undefined', typeof a, message);
-  },
-
-  assertNotUndefined: function(a, message) {
-    this.assertNotStrictEqual('undefined', typeof a, message);
-  },
-
-  assertNull: function(a, message) {
-    this.assertStrictEqual(null, a, message);
-  },
-
-  assertNotNull: function(a, message) {
-    this.assertNotStrictEqual(null, a, message);
-  },
-
-  assertObject: function(a, message) {
-    this.assertStrictEqual('[object Object]', Object.prototype.toString.apply(a), message);
-  },
-
-  assertString: function(a, message) {
-    this.assertStrictEqual('[object String]', Object.prototype.toString.apply(a), message);
-  },
-
-  assertArray: function(a, message) {
-    this.assertStrictEqual('[object Array]', Object.prototype.toString.apply(a), message);
-  },
-
-  assertNumber: function(a, message) {
-    this.assertStrictEqual('[object Number]', Object.prototype.toString.apply(a), message);
-  },
-
-  done: function done() {
-    if (this.isDone) {
-      return resolve();
-    }
-
-    this.isDone = true;
-    this.pass("This test is done.");
-
-    if (this.test.teardown) {
-      this.test.teardown(this);
-    }
-
-    if (this.waitTimeout !== null) {
-      timer.clearTimeout(this.waitTimeout);
-      this.waitTimeout = null;
-    }
-
-    // Do not leave any callback set when calling to `waitUntil`
-    this.waitUntilCallback = null;
-    if (this.test.passed == 0 && this.test.failed == 0) {
-      this._logTestFailed("empty test");
-
-      if ("testMessage" in this.console) {
-        this.console.testMessage(false, false, this.test.name, "Empty test");
-      }
-      else {
-        this.console.error("fail:", "Empty test")
-      }
-
-      this.failed++;
-      this.test.failed++;
-    }
-
-    let wins = windows(null, { includePrivate: true });
-    let winPromises = wins.map(win => {
-      return new Promise(resolve => {
-        if (["interactive", "complete"].indexOf(win.document.readyState) >= 0) {
-          resolve()
-        }
-        else {
-          win.addEventListener("DOMContentLoaded", function() {
-            resolve();
-          }, {once: true});
-        }
-      });
-    });
-
-    PromiseDebugging.flushUncaughtErrors();
-    PromiseDebugging.removeUncaughtErrorObserver(this._uncaughtErrorObserver);
-
-
-    return all(winPromises).then(() => {
-      let browserWins = wins.filter(isBrowser);
-      let failure = false;
-
-      if (wins.length != 1 || getInnerId(wins[0]) !== runnerWindows.get(this)) {
-        failure = true;
-        this.fail("Should not be any unexpected windows open");
-      }
-
-      if (failure) {
-        console.log("Windows open:");
-        for (let win of wins) {
-          if (isBrowser(win)) {
-            tabs = [];
-            console.log(win.location + " - " + tabs.map(getURI).join(", "));
-          }
-          else {
-            console.log(win.location);
-          }
-        }
-      }
-
-      return failure;
-    }).
-    then(failure => {
-      if (!failure) {
-        this.pass("There was a clean UI.");
-        return null;
-      }
-      return cleanUI().then(() => {
-        this.pass("There is a clean UI.");
-      });
-    }).
-    then(() => {
-      this.testRunSummary.push({
-        name: this.test.name,
-        passed: this.test.passed,
-        failed: this.test.failed,
-        errors: Object.keys(this.test.errors).join(", ")
-      });
-
-      if (this.onDone !== null) {
-        let onDone = this.onDone;
-        this.onDone = null;
-        timer.setTimeout(_ => onDone(this));
-      }
-    }).
-    catch(console.exception);
-  },
-
-  // Set of assertion functions to wait for an assertion to become true
-  // These functions take the same arguments as the TestRunner.assert* methods.
-  waitUntil: function waitUntil() {
-    return this._waitUntil(this.assert, arguments);
-  },
-
-  waitUntilNotEqual: function waitUntilNotEqual() {
-    return this._waitUntil(this.assertNotEqual, arguments);
-  },
-
-  waitUntilEqual: function waitUntilEqual() {
-    return this._waitUntil(this.assertEqual, arguments);
-  },
-
-  waitUntilMatches: function waitUntilMatches() {
-    return this._waitUntil(this.assertMatches, arguments);
-  },
-
-  /**
-   * Internal function that waits for an assertion to become true.
-   * @param {Function} assertionMethod
-   *    Reference to a TestRunner assertion method like test.assert,
-   *    test.assertEqual, ...
-   * @param {Array} args
-   *    List of arguments to give to the previous assertion method.
-   *    All functions in this list are going to be called to retrieve current
-   *    assertion values.
-   */
-  _waitUntil: function waitUntil(assertionMethod, args) {
-    let { promise, resolve } = defer();
-    let count = 0;
-    let maxCount = this.DEFAULT_PAUSE_TIMEOUT / this.PAUSE_DELAY;
-
-    // We need to ensure that test is asynchronous
-    if (!this.waitTimeout)
-      this.waitUntilDone(this.DEFAULT_PAUSE_TIMEOUT);
-
-    let finished = false;
-    let test = this;
-
-    // capture a traceback before we go async.
-    let traceback = require("../console/traceback");
-    let stack = traceback.get();
-    stack.splice(-2, 2);
-    let currentWaitStack = traceback.format(stack);
-    let timeout = null;
-
-    function loop(stopIt) {
-      timeout = null;
-
-      // Build a mockup object to fake TestRunner API and intercept calls to
-      // pass and fail methods, in order to retrieve nice error messages
-      // and assertion result
-      let mock = {
-        pass: function (msg) {
-          test.pass(msg);
-          test.waitUntilCallback = null;
-          if (!stopIt)
-            resolve();
-        },
-        fail: function (msg) {
-          // If we are called on test timeout, we stop the loop
-          // and print which test keeps failing:
-          if (stopIt) {
-            test.console.error("test assertion never became true:\n",
-                               msg + "\n",
-                               currentWaitStack);
-            if (timeout)
-              timer.clearTimeout(timeout);
-            return;
-          }
-          timeout = timer.setTimeout(loop, test.PAUSE_DELAY);
-        }
-      };
-
-      // Automatically call args closures in order to build arguments for
-      // assertion function
-      let appliedArgs = [];
-      for (let i = 0, l = args.length; i < l; i++) {
-        let a = args[i];
-        if (typeof a == "function") {
-          try {
-            a = a();
-          }
-          catch(e) {
-            test.fail("Exception when calling asynchronous assertion: " + e +
-                      "\n" + e.stack);
-            return resolve();
-          }
-        }
-        appliedArgs.push(a);
-      }
-
-      // Finally call assertion function with current assertion values
-      assertionMethod.apply(mock, appliedArgs);
-    }
-    loop();
-    this.waitUntilCallback = loop;
-
-    return promise;
-  },
-
-  waitUntilDone: function waitUntilDone(ms) {
-    if (ms === undefined)
-      ms = this.DEFAULT_PAUSE_TIMEOUT;
-
-    var self = this;
-
-    function tiredOfWaiting() {
-      self._logTestFailed("timed out");
-      if ("testMessage" in self.console) {
-        self.console.testMessage(false, false, self.test.name,
-          `Test timed out (after: ${self.test.last})`);
-      }
-      else {
-        self.console.error("fail:", `Timed out (after: ${self.test.last})`)
-      }
-      if (self.waitUntilCallback) {
-        self.waitUntilCallback(true);
-        self.waitUntilCallback = null;
-      }
-      self.failed++;
-      self.test.failed++;
-      self.done();
-    }
-
-    // We may already have registered a timeout callback
-    if (this.waitTimeout)
-      timer.clearTimeout(this.waitTimeout);
-
-    this.waitTimeout = timer.setTimeout(tiredOfWaiting, ms);
-  },
-
-  startMany: function startMany(options) {
-    function runNextTest(self) {
-      let { tests, onDone } = options;
-
-      return tests.getNext().then((test) => {
-        if (options.stopOnError && self.test && self.test.failed) {
-          self.console.error("aborted: test failed and --stop-on-error was specified");
-          onDone(self);
-        }
-        else if (test) {
-          self.start({test: test, onDone: runNextTest});
-        }
-        else {
-          onDone(self);
-        }
-      });
-    }
-
-    return runNextTest(this).catch(console.exception);
-  },
-
-  start: function start(options) {
-    this.test = options.test;
-    this.test.passed = 0;
-    this.test.failed = 0;
-    this.test.errors = {};
-    this.test.last = 'START';
-    PromiseDebugging.clearUncaughtErrorObservers();
-    this._uncaughtErrorObserver = this._uncaughtErrorObserver.bind(this);
-    PromiseDebugging.addUncaughtErrorObserver(this._uncaughtErrorObserver);
-
-    this.isDone = false;
-    this.onDone = function(self) {
-      if (cfxArgs.parseable)
-        self.console.print("TEST-END | " + self.test.name + "\n");
-      options.onDone(self);
-    }
-    this.waitTimeout = null;
-
-    try {
-      if (cfxArgs.parseable)
-        this.console.print("TEST-START | " + this.test.name + "\n");
-      else
-        this.console.info("executing '" + this.test.name + "'");
-
-      if(this.test.setup) {
-        this.test.setup(this);
-      }
-      this.test.testFunction(this);
-    } catch (e) {
-      this.exception(e);
-    }
-    if (this.waitTimeout === null)
-      this.done();
-  }
-};
-exports.TestRunner = TestRunner;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/window-utils.js
+++ /dev/null
@@ -1,193 +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 { Cc, Ci } = require('chrome');
-const events = require('../system/events');
-const { getInnerId, getOuterId, windows, isDocumentLoaded, isBrowser,
-        getMostRecentBrowserWindow, getToplevelWindow, getMostRecentWindow } = require('../window/utils');
-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);
-
-// Bug 834961: ignore private windows when they are not supported
-function getWindows() {
-  return windows(null, { includePrivate: isPrivateBrowsingSupported });
-}
-
-/**
- * An iterator for XUL windows currently in the application.
- *
- * @return A generator that yields XUL windows exposing the
- *         nsIDOMWindow interface.
- */
-function* windowIterator() {
-  // Bug 752631: We only pass already loaded window in order to avoid
-  // breaking XUL windows DOM. DOM is broken when some JS code try
-  // to access DOM during "uninitialized" state of the related document.
-  let list = getWindows().filter(isDocumentLoaded);
-  for (let i = 0, l = list.length; i < l; i++) {
-    yield list[i];
-  }
-};
-exports.windowIterator = windowIterator;
-
-/**
- * An iterator for browser windows currently open in the application.
- * @returns {Function}
- *    A generator that yields browser windows exposing the `nsIDOMWindow`
- *    interface.
- */
-function* browserWindowIterator() {
-  for (let window of windowIterator()) {
-    if (isBrowser(window))
-      yield window;
-  }
-}
-exports.browserWindowIterator = browserWindowIterator;
-
-function WindowTracker(delegate) {
-   if (!(this instanceof WindowTracker)) {
-     return new WindowTracker(delegate);
-   }
-
-  this._delegate = delegate;
-
-  for (let window of getWindows())
-    this._regWindow(window);
-  windowWatcher.registerNotification(this);
-  this._onToplevelWindowReady = this._onToplevelWindowReady.bind(this);
-  events.on('toplevel-window-ready', this._onToplevelWindowReady);
-
-  require('../system/unload').ensure(this);
-
-  return this;
-};
-
-WindowTracker.prototype = {
-  _regLoadingWindow: function _regLoadingWindow(window) {
-    // Bug 834961: ignore private windows when they are not supported
-    if (ignoreWindow(window))
-      return;
-
-    window.addEventListener('load', this, true);
-  },
-
-  _unregLoadingWindow: function _unregLoadingWindow(window) {
-    // This may have no effect if we ignored the window in _regLoadingWindow().
-    window.removeEventListener('load', this, true);
-  },
-
-  _regWindow: function _regWindow(window) {
-    // Bug 834961: ignore private windows when they are not supported
-    if (ignoreWindow(window))
-      return;
-
-    if (window.document.readyState == 'complete') {
-      this._unregLoadingWindow(window);
-      this._delegate.onTrack(window);
-    } else
-      this._regLoadingWindow(window);
-  },
-
-  _unregWindow: function _unregWindow(window) {
-    if (window.document.readyState == 'complete') {
-      if (this._delegate.onUntrack)
-        this._delegate.onUntrack(window);
-    } else {
-      this._unregLoadingWindow(window);
-    }
-  },
-
-  unload: function unload() {
-    windowWatcher.unregisterNotification(this);
-    events.off('toplevel-window-ready', this._onToplevelWindowReady);
-    for (let window of getWindows())
-      this._unregWindow(window);
-  },
-
-  handleEvent: function handleEvent(event) {
-    try {
-      if (event.type == 'load' && event.target) {
-        var window = event.target.defaultView;
-        if (window)
-          this._regWindow(getToplevelWindow(window));
-      }
-    }
-    catch(e) {
-      console.exception(e);
-    }
-  },
-
-  _onToplevelWindowReady: function _onToplevelWindowReady({subject}) {
-    let window = getToplevelWindow(subject);
-    // ignore private windows if they are not supported
-    if (ignoreWindow(window))
-      return;
-    this._regWindow(window);
-  },
-
-  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;
-
-Object.defineProperties(exports, {
-  activeWindow: {
-    enumerable: true,
-    get: function() {
-      return getMostRecentWindow(null);
-    },
-    set: function(window) {
-      try {
-        window.focus();
-      } catch (e) {}
-    }
-  },
-  activeBrowserWindow: {
-    enumerable: true,
-    get: getMostRecentBrowserWindow
-  }
-});
-
-
-/**
- * Returns the ID of the window's current inner window.
- */
-exports.getInnerId = deprecateFunction(getInnerId,
-  'require("window-utils").getInnerId is deprecated, ' +
-  'please use require("sdk/window/utils").getInnerId instead'
-);
-
-exports.getOuterId = deprecateFunction(getOuterId,
-  'require("window-utils").getOuterId is deprecated, ' +
-  'please use require("sdk/window/utils").getOuterId instead'
-);
-
-exports.isBrowser = deprecateFunction(isBrowser,
-  'require("window-utils").isBrowser is deprecated, ' +
-  'please use require("sdk/window/utils").isBrowser instead'
-);
-
-exports.hiddenWindow = appShellService.hiddenDOMWindow;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/event/chrome.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci, Cr, Cu } = require("chrome");
-const { emit, on, off } = require("./core");
-var observerService = Cc["@mozilla.org/observer-service;1"]
-                      .getService(Ci.nsIObserverService);
-
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
-const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
-
-const { when: unload } = require("../system/unload");
-
-// Simple class that can be used to instantiate event channel that
-// implements `nsIObserver` interface. It's will is used by `observe`
-// function as observer + event target. It basically proxies observer
-// notifications as to it's registered listeners.
-function ObserverChannel() {}
-Object.freeze(Object.defineProperties(ObserverChannel.prototype, {
-  QueryInterface: {
-    value: function(iid) {
-      if (!iid.equals(Ci.nsIObserver) &&
-          !iid.equals(Ci.nsISupportsWeakReference) &&
-          !iid.equals(Ci.nsISupports))
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      return this;
-    }
-  },
-  observe: {
-    value: function(subject, topic, data) {
-      emit(this, "data", {
-        type: topic,
-        target: subject,
-        data: data
-      });
-    }
-  }
-}));
-
-function observe(topic) {
-  let observerChannel = new ObserverChannel();
-
-  // Note: `nsIObserverService` will not hold a weak reference to a
-  // observerChannel (since third argument is `true`). There for if it
-  // will be GC-ed with all it's event listeners once no other references
-  // will be held.
-  addObserver(observerChannel, topic, true);
-
-  // We need to remove any observer added once the add-on is unloaded;
-  // otherwise we'll get a "dead object" exception.
-  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1001833
-  unload(() => removeObserver(observerChannel, topic));
-
-  return observerChannel;
-}
-
-exports.observe = observe;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/event/core.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.';
-const BAD_LISTENER = 'The event listener must be a function.';
-
-const { DefaultMap, DefaultWeakMap } = require('../util/object');
-
-const EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/;
-exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN;
-
-// Count of total listeners ever added.
-// This is used to keep track of when a listener was added, which can
-// have an effect on when it is and isn't dispatched. See comments in
-// emitOnObject for more details.
-let listenerCount = 0;
-
-const observers = new DefaultWeakMap(() => {
-  return new DefaultMap(() => new Map());
-});
-
-/**
- * Registers an event `listener` that is called every time events of
- * specified `type` is emitted on the given event `target`.
- * @param {Object} target
- *    Event target object.
- * @param {String} type
- *    The type of event.
- * @param {Function} listener
- *    The listener function that processes the event.
- */
-function on(target, type, listener) {
-  if (typeof(listener) !== 'function')
-    throw new Error(BAD_LISTENER);
-
-  observers.get(target).get(type).set(listener, listenerCount++);
-}
-exports.on = on;
-
-
-// Map of wrapper functions for listeners added using `once`.
-var onceWeakMap = new WeakMap();
-
-/**
- * Registers an event `listener` that is called only the next time an event
- * of the specified `type` is emitted on the given event `target`.
- * @param {Object} target
- *    Event target object.
- * @param {String} type
- *    The type of the event.
- * @param {Function} listener
- *    The listener function that processes the event.
- */
-function once(target, type, listener) {
-  function replacement(...args) {
-    off(target, type, replacement);
-    onceWeakMap.delete(listener);
-    listener.apply(target, args);
-  };
-  onceWeakMap.set(listener, replacement);
-  on(target, type, replacement);
-}
-exports.once = once;
-
-/**
- * Execute each of the listeners in order with the supplied arguments.
- * 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 be logged into an
- * error console.
- * @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 allListeners = observers.get(target);
-  let listeners = allListeners.get(type);
-
-  // If error event and there are no handlers (explicit or catch-all)
-  // then print error message to the console.
-  if (type === 'error' && !listeners.size && !allListeners.get('*').size)
-    console.exception(args[0]);
-
-  let count = listenerCount;
-  for (let [listener, added] of listeners)
-    try {
-      // Since our contract unfortunately requires that we not dispatch to
-      // this event to listeners that were either added or removed during this
-      // dispatch, we need to check when each listener was added.
-      if (added >= count)
-        break;
-      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')
-        emitOnObject(target, 'error', target, error);
-      else
-        console.exception(error);
-    }
-
-  // Also emit on `"*"` so that one could listen for all events.
-  if (type !== '*' && allListeners.get('*').size)
-    emitOnObject(target, '*', target, type, ...args);
-}
-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.
- * @param {String} type
- *    The type of event.
- * @param {Function} listener
- *    The listener function that processes the event.
- */
-function off(target, type, listener) {
-  let length = arguments.length;
-  if (length === 3) {
-    if (onceWeakMap.has(listener)) {
-      observers.get(target).get(type)
-               .delete(onceWeakMap.get(listener));
-      onceWeakMap.delete(listener);
-    }
-
-    observers.get(target).get(type).delete(listener);
-  }
-  else if (length === 2) {
-    observers.get(target).get(type).clear();
-    observers.get(target).delete(type);
-  }
-  else if (length === 1) {
-    for (let listeners of observers.get(target).values())
-      listeners.clear();
-    observers.delete(target);
-  }
-}
-exports.off = off;
-
-/**
- * Returns a number of event listeners registered for the given event `type`
- * on the given event `target`.
- */
-function count(target, type) {
-  return observers.get(target).get(type).size;
-}
-exports.count = count;
-
-/**
- * Registers listeners on the given event `target` from the given `listeners`
- * dictionary. Iterates over the listeners and if property name matches name
- * pattern `onEventType` and property is a function, then registers it as
- * an `eventType` listener on `target`.
- *
- * @param {Object} target
- *    The type of event.
- * @param {Object} listeners
- *    Dictionary of listeners.
- */
-function setListeners(target, listeners) {
-  Object.keys(listeners || {}).forEach(key => {
-    let match = EVENT_TYPE_PATTERN.exec(key);
-    let type = match && match[1].toLowerCase();
-    if (!type)
-      return;
-
-    let listener = listeners[key];
-    if (typeof(listener) === 'function')
-      on(target, type, listener);
-  });
-}
-exports.setListeners = setListeners;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/event/dom.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Ci } = require("chrome");
-
-lazyRequire(this, "./core", "emit");
-var { when: unload } = require("../system/unload");
-var listeners = new WeakMap();
-
-const { Cu } = require("chrome");
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const { ThreadSafeChromeUtils } = Cu.import("resource://gre/modules/Services.jsm", {});
-
-var getWindowFrom = x =>
-                    x instanceof Ci.nsIDOMWindow ? x :
-                    x instanceof Ci.nsIDOMDocument ? x.defaultView :
-                    x instanceof Ci.nsIDOMNode ? x.ownerGlobal :
-                    null;
-
-function removeFromListeners() {
-  ShimWaiver.getProperty(this, "removeEventListener")("DOMWindowClose", removeFromListeners);
-  for (let cleaner of listeners.get(this))
-    cleaner();
-
-  listeners.delete(this);
-}
-
-// Simple utility function takes event target, event type and optional
-// `options.capture` and returns node style event stream that emits "data"
-// events every time event of that type occurs on the given `target`.
-function open(target, type, options) {
-  let output = {};
-  let capture = options && options.capture ? true : false;
-  let listener = (event) => emit(output, "data", event);
-
-  // `open` is currently used only on DOM Window objects, however it was made
-  // to be used to any kind of `target` that supports `addEventListener`,
-  // therefore is safer get the `window` from the `target` instead assuming
-  // that `target` is the `window`.
-  let window = getWindowFrom(target);
-
-  // If we're not able to get a `window` from `target`, there is something
-  // wrong. We cannot add listeners that can leak later, or results in
-  // "dead object" exception.
-  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1001833
-  if (!window)
-    throw new Error("Unable to obtain the owner window from the target given.");
-
-  let cleaners = listeners.get(window);
-  if (!cleaners) {
-    cleaners = [];
-    listeners.set(window, cleaners);
-
-    // We need to remove from our map the `window` once is closed, to prevent
-    // memory leak
-    ShimWaiver.getProperty(window, "addEventListener")("DOMWindowClose", removeFromListeners);
-  }
-
-  cleaners.push(() => ShimWaiver.getProperty(target, "removeEventListener")(type, listener, capture));
-  ShimWaiver.getProperty(target, "addEventListener")(type, listener, capture);
-
-  return output;
-}
-
-unload(() => {
-  let keys = ThreadSafeChromeUtils.nondeterministicGetWeakMapKeys(listeners)
-  for (let window of keys)
-    removeFromListeners.call(window);
-});
-
-exports.open = open;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/event/target.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  "stability": "stable"
-};
-
-const { on, once, off, setListeners } = require('./core');
-const { method, chainable } = require('../lang/functional/core');
-const { Class } = require('../core/heritage');
-
-/**
- * `EventTarget` is an exemplar for creating an objects that can be used to
- * add / remove event listeners on them. Events on these objects may be emitted
- * via `emit` function exported by 'event/core' module.
- */
-const EventTarget = Class({
-  /**
-   * Method initializes `this` event source. It goes through properties of a
-   * given `options` and registers listeners for the ones that look like an
-   * event listeners.
-   */
-  /**
-   * Method initializes `this` event source. It goes through properties of a
-   * given `options` and registers listeners for the ones that look like an
-   * event listeners.
-   */
-  initialize: function initialize(options) {
-    setListeners(this, options);
-  },
-  /**
-   * 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: chainable(method(on)),
-  /**
-   * 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: chainable(method(once)),
-  /**
-   * Removes an event `listener` for the given event `type`.
-   * @param {String} type
-   *    The type of event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   */
-  removeListener: function removeListener(type, listener) {
-    // Note: We can't just wrap `off` in `method` as we do it for other methods
-    // cause skipping a second or third argument will behave very differently
-    // than intended. This way we make sure all arguments are passed and only
-    // one listener is removed at most.
-    off(this, type, listener);
-    return this;
-  },
-  // but we can wrap `off` here, as the semantics are the same
-  off: chainable(method(off))
-
-});
-exports.EventTarget = EventTarget;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/event/utils.js
+++ /dev/null
@@ -1,328 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-lazyRequire(this, "./core", "emit", "on", "once", "off", "EVENT_TYPE_PATTERN");
-const { Cu } = require("chrome");
-
-// This module provides set of high order function for working with event
-// streams (streams in a NodeJS style that dispatch data, end and error
-// events).
-
-// Function takes a `target` object and returns set of implicit references
-// (non property references) it keeps. This basically allows defining
-// references between objects without storing the explicitly. See transform for
-// more details.
-var refs = (function() {
-  let refSets = new WeakMap();
-  return function refs(target) {
-    if (!refSets.has(target)) refSets.set(target, new Set());
-    return refSets.get(target);
-  };
-})();
-
-function transform(input, f) {
-  let output = new Output();
-
-  // Since event listeners don't prevent `input` to be GC-ed we wanna presrve
-  // it until `output` can be GC-ed. There for we add implicit reference which
-  // is removed once `input` ends.
-  refs(output).add(input);
-
-  const next = data => receive(output, data);
-  once(output, "start", () => start(input));
-  on(input, "error", error => emit(output, "error", error));
-  on(input, "end", function() {
-    refs(output).delete(input);
-    end(output);
-  });
-  on(input, "data", data => f(data, next));
-  return output;
-}
-
-// High order event transformation function that takes `input` event channel
-// and returns transformation containing only events on which `p` predicate
-// returns `true`.
-function filter(input, predicate) {
-  return transform(input, function(data, next) {
-    if (predicate(data))
-      next(data);
-  });
-}
-exports.filter = filter;
-
-// High order function that takes `input` and returns input of it's values
-// mapped via given `f` function.
-const map = (input, f) => transform(input, (data, next) => next(f(data)));
-exports.map = map;
-
-// High order function that takes `input` stream of streams and merges them
-// into single event stream. Like flatten but time based rather than order
-// based.
-function merge(inputs) {
-  let output = new Output();
-  let open = 1;
-  let state = [];
-  output.state = state;
-  refs(output).add(inputs);
-
-  function end(input) {
-    open = open - 1;
-    refs(output).delete(input);
-    if (open === 0) emit(output, "end");
-  }
-  const error = e => emit(output, "error", e);
-  function forward(input) {
-    state.push(input);
-    open = open + 1;
-    on(input, "end", () => end(input));
-    on(input, "error", error);
-    on(input, "data", data => emit(output, "data", data));
-  }
-
-  // If `inputs` is an array treat it as a stream.
-  if (Array.isArray(inputs)) {
-    inputs.forEach(forward);
-    end(inputs);
-  }
-  else {
-    on(inputs, "end", () => end(inputs));
-    on(inputs, "error", error);
-    on(inputs, "data", forward);
-  }
-
-  return output;
-}
-exports.merge = merge;
-
-const expand = (inputs, f) => merge(map(inputs, f));
-exports.expand = expand;
-
-const pipe = (from, to) => on(from, "*", emit.bind(emit, to));
-exports.pipe = pipe;
-
-
-// Shim signal APIs so other modules can be used as is.
-const receive = (input, message) => {
-  if (input[receive])
-    input[receive](input, message);
-  else
-    emit(input, "data", message);
-
-  // Ideally our input will extend Input and already provide a weak value
-  // getter.  If not, opportunistically shim the weak value getter on
-  // other types passed as the input.
-  if (!("value" in input)) {
-    Object.defineProperty(input, "value", WeakValueGetterSetter);
-  }
-  input.value = message;
-};
-receive.toString = () => "@@receive";
-exports.receive = receive;
-exports.send = receive;
-
-const end = input => {
-  if (input[end])
-    input[end](input);
-  else
-    emit(input, "end", input);
-};
-end.toString = () => "@@end";
-exports.end = end;
-
-const stop = input => {
-  if (input[stop])
-    input[stop](input);
-  else
-    emit(input, "stop", input);
-};
-stop.toString = () => "@@stop";
-exports.stop = stop;
-
-const start = input => {
-  if (input[start])
-    input[start](input);
-  else
-    emit(input, "start", input);
-};
-start.toString = () => "@@start";
-exports.start = start;
-
-const lift = (step, ...inputs) => {
-  let args = null;
-  let opened = inputs.length;
-  let started = false;
-  const output = new Output();
-  const init = () => {
-    args = [...inputs.map(input => input.value)];
-    output.value = step(...args);
-  };
-
-  inputs.forEach((input, index) => {
-    on(input, "data", data => {
-      args[index] = data;
-      receive(output, step(...args));
-    });
-    on(input, "end", () => {
-      opened = opened - 1;
-      if (opened <= 0)
-        end(output);
-    });
-  });
-
-  once(output, "start", () => {
-    inputs.forEach(start);
-    init();
-  });
-
-  init();
-
-  return output;
-};
-exports.lift = lift;
-
-const merges = inputs => {
-  let opened = inputs.length;
-  let output = new Output();
-  output.value = inputs[0].value;
-  inputs.forEach((input, index) => {
-    on(input, "data", data => receive(output, data));
-    on(input, "end", () => {
-      opened = opened - 1;
-      if (opened <= 0)
-        end(output);
-    });
-  });
-
-  once(output, "start", () => {
-    inputs.forEach(start);
-    output.value = inputs[0].value;
-  });
-
-  return output;
-};
-exports.merges = merges;
-
-const foldp = (step, initial, input) => {
-  let output = map(input, x => step(output.value, x));
-  output.value = initial;
-  return output;
-};
-exports.foldp = foldp;
-
-const keepIf = (p, base, input) => {
-  let output = filter(input, p);
-  output.value = base;
-  return output;
-};
-exports.keepIf = keepIf;
-
-function Input() {}
-Input.start = input => emit(input, "start", input);
-Input.prototype.start = Input.start;
-
-Input.end = input => {
-  emit(input, "end", input);
-  stop(input);
-};
-Input.prototype[end] = Input.end;
-
-// The event channel system caches the last event seen as input.value.
-// Unfortunately, if the last event is a DOM object this is a great way
-// leak windows.  Mitigate this by storing input.value using a weak
-// reference.  This allows the system to work for normal event processing
-// while also allowing the objects to be reclaimed.  It means, however,
-// input.value cannot be accessed long after the event was dispatched.
-const WeakValueGetterSetter = {
-  get: function() {
-    return this._weakValue ? this._weakValue.get() : this._simpleValue
-  },
-  set: function(v) {
-    if (v && typeof v === "object") {
-      try {
-        // Try to set a weak reference.  This can throw for some values.
-        // For example, if the value is a native object that does not
-        // implement nsISupportsWeakReference.
-        this._weakValue = Cu.getWeakReference(v)
-        this._simpleValue = undefined;
-        return;
-      } catch (e) {
-        // Do nothing.  Fall through to setting _simpleValue below.
-      }
-    }
-    this._simpleValue = v;
-    this._weakValue = undefined;
-  },
-}
-Object.defineProperty(Input.prototype, "value", WeakValueGetterSetter);
-
-exports.Input = Input;
-
-// Define an Output type with a weak value getter for the transformation
-// functions that produce new channels.
-function Output() { }
-Object.defineProperty(Output.prototype, "value", WeakValueGetterSetter);
-exports.Output = Output;
-
-const $source = "@@source";
-const $outputs = "@@outputs";
-exports.outputs = $outputs;
-
-// NOTE: Passing DOM objects through a Reactor can cause them to leak
-// when they get cached in this.value.  We cannot use a weak reference
-// in this case because the Reactor design expects to always have both the
-// past and present value.  If we allow past values to be collected the
-// system breaks.
-
-function Reactor(options={}) {
-  const {onStep, onStart, onEnd} = options;
-  if (onStep)
-    this.onStep = onStep;
-  if (onStart)
-    this.onStart = onStart;
-  if (onEnd)
-    this.onEnd = onEnd;
-}
-Reactor.prototype.onStep = _ => void(0);
-Reactor.prototype.onStart = _ => void(0);
-Reactor.prototype.onEnd = _ => void(0);
-Reactor.prototype.onNext = function(present, past) {
-  this.value = present;
-  this.onStep(present, past);
-};
-Reactor.prototype.run = function(input) {
-  on(input, "data", message => this.onNext(message, input.value));
-  on(input, "end", () => this.onEnd(input.value));
-  start(input);
-  this.value = input.value;
-  this.onStart(input.value);
-};
-exports.Reactor = Reactor;
-
-/**
- * Takes an object used as options with potential keys like 'onMessage',
- * used to be called `require('sdk/event/core').setListeners` on.
- * This strips all keys that would trigger a listener to be set.
- *
- * @params {Object} object
- * @return {Object}
- */
-
-function stripListeners (object) {
-  return Object.keys(object || {}).reduce((agg, key) => {
-    if (!EVENT_TYPE_PATTERN.test(key))
-      agg[key] = object[key];
-    return agg;
-  }, {});
-}
-exports.stripListeners = stripListeners;
-
-const when = (target, type) => new Promise(resolve => {
-  once(target, type, resolve);
-});
-exports.when = when;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/frame/utils.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Ci } = require("chrome");
-const XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-
-function eventTarget(frame) {
-  return getDocShell(frame).chromeEventHandler;
-}
-exports.eventTarget = eventTarget;
-
-function getDocShell(frame) {
-  let { frameLoader } = frame.QueryInterface(Ci.nsIFrameLoaderOwner);
-  return frameLoader && frameLoader.docShell;
-}
-exports.getDocShell = getDocShell;
-
-/**
- * Creates a XUL `browser` element in a privileged document.
- * @params {nsIDOMDocument} document
- * @params {String} options.type
- *    By default is 'content' for possible values see:
- *    https://developer.mozilla.org/en/XUL/iframe#a-browser.type
- * @params {String} options.uri
- *    URI of the document to be loaded into created frame.
- * @params {Boolean} options.remote
- *    If `true` separate process will be used for this frame, also in such
- *    case all the following options are ignored.
- * @params {Boolean} options.allowAuth
- *    Whether to allow auth dialogs. Defaults to `false`.
- * @params {Boolean} options.allowJavascript
- *    Whether to allow Javascript execution. Defaults to `false`.
- * @params {Boolean} options.allowPlugins
- *    Whether to allow plugin execution. Defaults to `false`.
- */
-function create(target, options) {
-  target = target instanceof Ci.nsIDOMDocument ? target.documentElement :
-           target instanceof Ci.nsIDOMWindow ? target.document.documentElement :
-           target;
-  options = options || {};
-  let remote = options.remote || false;
-  let namespaceURI = options.namespaceURI || XUL;
-  let isXUL = namespaceURI === XUL;
-  let nodeName = isXUL && options.browser ? 'browser' : 'iframe';
-  let document = target.ownerDocument;
-
-  let frame = document.createElementNS(namespaceURI, nodeName);
-  // Type="content" is mandatory to enable stuff here:
-  // http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsFrameLoader.cpp#1776
-  frame.setAttribute('type', options.type || 'content');
-  frame.setAttribute('src', options.uri || 'about:blank');
-
-  // Must set the remote attribute before attaching the frame to the document
-  if (remote && isXUL) {
-    // We remove XBL binding to avoid execution of code that is not going to
-    // work because browser has no docShell attribute in remote mode
-    // (for example)
-    frame.setAttribute('style', '-moz-binding: none;');
-    frame.setAttribute('remote', 'true');
-  }
-
-  target.appendChild(frame);
-
-  // Load in separate process if `options.remote` is `true`.
-  // http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsFrameLoader.cpp#1347
-  if (remote && !isXUL) {
-    frame.QueryInterface(Ci.nsIMozBrowserFrame);
-    frame.createRemoteFrameLoader(null);
-  }
-
-  // If browser is remote it won't have a `docShell`.
-  if (!remote) {
-    let docShell = getDocShell(frame);
-    docShell.allowAuth = options.allowAuth || false;
-    docShell.allowJavascript = options.allowJavascript || false;
-    docShell.allowPlugins = options.allowPlugins || false;
-    docShell.allowWindowControl = options.allowWindowControl || false;
-  }
-
-  return frame;
-}
-exports.create = create;
-
-function swapFrameLoaders(from, to) {
-  return from.QueryInterface(Ci.nsIFrameLoaderOwner).swapFrameLoaders(to);
-}
-exports.swapFrameLoaders = swapFrameLoaders;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/io/file.js
+++ /dev/null
@@ -1,197 +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 {Cc,Ci,Cr} = require("chrome");
-
-lazyRequireModule(this, "./byte-streams", "byteStreams");
-lazyRequireModule(this, "./text-streams", "textStreams");
-
-// Flags passed when opening a file.  See nsprpub/pr/include/prio.h.
-const OPEN_FLAGS = {
-  RDONLY: parseInt("0x01"),
-  WRONLY: parseInt("0x02"),
-  CREATE_FILE: parseInt("0x08"),
-  APPEND: parseInt("0x10"),
-  TRUNCATE: parseInt("0x20"),
-  EXCL: parseInt("0x80")
-};
-
-var dirsvc = Cc["@mozilla.org/file/directory_service;1"]
-             .getService(Ci.nsIProperties);
-
-function MozFile(path) {
-  var file = Cc['@mozilla.org/file/local;1']
-             .createInstance(Ci.nsIFile);
-  file.initWithPath(path);
-  return file;
-}
-
-function ensureReadable(file) {
-  if (!file.isReadable())
-    throw new Error("path is not readable: " + file.path);
-}
-
-function ensureDir(file) {
-  ensureExists(file);
-  if (!file.isDirectory())
-    throw new Error("path is not a directory: " + file.path);
-}
-
-function ensureFile(file) {
-  ensureExists(file);
-  if (!file.isFile())
-    throw new Error("path is not a file: " + file.path);
-}
-
-function ensureExists(file) {
-  if (!file.exists())
-    throw friendlyError(Cr.NS_ERROR_FILE_NOT_FOUND, file.path);
-}
-
-function friendlyError(errOrResult, filename) {
-  var isResult = typeof(errOrResult) === "number";
-  var result = isResult ? errOrResult : errOrResult.result;
-  switch (result) {
-  case Cr.NS_ERROR_FILE_NOT_FOUND:
-    return new Error("path does not exist: " + filename);
-  }
-  return isResult ? new Error("XPCOM error code: " + errOrResult) : errOrResult;
-}
-
-exports.exists = function exists(filename) {
-  return MozFile(filename).exists();
-};
-
-exports.isFile = function isFile(filename) {
-  return MozFile(filename).isFile();
-};
-
-exports.read = function read(filename, mode) {
-  if (typeof(mode) !== "string")
-    mode = "";
-
-  // Ensure mode is read-only.
-  mode = /b/.test(mode) ? "b" : "";
-
-  var stream = exports.open(filename, mode);
-  try {
-    var str = stream.read();
-  }
-  finally {
-    stream.close();
-  }
-
-  return str;
-};
-
-exports.join = function join(base) {
-  if (arguments.length < 2)
-    throw new Error("need at least 2 args");
-  base = MozFile(base);
-  for (var i = 1; i < arguments.length; i++)
-    base.append(arguments[i]);
-  return base.path;
-};
-
-exports.dirname = function dirname(path) {
-  var parent = MozFile(path).parent;
-  return parent ? parent.path : "";
-};
-
-exports.basename = function basename(path) {
-  var leafName = MozFile(path).leafName;
-
-  // On Windows, leafName when the path is a volume letter and colon ("c:") is
-  // the path itself.  But such a path has no basename, so we want the empty
-  // string.
-  return leafName == path ? "" : leafName;
-};
-
-exports.list = function list(path) {
-  var file = MozFile(path);
-  ensureDir(file);
-  ensureReadable(file);
-
-  var entries = file.directoryEntries;
-  var entryNames = [];
-  while(entries.hasMoreElements()) {
-    var entry = entries.getNext();
-    entry.QueryInterface(Ci.nsIFile);
-    entryNames.push(entry.leafName);
-  }
-  return entryNames;
-};
-
-exports.open = function open(filename, mode) {
-  var file = MozFile(filename);
-  if (typeof(mode) !== "string")
-    mode = "";
-
-  // File opened for write only.
-  if (/w/.test(mode)) {
-    if (file.exists())
-      ensureFile(file);
-    var stream = Cc['@mozilla.org/network/file-output-stream;1'].
-                 createInstance(Ci.nsIFileOutputStream);
-    var openFlags = OPEN_FLAGS.WRONLY |
-                    OPEN_FLAGS.CREATE_FILE |
-                    OPEN_FLAGS.TRUNCATE;
-    var permFlags = 0o644; // u+rw go+r
-    try {
-      stream.init(file, openFlags, permFlags, 0);
-    }
-    catch (err) {
-      throw friendlyError(err, filename);
-    }
-    return /b/.test(mode) ?
-           new byteStreams.ByteWriter(stream) :
-           new textStreams.TextWriter(stream);
-  }
-
-  // File opened for read only, the default.
-  ensureFile(file);
-  stream = Cc['@mozilla.org/network/file-input-stream;1'].
-           createInstance(Ci.nsIFileInputStream);
-  try {
-    stream.init(file, OPEN_FLAGS.RDONLY, 0, 0);
-  }
-  catch (err) {
-    throw friendlyError(err, filename);
-  }
-  return /b/.test(mode) ?
-         new byteStreams.ByteReader(stream) :
-         new textStreams.TextReader(stream);
-};
-
-exports.remove = function remove(path) {
-  var file = MozFile(path);
-  ensureFile(file);
-  file.remove(false);
-};
-
-exports.mkpath = function mkpath(path) {
-  var file = MozFile(path);
-  if (!file.exists())
-    file.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); // u+rwx go+rx
-  else if (!file.isDirectory())
-    throw new Error("The path already exists and is not a directory: " + path);
-};
-
-exports.rmdir = function rmdir(path) {
-  var file = MozFile(path);
-  ensureDir(file);
-  try {
-    file.remove(false);
-  }
-  catch (err) {
-    // Bug 566950 explains why we're not catching a specific exception here.
-    throw new Error("The directory is not empty: " + path);
-  }
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/functional.js
+++ /dev/null
@@ -1,47 +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/. */
-
-// Disclaimer: Some of the functions in this module implement APIs from
-// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
-// those goes to him.
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { defer, remit, delay, debounce,
-        throttle } = require("./functional/concurrent");
-const { method, invoke, partial, curry, compose, wrap, identity, memoize, once,
-        cache, complement, constant, when, apply, flip, field, query,
-        isInstance, chainable, is, isnt } = require("./functional/core");
-
-exports.defer = defer;
-exports.remit = remit;
-exports.delay = delay;
-exports.debounce = debounce;
-exports.throttle = throttle;
-
-exports.method = method;
-exports.invoke = invoke;
-exports.partial = partial;
-exports.curry = curry;
-exports.compose = compose;
-exports.wrap = wrap;
-exports.identity = identity;
-exports.memoize = memoize;
-exports.once = once;
-exports.cache = cache;
-exports.complement = complement;
-exports.constant = constant;
-exports.when = when;
-exports.apply = apply;
-exports.flip = flip;
-exports.field = field;
-exports.query = query;
-exports.isInstance = isInstance;
-exports.chainable = chainable;
-exports.is = is;
-exports.isnt = isnt;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/functional/concurrent.js
+++ /dev/null
@@ -1,111 +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/. */
-
-// Disclaimer: Some of the functions in this module implement APIs from
-// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
-// those goes to him.
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { arity, name, derive, invoke } = require("./helpers");
-
-lazyRequire(this, "sdk/timers", "setTimeout", "clearTimeout", "setImmediate");
-
-/**
- * Takes a function and returns a wrapped one instead, calling which will call
- * original function in the next turn of event loop. This is basically utility
- * to do `setImmediate(function() { ... })`, with a difference that returned
- * function is reused, instead of creating a new one each time. This also allows
- * to use this functions as event listeners.
- */
-const defer = f => derive(function(...args) {
-  setImmediate(invoke, f, args, this);
-}, f);
-exports.defer = defer;
-// Exporting `remit` alias as `defer` may conflict with promises.
-exports.remit = defer;
-
-/**
- * Much like setTimeout, invokes function after wait milliseconds. If you pass
- * the optional arguments, they will be forwarded on to the function when it is
- * invoked.
- */
-const delay = function delay(f, ms, ...args) {
-  setTimeout(() => f.apply(this, args), ms);
-};
-exports.delay = delay;
-
-/**
- * From underscore's `_.debounce`
- * http://underscorejs.org
- * (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Underscore may be freely distributed under the MIT license.
- */
-const debounce = function debounce (fn, wait) {
-  let timeout, args, context, timestamp, result;
-
-  let later = function () {
-    let last = Date.now() - timestamp;
-    if (last < wait) {
-      timeout = setTimeout(later, wait - last);
-    } else {
-      timeout = null;
-      result = fn.apply(context, args);
-      context = args = null;
-    }
-  };
-
-  return function (...aArgs) {
-    context = this;
-    args = aArgs;
-    timestamp  = Date.now();
-    if (!timeout) {
-      timeout = setTimeout(later, wait);
-    }
-
-    return result;
-  };
-};
-exports.debounce = debounce;
-
-/**
- * From underscore's `_.throttle`
- * http://underscorejs.org
- * (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Underscore may be freely distributed under the MIT license.
- */
-const throttle = function throttle (func, wait, options) {
-  let context, args, result;
-  let timeout = null;
-  let previous = 0;
-  options || (options = {});
-  let later = function() {
-    previous = options.leading === false ? 0 : Date.now();
-    timeout = null;
-    result = func.apply(context, args);
-    context = args = null;
-  };
-  return function() {
-    let now = Date.now();
-    if (!previous && options.leading === false) previous = now;
-    let remaining = wait - (now - previous);
-    context = this;
-    args = arguments;
-    if (remaining <= 0) {
-      clearTimeout(timeout);
-      timeout = null;
-      previous = now;
-      result = func.apply(context, args);
-      context = args = null;
-    } else if (!timeout && options.trailing !== false) {
-      timeout = setTimeout(later, remaining);
-    }
-    return result;
-  };
-};
-exports.throttle = throttle;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/functional/core.js
+++ /dev/null
@@ -1,290 +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/. */
-
-// Disclaimer: Some of the functions in this module implement APIs from
-// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
-// those goes to him.
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-}
-const { arity, name, derive, invoke } = require("./helpers");
-
-/**
- * Takes variadic numeber of functions and returns composed one.
- * Returned function pushes `this` pseudo-variable to the head
- * of the passed arguments and invokes all the functions from
- * left to right passing same arguments to them. Composite function
- * returns return value of the right most funciton.
- */
-const method = (...lambdas) => {
-  return function method(...args) {
-    args.unshift(this);
-    return lambdas.reduce((_, lambda) => lambda.apply(this, args),
-                          void(0));
-  };
-};
-exports.method = method;
-
-/**
- * Invokes `callee` by passing `params` as an arguments and `self` as `this`
- * pseudo-variable. Returns value that is returned by a callee.
- * @param {Function} callee
- *    Function to invoke.
- * @param {Array} params
- *    Arguments to invoke function with.
- * @param {Object} self
- *    Object to be passed as a `this` pseudo variable.
- */
-exports.invoke = invoke;
-
-/**
- * Takes a function and bind values to one or more arguments, returning a new
- * function of smaller arity.
- *
- * @param {Function} fn
- *    The function to partial
- *
- * @returns The new function with binded values
- */
-const partial = (f, ...curried) => {
-  if (typeof(f) !== "function")
-    throw new TypeError(String(f) + " is not a function");
-
-  let fn = derive(function(...args) {
-    return f.apply(this, curried.concat(args));
-  }, f);
-  fn.arity = arity(f) - curried.length;
-  return fn;
-};
-exports.partial = partial;
-
-/**
- * Returns function with implicit currying, which will continue currying until
- * expected number of argument is collected. Expected number of arguments is
- * determined by `fn.length`. Using this with variadic functions is stupid,
- * so don't do it.
- *
- * @examples
- *
- * var sum = curry(function(a, b) {
- *   return a + b
- * })
- * console.log(sum(2, 2)) // 4
- * console.log(sum(2)(4)) // 6
- */
-const curry = new function() {
-  const currier = (fn, arity, params) => {
-    // Function either continues to curry arguments or executes function
-    // if desired arguments have being collected.
-    const curried = function(...input) {
-      // Prepend all curried arguments to the given arguments.
-      if (params) input.unshift.apply(input, params);
-      // If expected number of arguments has being collected invoke fn,
-      // othrewise return curried version Otherwise continue curried.
-      return (input.length >= arity) ? fn.apply(this, input) :
-             currier(fn, arity, input);
-    };
-    curried.arity = arity - (params ? params.length : 0);
-
-    return curried;
-  };
-
-  return fn => currier(fn, arity(fn));
-};
-exports.curry = curry;
-
-/**
- * Returns the composition of a list of functions, where each function consumes
- * the return value of the function that follows. In math terms, composing the
- * functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
- * @example
- *
- *   var greet = function(name) { return "hi: " + name; };
- *   var exclaim = function(statement) { return statement + "!"; };
- *   var welcome = compose(exclaim, greet);
- *
- *   welcome('moe');    // => 'hi: moe!'
- */
-function compose(...lambdas) {
-  return function composed(...args) {
-    let index = lambdas.length;
-    while (0 <= --index)
-      args = [lambdas[index].apply(this, args)];
-
-    return args[0];
-  };
-}
-exports.compose = compose;
-
-/*
- * Returns the first function passed as an argument to the second,
- * allowing you to adjust arguments, run code before and after, and
- * conditionally execute the original function.
- * @example
- *
- *  var hello = function(name) { return "hello: " + name; };
- *  hello = wrap(hello, function(f) {
- *    return "before, " + f("moe") + ", after";
- *  });
- *
- *  hello();    // => 'before, hello: moe, after'
- */
-const wrap = (f, wrapper) => derive(function wrapped(...args) {
-  return wrapper.apply(this, [f].concat(args));
-}, f);
-exports.wrap = wrap;
-
-/**
- * Returns the same value that is used as the argument. In math: f(x) = x
- */
-const identity = value => value;
-exports.identity = identity;
-
-/**
- * Memoizes a given function by caching the computed result. Useful for
- * speeding up slow-running computations. If passed an optional hashFunction,
- * it will be used to compute the hash key for storing the result, based on
- * the arguments to the original function. The default hashFunction just uses
- * the first argument to the memoized function as the key.
- */
-const memoize = (f, hasher) => {
-  let memo = Object.create(null);
-  let cache = new WeakMap();
-  hasher = hasher || identity;
-  return derive(function memoizer(...args) {
-    const key = hasher.apply(this, args);
-    const type = typeof(key);
-    if (key && (type === "object" || type === "function")) {
-      if (!cache.has(key))
-        cache.set(key, f.apply(this, args));
-      return cache.get(key);
-    }
-    else {
-      if (!(key in memo))
-        memo[key] = f.apply(this, args);
-      return memo[key];
-    }
-  }, f);
-};
-exports.memoize = memoize;
-
-/*
- * Creates a version of the function that can only be called one time. Repeated
- * calls to the modified function will have no effect, returning the value from
- * the original call. Useful for initialization functions, instead of having to
- * set a boolean flag and then check it later.
- */
-const once = f => {
-  let ran = false, cache;
-  return derive(function(...args) {
-    return ran ? cache : (ran = true, cache = f.apply(this, args));
-  }, f);
-};
-exports.once = once;
-// export cache as once will may be conflicting with event once a lot.
-exports.cache = once;
-
-// Takes a `f` function and returns a function that takes the same
-// arguments as `f`, has the same effects, if any, and returns the
-// opposite truth value.
-const complement = f => derive(function(...args) {
-  return args.length < arity(f) ? complement(partial(f, ...args)) :
-         !f.apply(this, args);
-}, f);
-exports.complement = complement;
-
-// Constructs function that returns `x` no matter what is it
-// invoked with.
-const constant = x => _ => x;
-exports.constant = constant;
-
-// Takes `p` predicate, `consequent` function and an optional
-// `alternate` function and composes function that returns
-// application of arguments over `consequent` if application over
-// `p` is `true` otherwise returns application over `alternate`.
-// If `alternate` is not a function returns `undefined`.
-const when = (p, consequent, alternate) => {
-  if (typeof(alternate) !== "function" && alternate !== void(0))
-    throw TypeError("alternate must be a function");
-  if (typeof(consequent) !== "function")
-    throw TypeError("consequent must be a function");
-
-  return function(...args) {
-    return p.apply(this, args) ?
-           consequent.apply(this, args) :
-           alternate && alternate.apply(this, args);
-  };
-};
-exports.when = when;
-
-// Apply function that behaves as `apply` does in lisp:
-// apply(f, x, [y, z]) => f.apply(f, [x, y, z])
-// apply(f, x) => f.apply(f, [x])
-const apply = (f, ...rest) => f.apply(f, rest.concat(rest.pop()));
-exports.apply = apply;
-
-// Returns function identical to given `f` but with flipped order
-// of arguments.
-const flip = f => derive(function(...args) {
-  return f.apply(this, args.reverse());
-}, f);
-exports.flip = flip;
-
-// Takes field `name` and `target` and returns value of that field.
-// If `target` is `null` or `undefined` it would be returned back
-// instead of attempt to access it's field. Function is implicitly
-// curried, this allows accessor function generation by calling it
-// with only `name` argument.
-const field = curry((name, target) =>
-  // Note: Permisive `==` is intentional.
-  target == null ? target : target[name]);
-exports.field = field;
-
-// Takes `.` delimited string representing `path` to a nested field
-// and a `target` to get it from. For convinience function is
-// implicitly curried, there for accessors can be created by invoking
-// it with just a `path` argument.
-const query = curry((path, target) => {
-  const names = path.split(".");
-  const count = names.length;
-  let index = 0;
-  let result = target;
-  // Note: Permisive `!=` is intentional.
-  while (result != null && index < count) {
-    result = result[names[index]];
-    index = index + 1;
-  }
-  return result;
-});
-exports.query = query;
-
-// Takes `Type` (constructor function) and a `value` and returns
-// `true` if `value` is instance of the given `Type`. Function is
-// implicitly curried this allows predicate generation by calling
-// function with just first argument.
-const isInstance = curry((Type, value) => value instanceof Type);
-exports.isInstance = isInstance;
-
-/*
- * Takes a funtion and returns a wrapped function that returns `this`
- */
-const chainable = f => derive(function(...args) {
-  f.apply(this, args);
-  return this;
-}, f);
-exports.chainable = chainable;
-
-// Functions takes `expected` and `actual` values and returns `true` if
-// `expected === actual`. Returns curried function if called with less then
-// two arguments.
-//
-// [ 1, 0, 1, 0, 1 ].map(is(1)) // => [ true, false, true, false, true ]
-const is = curry((expected, actual) => actual === expected);
-exports.is = is;
-
-const isnt = complement(is);
-exports.isnt = isnt;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/functional/helpers.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/. */
-
-// Disclaimer: Some of the functions in this module implement APIs from
-// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
-// those goes to him.
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-}
-
-const arity = f => f.arity || f.length;
-exports.arity = arity;
-
-const name = f => f.displayName || f.name;
-exports.name = name;
-
-const derive = (f, source) => {
-  f.displayName = name(source);
-  f.arity = arity(source);
-  return f;
-};
-exports.derive = derive;
-
-const invoke = (callee, params, self) => callee.apply(self, params);
-exports.invoke = invoke;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/type.js
+++ /dev/null
@@ -1,388 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-/**
- * Returns `true` if `value` is `undefined`.
- * @examples
- *    var foo; isUndefined(foo); // true
- *    isUndefined(0); // false
- */
-function isUndefined(value) {
-  return value === undefined;
-}
-exports.isUndefined = isUndefined;
-
-/**
- * Returns `true` if value is `null`.
- * @examples
- *    isNull(null); // true
- *    isNull(undefined); // false
- */
-function isNull(value) {
-  return value === null;
-}
-exports.isNull = isNull;
-
-/**
- * Returns `true` if value is `null` or `undefined`.
- * It's equivalent to `== null`, but resolve the ambiguity of the writer
- * intention, makes clear that he's clearly checking both `null` and `undefined`
- * values, and it's not a typo for `=== null`.
- */
-function isNil(value) {
-  return value === null || value === undefined;
-}
-exports.isNil = isNil;
-
-function isBoolean(value) {
-  return typeof value === "boolean";
-}
-exports.isBoolean = isBoolean;
-/**
- * Returns `true` if value is a string.
- * @examples
- *    isString("moe"); // true
- */
-function isString(value) {
-  return typeof value === "string";
-}
-exports.isString = isString;
-
-/**
- * Returns `true` if `value` is a number.
- * @examples
- *    isNumber(8.4 * 5); // true
- */
-function isNumber(value) {
-  return typeof value === "number";
-}
-exports.isNumber = isNumber;
-
-/**
- * Returns `true` if `value` is a `RegExp`.
- * @examples
- *    isRegExp(/moe/); // true
- */
-function isRegExp(value) {
-  return isObject(value) && instanceOf(value, RegExp);
-}
-exports.isRegExp = isRegExp;
-
-/**
- * Returns true if `value` is a `Date`.
- * @examples
- *    isDate(new Date()); // true
- */
-function isDate(value) {
-  return isObject(value) && instanceOf(value, Date);
-}
-exports.isDate = isDate;
-
-/**
- * Returns true if object is a Function.
- * @examples
- *    isFunction(function foo(){}) // true
- */
-function isFunction(value) {
-    return typeof value === "function";
-}
-exports.isFunction = isFunction;
-
-/**
- * Returns `true` if `value` is an object (please note that `null` is considered
- * to be an atom and not an object).
- * @examples
- *    isObject({}) // true
- *    isObject(null) // false
- */
-function isObject(value) {
-    return typeof value === "object" && value !== null;
-}
-exports.isObject = isObject;
-
-/**
- * Detect whether a value is a generator.
- *
- * @param aValue
- *        The value to identify.
- * @return A boolean indicating whether the value is a generator.
- */
-function isGenerator(aValue) {
-  return !!(aValue && aValue.isGenerator && aValue.isGenerator());
-}
-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;
-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) {
-  return Object.prototype.toString.call(value) === "[object Arguments]";
-}
-exports.isArguments = isArguments;
-
-var isMap = value => Object.prototype.toString.call(value) === "[object Map]"
-exports.isMap = isMap;
-
-var isSet = value => Object.prototype.toString.call(value) === "[object Set]"
-exports.isSet = isSet;
-
-/**
- * Returns true if it is a primitive `value`. (null, undefined, number,
- * boolean, string)
- * @examples
- *    isPrimitive(3) // true
- *    isPrimitive('foo') // true
- *    isPrimitive({ bar: 3 }) // false
- */
-function isPrimitive(value) {
-  return !isFunction(value) && !isObject(value);
-}
-exports.isPrimitive = isPrimitive;
-
-/**
- * Returns `true` if given `object` is flat (it is direct decedent of
- * `Object.prototype` or `null`).
- * @examples
- *    isFlat({}) // true
- *    isFlat(new Type()) // false
- */
-function isFlat(object) {
-  return isObject(object) && (isNull(Object.getPrototypeOf(object)) ||
-                              isNull(Object.getPrototypeOf(
-                                     Object.getPrototypeOf(object))));
-}
-exports.isFlat = isFlat;
-
-/**
- * Returns `true` if object contains no values.
- */
-function isEmpty(object) {
-  if (isObject(object)) {
-    for (var key in object)
-      return false;
-    return true;
-  }
-  return false;
-}
-exports.isEmpty = isEmpty;
-
-/**
- * Returns `true` if `value` is an array / flat object containing only atomic
- * values and other flat objects.
- */
-function isJSON(value, visited) {
-    // Adding value to array of visited values.
-    (visited || (visited = [])).push(value);
-            // If `value` is an atom return `true` cause it's valid JSON.
-    return  isPrimitive(value) ||
-            // If `value` is an array of JSON values that has not been visited
-            // yet.
-            (isArray(value) &&  value.every(function(element) {
-                                  return isJSON(element, visited);
-                                })) ||
-            // If `value` is a plain object containing properties with a JSON
-            // values it's a valid JSON.
-            (isFlat(value) && Object.keys(value).every(function(key) {
-                var $ = Object.getOwnPropertyDescriptor(value, key);
-                // Check every proprety of a plain object to verify that
-                // it's neither getter nor setter, but a JSON value, that
-                // has not been visited yet.
-                return  ((!isObject($.value) || !~visited.indexOf($.value)) &&
-                        !('get' in $) && !('set' in $) &&
-                        isJSON($.value, visited));
-            }));
-}
-exports.isJSON = function (value) {
-  return isJSON(value);
-};
-
-/**
- * Returns `true` if `value` is JSONable
- */
-const isJSONable = (value) => {
-  try {
-    JSON.parse(JSON.stringify(value));
-  }
-  catch (e) {
-    return false;
-  }
-  return true;
-};
-exports.isJSONable = isJSONable;
-
-/**
- * Returns if `value` is an instance of a given `Type`. This is exactly same as
- * `value instanceof Type` with a difference that `Type` can be from a scope
- * that has a different top level object. (Like in case where `Type` is a
- * function from different iframe / jetpack module / sandbox).
- */
-function instanceOf(value, Type) {
-  var isConstructorNameSame;
-  var isConstructorSourceSame;
-
-  // If `instanceof` returned `true` we know result right away.
-  var isInstanceOf = value instanceof Type;
-
-  // If `instanceof` returned `false` we do ducktype check since `Type` may be
-  // from a different sandbox. If a constructor of the `value` or a constructor
-  // of the value's prototype has same name and source we assume that it's an
-  // instance of the Type.
-  if (!isInstanceOf && value) {
-    isConstructorNameSame = value.constructor.name === Type.name;
-    isConstructorSourceSame = String(value.constructor) == String(Type);
-    isInstanceOf = (isConstructorNameSame && isConstructorSourceSame) ||
-                    instanceOf(Object.getPrototypeOf(value), Type);
-  }
-  return isInstanceOf;
-}
-exports.instanceOf = instanceOf;
-
-/**
- * Function returns textual representation of a value passed to it. Function
- * takes additional `indent` argument that is used for indentation. Also
- * optional `limit` argument may be passed to limit amount of detail returned.
- * @param {Object} value
- * @param {String} [indent="    "]
- * @param {Number} [limit]
- */
-function source(value, indent, limit, offset, visited) {
-  var result;
-  var names;
-  var nestingIndex;
-  var isCompact = !isUndefined(limit);
-
-  indent = indent || "    ";
-  offset = (offset || "");
-  result = "";
-  visited = visited || [];
-
-  if (isUndefined(value)) {
-    result += "undefined";
-  }
-  else if (isNull(value)) {
-    result += "null";
-  }
-  else if (isString(value)) {
-    result += '"' + value + '"';
-  }
-  else if (isFunction(value)) {
-    value = String(value).split("\n");
-    if (isCompact && value.length > 2) {
-      value = value.splice(0, 2);
-      value.push("...}");
-    }
-    result += value.join("\n" + offset);
-  }
-  else if (isArray(value)) {
-    if ((nestingIndex = (visited.indexOf(value) + 1))) {
-      result = "#" + nestingIndex + "#";
-    }
-    else {
-      visited.push(value);
-
-      if (isCompact)
-        value = value.slice(0, limit);
-
-      result += "[\n";
-      result += value.map(function(value) {
-        return offset + indent + source(value, indent, limit, offset + indent,
-                                        visited);
-      }).join(",\n");
-      result += isCompact && value.length > limit ?
-                ",\n" + offset + "...]" : "\n" + offset + "]";
-    }
-  }
-  else if (isObject(value)) {
-    if ((nestingIndex = (visited.indexOf(value) + 1))) {
-      result = "#" + nestingIndex + "#"
-    }
-    else {
-      visited.push(value)
-
-      names = Object.keys(value);
-
-      result += "{ // " + value + "\n";
-      result += (isCompact ? names.slice(0, limit) : names).map(function(name) {
-        var _limit = isCompact ? limit - 1 : limit;
-        var descriptor = Object.getOwnPropertyDescriptor(value, name);
-        var result = offset + indent + "// ";
-        var accessor;
-        if (0 <= name.indexOf(" "))
-          name = '"' + name + '"';
-
-        if (descriptor.writable)
-          result += "writable ";
-        if (descriptor.configurable)
-          result += "configurable ";
-        if (descriptor.enumerable)
-          result += "enumerable ";
-
-        result += "\n";
-        if ("value" in descriptor) {
-          result += offset + indent + name + ": ";
-          result += source(descriptor.value, indent, _limit, indent + offset,
-                           visited);
-        }
-        else {
-
-          if (descriptor.get) {
-            result += offset + indent + "get " + name + " ";
-            accessor = source(descriptor.get, indent, _limit, indent + offset,
-                              visited);
-            result += accessor.substr(accessor.indexOf("{"));
-          }
-
-          if (descriptor.set) {
-            result += offset + indent + "set " + name + " ";
-            accessor = source(descriptor.set, indent, _limit, indent + offset,
-                              visited);
-            result += accessor.substr(accessor.indexOf("{"));
-          }
-        }
-        return result;
-      }).join(",\n");
-
-      if (isCompact) {
-        if (names.length > limit && limit > 0) {
-          result += ",\n" + offset  + indent + "//...";
-        }
-      }
-      else {
-        if (names.length)
-          result += ",";
-
-        result += "\n" + offset + indent + '"__proto__": ';
-        result += source(Object.getPrototypeOf(value), indent, 0,
-                         offset + indent);
-      }
-
-      result += "\n" + offset + "}";
-    }
-  }
-  else {
-    result += String(value);
-  }
-  return result;
-}
-exports.source = function (value, indentation, limit) {
-  return source(value, indentation, limit);
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/lang/weak-set.js
+++ /dev/null
@@ -1,75 +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/. */
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-"use strict";
-
-const { Cu } = require("chrome");
-
-function makeGetterFor(Type) {
-  let cache = new WeakMap();
-
-  return {
-    getFor(target) {
-      if (!cache.has(target))
-        cache.set(target, new Type());
-
-      return cache.get(target);
-    },
-    clearFor(target) {
-      return cache.delete(target)
-    }
-  }
-}
-
-var {getFor: getLookupFor, clearFor: clearLookupFor} = makeGetterFor(WeakMap);
-var {getFor: getRefsFor, clearFor: clearRefsFor} = makeGetterFor(Set);
-
-function add(target, value) {
-  if (has(target, value))
-    return;
-
-  getLookupFor(target).set(value, true);
-  getRefsFor(target).add(Cu.getWeakReference(value));
-}
-exports.add = add;
-
-function remove(target, value) {
-  getLookupFor(target).delete(value);
-}
-exports.remove = remove;
-
-function has(target, value) {
-  return getLookupFor(target).has(value);
-}
-exports.has = has;
-
-function clear(target) {
-  clearLookupFor(target);
-  clearRefsFor(target);
-}
-exports.clear = clear;
-
-function* iterator(target) {
-  let refs = getRefsFor(target);
-
-  for (let ref of refs) {
-    let value = ref.get();
-
-    // If `value` is already gc'ed, it would be `null`.
-    // The `has` function is using a WeakMap as lookup table, so passing `null`
-    // would raise an exception because WeakMap accepts as value only non-null
-    // object.
-    // Plus, if `value` is already gc'ed, we do not have to take it in account
-    // during the iteration, and remove it from the references.
-    if (value !== null && has(target, value))
-      yield value;
-    else
-      refs.delete(ref);
-  }
-}
-exports[Symbol.iterator] = iterator;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/net/url.js
+++ /dev/null
@@ -1,93 +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 { Ci, Cu, components } = require("chrome");
-
-lazyRequire(this, "../core/promise", "defer");
-
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-
-/**
- * Reads a URI and returns a promise.
- *
- * @param uri {string} The URI to read
- * @param [options] {object} This parameter can have any or all of the following
- * fields: `charset`. By default the `charset` is set to 'UTF-8'.
- *
- * @returns {promise}  The promise that will be resolved with the content of the
- *          URL given.
- *
- * @example
- *  let promise = readURI('resource://gre/modules/NetUtil.jsm', {
- *    charset: 'US-ASCII'
- *  });
- */
-function readURI(uri, options) {
-  options = options || {};
-  let charset = options.charset || 'UTF-8';
-
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, charset),
-    loadUsingSystemPrincipal: true});
-
-  let { promise, resolve, reject } = defer();
-
-  try {
-    NetUtil.asyncFetch(channel, function (stream, result) {
-      if (components.isSuccessCode(result)) {
-        let count = stream.available();
-        let data = NetUtil.readInputStreamToString(stream, count, { charset : charset });
-
-        resolve(data);
-      } else {
-        reject("Failed to read: '" + uri + "' (Error Code: " + result + ")");
-      }
-    });
-  }
-  catch (e) {
-    reject("Failed to read: '" + uri + "' (Error: " + e.message + ")");
-  }
-
-  return promise;
-}
-
-exports.readURI = readURI;
-
-/**
- * Reads a URI synchronously.
- * This function is intentionally undocumented to favorites the `readURI` usage.
- *
- * @param uri {string} The URI to read
- * @param [charset] {string} The character set to use when read the content of
- *        the `uri` given.  By default is set to 'UTF-8'.
- *
- * @returns {string} The content of the URI given.
- *
- * @example
- *  let data = readURISync('resource://gre/modules/NetUtil.jsm');
- */
-function readURISync(uri, charset) {
-  charset = typeof charset === "string" ? charset : "UTF-8";
-
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, charset),
-    loadUsingSystemPrincipal: true});
-  let stream = channel.open2();
-
-  let count = stream.available();
-  let data = NetUtil.readInputStreamToString(stream, count, { charset : charset });
-
-  stream.close();
-
-  return data;
-}
-
-exports.readURISync = readURISync;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/platform/xpcom.js
+++ /dev/null
@@ -1,241 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci, Cr, Cm, components: { classesByID } } = require('chrome');
-const { registerFactory, unregisterFactory, isCIDRegistered } =
-      Cm.QueryInterface(Ci.nsIComponentRegistrar);
-
-const { Class, extend, mix } = require('../core/heritage');
-lazyRequire(this, '../util/object', 'merge');
-lazyRequire(this, '../util/uuid', 'uuid');
-
-// This is a base prototype, that provides bare bones of XPCOM. JS based
-// components can be easily implement by extending it.
-const Unknown = new function() {
-  function hasInterface(component, iid) {
-    return component && component.interfaces &&
-      ( component.interfaces.some(id => iid.equals(Ci[id])) ||
-        component.implements.some($ => hasInterface($, iid)) ||
-        hasInterface(Object.getPrototypeOf(component), iid));
-  }
-
-  return Class({
-    /**
-     * The `QueryInterface` method provides runtime type discovery used by XPCOM.
-     * This method return queried instance of `this` if given `iid` is listed in
-     * the `interfaces` property or in equivalent properties of objects in it's
-     * prototype chain. In addition it will look up in the prototypes under
-     * `implements` array property, this ways compositions made via `Class`
-     * utility will carry interfaces implemented by composition components.
-     */
-    QueryInterface: function QueryInterface(iid) {
-      // For some reason there are cases when `iid` is `null`. In such cases we
-      // just return `this`. Otherwise we verify that component implements given
-      // `iid` interface. This will be no longer necessary once Bug 748003 is
-      // fixed.
-      if (iid && !hasInterface(this, iid))
-        throw Cr.NS_ERROR_NO_INTERFACE;
-
-      return this;
-    },
-    /**
-     * Array of `XPCOM` interfaces (as strings) implemented by this component.
-     * All components implement `nsISupports` by default which is default value
-     * here. Provide array of interfaces implemented by an object when
-     * extending, to append them to this list (Please note that there is no
-     * need to repeat interfaces implemented by super as they will be added
-     * automatically).
-     */
-    interfaces: Object.freeze([ 'nsISupports' ])
-  });
-}
-exports.Unknown = Unknown;
-
-// Base exemplar for creating instances implementing `nsIFactory` interface,
-// that maybe registered into runtime via `register` function. Instances of
-// this factory create instances of enclosed component on `createInstance`.
-const Factory = Class({
-  extends: Unknown,
-  interfaces: [ 'nsIFactory' ],
-  /**
-   * All the descendants will get auto generated `id` (also known as `classID`
-   * in XPCOM world) unless one is manually provided.
-   */
-  get id() { throw Error('Factory must implement `id` property') },
-  /**
-   * XPCOM `contractID` may optionally  be provided to associate this factory
-   * with it. `contract` is a unique string that has a following format:
-   * '@vendor.com/unique/id;1'.
-   */
-  contract: null,
-  /**
-   * Class description that is being registered. This value is intended as a
-   * human-readable description for the given class and does not needs to be
-   * globally unique.
-   */
-  description: 'Jetpack generated factory',
-  /**
-   * This method is required by `nsIFactory` interfaces, but as in most
-   * implementations it does nothing interesting.
-   */
-  lockFactory: function lockFactory(lock) {
-    return undefined;
-  },
-  /**
-   * If property is `true` XPCOM service / factory will be registered
-   * automatically on creation.
-   */
-  register: true,
-  /**
-   * If property is `true` XPCOM factory will be unregistered prior to add-on
-   * unload.
-   */
-  unregister: true,
-  /**
-   * Method is called on `Service.new(options)` passing given `options` to
-   * it. Options is expected to have `component` property holding XPCOM
-   * component implementation typically decedent of `Unknown` or any custom
-   * implementation with a `new` method and optional `register`, `unregister`
-   * flags. Unless `register` is `false` Service / Factory will be
-   * automatically registered. Unless `unregister` is `false` component will
-   * be automatically unregistered on add-on unload.
-   */
-  initialize: function initialize(options) {
-    merge(this, {
-      id: 'id' in options ? options.id : uuid(),
-      register: 'register' in options ? options.register : this.register,
-      unregister: 'unregister' in options ? options.unregister : this.unregister,
-      contract: 'contract' in options ? options.contract : null,
-      Component: options.Component
-    });
-
-    // If service / factory has auto registration enabled then register.
-    if (this.register)
-      register(this);
-  },
-  /**
-   * Creates an instance of the class associated with this factory.
-   */
-  createInstance: function createInstance(outer, iid) {
-    try {
-      if (outer)
-        throw Cr.NS_ERROR_NO_AGGREGATION;
-      return this.create().QueryInterface(iid);
-    }
-    catch (error) {
-      throw error instanceof Ci.nsIException ? error : Cr.NS_ERROR_FAILURE;
-    }
-  },
-  create: function create() {
-    return this.Component();
-  }
-});
-exports.Factory = Factory;
-
-// Exemplar for creating services that implement `nsIFactory` interface, that
-// can be registered into runtime via call to `register`. This services return
-// enclosed `component` on `getService`.
-const Service = Class({
-  extends: Factory,
-  initialize: function initialize(options) {
-    this.component = options.Component();
-    Factory.prototype.initialize.call(this, options);
-  },
-  description: 'Jetpack generated service',
-  /**
-   * Creates an instance of the class associated with this factory.
-   */
-  create: function create() {
-    return this.component;
-  }
-});
-exports.Service = Service;
-
-function isRegistered({ id }) {
-  return isCIDRegistered(id);
-}
-exports.isRegistered = isRegistered;
-
-/**
- * Registers given `component` object to be used to instantiate a particular
- * class identified by `component.id`, and creates an association of class
- * name and `component.contract` with the class.
- */
-function register(factory) {
-  if (!(factory instanceof Factory)) {
-    throw new Error("xpcom.register() expect a Factory instance.\n" +
-                    "Please refactor your code to new xpcom module if you" +
-                    " are repacking an addon from SDK <= 1.5:\n" +
-                    "https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/platform_xpcom");
-  }
-
-  registerFactory(factory.id, factory.description, factory.contract, factory);
-
-  if (factory.unregister)
-    require('../system/unload').when(unregister.bind(null, factory));
-}
-exports.register = register;
-
-/**
- * Unregister a factory associated with a particular class identified by
- * `factory.classID`.
- */
-function unregister(factory) {
-  if (isRegistered(factory))
-    unregisterFactory(factory.id, factory);
-}
-exports.unregister = unregister;
-
-function autoRegister(path) {
-  // TODO: This assumes that the url points to a directory
-  // that contains subdirectories corresponding to OS/ABI and then
-  // further subdirectories corresponding to Gecko platform version.
-  // we should probably either behave intelligently here or allow
-  // the caller to pass-in more options if e.g. there aren't
-  // Gecko-specific binaries for a component (which will be the case
-  // if only frozen interfaces are used).
-
-  var runtime = require("../system/runtime");
-  var osDirName = runtime.OS + "_" + runtime.XPCOMABI;
-  var platformVersion = require("../system/xul-app").platformVersion.substring(0, 5);
-
-  var file = Cc['@mozilla.org/file/local;1']
-             .createInstance(Ci.nsIFile);
-  file.initWithPath(path);
-  file.append(osDirName);
-  file.append(platformVersion);
-
-  if (!(file.exists() && file.isDirectory()))
-    throw new Error("component not available for OS/ABI " +
-                    osDirName + " and platform " + platformVersion);
-
-  Cm.QueryInterface(Ci.nsIComponentRegistrar);
-  Cm.autoRegister(file);
-}
-exports.autoRegister = autoRegister;
-
-/**
- * Returns registered factory that has a given `id` or `null` if not found.
- */
-function factoryByID(id) {
-  return classesByID[id] || null;
-}
-exports.factoryByID = factoryByID;
-
-/**
- * Returns factory registered with a given `contract` or `null` if not found.
- * In contrast to `Cc[contract]` that does ignores new factory registration
- * with a given `contract` this will return a factory currently associated
- * with a `contract`.
- */
-function factoryByContract(contract) {
-  return factoryByID(Cm.contractIDToCID(contract));
-}
-exports.factoryByContract = factoryByContract;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/preferences/service.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-// The minimum and maximum integers that can be set as preferences.
-// The range of valid values is narrower than the range of valid JS values
-// because the native preferences code treats integers as NSPR PRInt32s,
-// which are 32-bit signed integers on all platforms.
-const MAX_INT = 0x7FFFFFFF;
-const MIN_INT = -0x80000000;
-
-const {Cc,Ci,Cr} = require("chrome");
-
-const prefService = Cc["@mozilla.org/preferences-service;1"].
-                getService(Ci.nsIPrefService);
-const prefSvc = prefService.getBranch(null);
-const defaultBranch = prefService.getDefaultBranch(null);
-
-const { Preferences } = require("resource://gre/modules/Preferences.jsm");
-const prefs = new Preferences({});
-
-const branchKeys = branchName =>
-  keys(branchName).map($ => $.replace(branchName, ""));
-
-const Branch = function(branchName) {
-  return new Proxy(Branch.prototype, {
-    getOwnPropertyDescriptor(target, name, receiver) {
-      return {
-        configurable: true,
-        enumerable: true,
-        writable: false,
-        value: this.get(target, name, receiver)
-      };
-    },
-    ownKeys(target) {
-      return branchKeys(branchName);
-    },
-    get(target, name, receiver) {
-      return get(`${branchName}${name}`);
-    },
-    set(target, name, value, receiver) {
-      set(`${branchName}${name}`, value);
-      return true;
-    },
-    has(target, name) {
-      return this.hasOwn(target, name);
-    },
-    hasOwn(target, name) {
-      return has(`${branchName}${name}`);
-    },
-    deleteProperty(target, name) {
-      reset(`${branchName}${name}`);
-      return true;
-    }
-  });
-}
-
-
-function get(name, defaultValue) {
-  return prefs.get(name, defaultValue);
-}
-exports.get = get;
-
-
-function set(name, value) {
-  var prefType;
-  if (typeof value != "undefined" && value != null)
-    prefType = value.constructor.name;
-
-  switch (prefType) {
-  case "Number":
-    if (value % 1 != 0)
-      throw new Error("cannot store non-integer number: " + value);
-  }
-
-  prefs.set(name, value);
-}
-exports.set = set;
-
-const has = prefs.has.bind(prefs)
-exports.has = has;
-
-function keys(root) {
-  return prefSvc.getChildList(root);
-}
-exports.keys = keys;
-
-const isSet = prefs.isSet.bind(prefs);
-exports.isSet = isSet;
-
-function reset(name) {
-  try {
-    prefSvc.clearUserPref(name);
-  }
-  catch (e) {
-    // The pref service throws NS_ERROR_UNEXPECTED when the caller tries
-    // to reset a pref that doesn't exist or is already set to its default
-    // value.  This interface fails silently in those cases, so callers
-    // can unconditionally reset a pref without having to check if it needs
-    // resetting first or trap exceptions after the fact.  It passes through
-    // other exceptions, however, so callers know about them, since we don't
-    // know what other exceptions might be thrown and what they might mean.
-    if (e.result != Cr.NS_ERROR_UNEXPECTED) {
-      throw e;
-    }
-  }
-}
-exports.reset = reset;
-
-function getLocalized(name, defaultValue) {
-  let value = null;
-  try {
-    value = prefSvc.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
-  }
-  finally {
-    return value || defaultValue;
-  }
-}
-exports.getLocalized = getLocalized;
-
-function setLocalized(name, value) {
-  // We can't use `prefs.set` here as we have to use `getDefaultBranch`
-  // (instead of `getBranch`) in order to have `mIsDefault` set to true, here:
-  // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#233
-  // Otherwise, we do not enter into this expected condition:
-  // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#244
-  defaultBranch.setCharPref(name, value);
-}
-exports.setLocalized = setLocalized;
-
-exports.Branch = Branch;
-
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/preferences/utils.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { openTab, getBrowserForTab, getTabId } = require("sdk/tabs/utils");
-const { on, off } = require("sdk/system/events");
-const { getMostRecentBrowserWindow } = require('../window/utils');
-
-// Opens about:addons in a new tab, then displays the inline
-// preferences of the provided add-on
-const open = ({ id }) => new Promise((resolve, reject) => {
-  // opening the about:addons page in a new tab
-  let tab = openTab(getMostRecentBrowserWindow(), "about:addons");
-  let browser = getBrowserForTab(tab);
-
-  // waiting for the about:addons page to load
-  browser.addEventListener("load", function() {
-    let window = browser.contentWindow;
-
-    // wait for the add-on's "addon-options-displayed"
-    on("addon-options-displayed", function onPrefDisplayed({ subject: doc, data }) {
-      if (data === id) {
-        off("addon-options-displayed", onPrefDisplayed);
-        resolve({
-          id: id,
-          tabId: getTabId(tab),
-          "document": doc
-        });
-      }
-    }, true);
-
-    // display the add-on inline preferences page
-    window.gViewController.commands.cmd_showItemDetails.doCommand({ id: id }, true);
-  }, {capture: true, once: true});
-});
-exports.open = open;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/private-browsing.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  "stability": "stable"
-};
-
-const { isPrivate } = require('./private-browsing/utils');
-
-exports.isPrivate = isPrivate;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/private-browsing/utils.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci, Cu } = require('chrome');
-const { is } = require('../system/xul-app');
-const { dispatcher } = require("../util/dispatcher");
-
-lazyRequire(this, '../window/utils', "isWindowPrivate");
-lazyRequire(this, '../self', "isPrivateBrowsingSupported");
-
-var PrivateBrowsingUtils;
-
-// Private browsing is only supported in Fx
-try {
-  PrivateBrowsingUtils = Cu.import('resource://gre/modules/PrivateBrowsingUtils.jsm', {}).PrivateBrowsingUtils;
-}
-catch (e) {}
-
-exports.isGlobalPBSupported = false;
-
-// checks that per-window private browsing is implemented
-var isWindowPBSupported = exports.isWindowPBSupported =
-                          !!PrivateBrowsingUtils && is('Firefox');
-
-// checks that per-tab private browsing is implemented
-var isTabPBSupported = exports.isTabPBSupported =
-                       !!PrivateBrowsingUtils && is('Fennec');
-
-function isPermanentPrivateBrowsing() {
- return !!(PrivateBrowsingUtils && PrivateBrowsingUtils.permanentPrivateBrowsing);
-}
-exports.isPermanentPrivateBrowsing = isPermanentPrivateBrowsing;
-
-function ignoreWindow(window) {
-  return !isPrivateBrowsingSupported && isWindowPrivate(window);
-}
-exports.ignoreWindow = ignoreWindow;
-
-var getMode = function getMode(chromeWin) {
-  return (chromeWin !== undefined && isWindowPrivate(chromeWin));
-};
-exports.getMode = getMode;
-
-const isPrivate = dispatcher("isPrivate");
-isPrivate.when(isPermanentPrivateBrowsing, _ => true);
-isPrivate.when(x => x instanceof Ci.nsIDOMWindow, isWindowPrivate);
-isPrivate.when(x => Ci.nsIPrivateBrowsingChannel && x instanceof Ci.nsIPrivateBrowsingChannel, x => x.isChannelPrivate);
-isPrivate.define(() => false);
-exports.isPrivate = isPrivate;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/querystring.js
+++ /dev/null
@@ -1,121 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-var unescape = decodeURIComponent;
-exports.unescape = unescape;
-
-// encodes a string safely for application/x-www-form-urlencoded
-// adheres to RFC 3986
-// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent
-function escape(query) {
-  return encodeURIComponent(query).
-    replace(/%20/g, '+').
-    replace(/!/g, '%21').
-    replace(/'/g, '%27').
-    replace(/\(/g, '%28').
-    replace(/\)/g, '%29').
-    replace(/\*/g, '%2A');
-}
-exports.escape = escape;
-
-// Converts an object of unordered key-vals to a string that can be passed
-// as part of a request
-function stringify(options, separator, assigner) {
-  separator = separator || '&';
-  assigner = assigner || '=';
-  // Explicitly return null if we have null, and empty string, or empty object.
-  if (!options)
-    return '';
-
-  // If content is already a string, just return it as is.
-  if (typeof(options) == 'string')
-    return options;
-
-  // At this point we have a k:v object. Iterate over it and encode each value.
-  // Arrays and nested objects will get encoded as needed. For example...
-  //
-  //   { foo: [1, 2, { omg: 'bbq', 'all your base!': 'are belong to us' }], bar: 'baz' }
-  //
-  // will be encoded as
-  //
-  //   foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz
-  //
-  // Keys (including '[' and ']') and values will be encoded with
-  // `escape` before returning.
-  //
-  // Execution was inspired by jQuery, but some details have changed and numeric
-  // array keys are included (whereas they are not in jQuery).
-
-  let encodedContent = [];
-  function add(key, val) {
-    encodedContent.push(escape(key) + assigner + escape(val));
-  }
-
-  function make(key, value) {
-    if (value && typeof(value) === 'object')
-      Object.keys(value).forEach(function(name) {
-        make(key + '[' + name + ']', value[name]);
-      });
-    else
-      add(key, value);
-  }
-
-  Object.keys(options).forEach(function(name) { make(name, options[name]); });
-  return encodedContent.join(separator);
-
-  //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had
-  //        trouble getting that working. It would also be nice to stay
-  //        backwards-compat as long as possible. Keeping this in for now...
-  // let formData = Cc['@mozilla.org/files/formdata;1'].
-  //                createInstance(Ci.nsIDOMFormData);
-  // for ([k, v] in Iterator(content)) {
-  //   formData.append(k, v);
-  // }
-  // return formData;
-}
-exports.stringify = stringify;
-
-// Exporting aliases that nodejs implements just for the sake of
-// interoperability.
-exports.encode = stringify;
-exports.serialize = stringify;
-
-// Note: That `stringify` and `parse` aren't bijective as we use `stringify`
-// as it was implement in request module, but implement `parse` to match nodejs
-// behavior.
-// TODO: Make `stringify` implement API as in nodejs and figure out backwards
-// compatibility.
-function parse(query, separator, assigner) {
-  separator = separator || '&';
-  assigner = assigner || '=';
-  let result = {};
-
-  if (typeof query !== 'string' || query.length === 0)
-    return result;
-
-  query.split(separator).forEach(function(chunk) {
-    let pair = chunk.split(assigner);
-    let key = unescape(pair[0]);
-    let value = unescape(pair.slice(1).join(assigner));
-
-    if (!(key in result))
-      result[key] = value;
-    else if (Array.isArray(result[key]))
-      result[key].push(value);
-    else
-      result[key] = [result[key], value];
-  });
-
-  return result;
-};
-exports.parse = parse;
-// Exporting aliases that nodejs implements just for the sake of
-// interoperability.
-exports.decode = parse;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/self.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "stable"
-};
-
-const { CC } = require('chrome');
-const options = require('@loader/options');
-
-const { get } = require("./preferences/service");
-lazyRequire(this, './net/url', "readURISync");
-
-const id = options.id;
-
-const readPref = key => get("extensions." + id + ".sdk." + key);
-
-const name = readPref("name") || options.name;
-const version = readPref("version") || options.version;
-const loadReason = readPref("load.reason") || options.loadReason;
-const rootURI = readPref("rootURI") || options.rootURI || "";
-const baseURI = readPref("baseURI") || options.prefixURI + name + "/"
-const addonDataURI = baseURI + "data/";
-const metadata = options.metadata || {};
-const permissions = metadata.permissions || {};
-const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
-
-const isPrivateBrowsingSupported = 'private-browsing' in permissions &&
-                                   permissions['private-browsing'] === true;
-
-const uri = (path="") =>
-  path.includes(":") ? path : addonDataURI + path.replace(/^\.\//, "");
-
-var preferencesBranch = ("preferences-branch" in metadata)
-                            ? metadata["preferences-branch"]
-                            : options.preferencesBranch
-
-if (/[^\w{@}.-]/.test(preferencesBranch)) {
-  preferencesBranch = id;
-  console.warn("Ignoring preferences-branch (not a valid branch name)");
-}
-
-// Some XPCOM APIs require valid URIs as an argument for certain operations
-// (see `nsILoginManager` for example). This property represents add-on
-// associated unique URI string that can be used for that.
-exports.uri = 'addon:' + id;
-exports.id = id;
-exports.preferencesBranch = preferencesBranch || id;
-exports.name = name;
-exports.loadReason = loadReason;
-exports.version = version;
-exports.packed = isPacked;
-exports.data = Object.freeze({
-  url: uri,
-  load: function read(path) {
-    return readURISync(uri(path));
-  }
-});
-exports.isPrivateBrowsingSupported = isPrivateBrowsingSupported;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system.js
+++ /dev/null
@@ -1,175 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci, CC } = require('chrome');
-const options = require('@loader/options');
-const runtime = require("./system/runtime");
-const { when: unload } = require("./system/unload");
-
-const { XPCOMUtils } = require('resource://gre/modules/XPCOMUtils.jsm');
-
-XPCOMUtils.defineLazyServiceGetter(this, 'appStartup',
-                                   '@mozilla.org/toolkit/app-startup;1',
-                                   'nsIAppStartup');
-XPCOMUtils.defineLazyServiceGetter(this, 'directoryService',
-                                   '@mozilla.org/file/directory_service;1',
-                                   'nsIProperties');
-
-const appInfo = Cc["@mozilla.org/xre/app-info;1"].
-                getService(Ci.nsIXULAppInfo);
-
-const PR_WRONLY = parseInt("0x02");
-const PR_CREATE_FILE = parseInt("0x08");
-const PR_APPEND = parseInt("0x10");
-const PR_TRUNCATE = parseInt("0x20");
-
-function openFile(path, mode) {
-  let file = Cc["@mozilla.org/file/local;1"].
-             createInstance(Ci.nsIFile);
-  file.initWithPath(path);
-  let stream = Cc["@mozilla.org/network/file-output-stream;1"].
-               createInstance(Ci.nsIFileOutputStream);
-  stream.init(file, mode, -1, 0);
-  return stream
-}
-
-/**
- * Parsed JSON object that was passed via `cfx --static-args "{ foo: 'bar' }"`
- */
-exports.staticArgs = options.staticArgs;
-
-/**
- * Environment variables. Environment variables are non-enumerable properties
- * of this object (key is name and value is value).
- */
-exports.env = require('./system/environment').env;
-
-/**
- * Ends the process with the specified `code`. If omitted, exit uses the
- * 'success' code 0. To exit with failure use `1`.
- * TODO: Improve platform to actually quit with an exit code.
- */
-var forcedExit = false;
-exports.exit = function exit(code) {
-  if (forcedExit) {
-    // a forced exit was already tried
-    // NOTE: exit(0) is called twice sometimes (ex when using cfx testaddons)
-    return;
-  }
-
-  let resultsFile = 'resultFile' in options && options.resultFile;
-  function unloader() {
-    if (!options.resultFile) {
-      return;
-    }
-
-    // This is used by 'cfx' to find out exit code.
-    let mode = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
-    let stream = openFile(options.resultFile, mode);
-    let status = code ? 'FAIL' : 'OK';
-    stream.write(status, status.length);
-    stream.flush();
-    stream.close();
-    return;
-  }
-
-  if (code == 0) {
-    forcedExit = true;
-  }
-
-  // Bug 856999: Prevent automatic kill of Firefox when running tests
-  if (options.noQuit) {
-    return unload(unloader);
-  }
-
-  unloader();
-  appStartup.quit(code ? appStartup.eAttemptQuit : appStartup.eForceQuit);
-};
-
-// Adapter for nodejs's stdout & stderr:
-// http://nodejs.org/api/process.html#process_process_stdout
-var stdout = Object.freeze({ write: dump, end: dump });
-exports.stdout = stdout;
-exports.stderr = stdout;
-
-/**
- * Returns a path of the system's or application's special directory / file
- * associated with a given `id`. For list of possible `id`s please see:
- * https://developer.mozilla.org/en-US/docs/Code_snippets/File_I_O#Getting_files_in_special_directories
- * http://dxr.mozilla.org/mozilla-central/source/xpcom/io/nsAppDirectoryServiceDefs.h
- * @example
- *
- *    // get firefox profile path
- *    let profilePath = require('system').pathFor('ProfD');
- *    // get OS temp files directory (/tmp)
- *    let temps = require('system').pathFor('TmpD');
- *    // get OS desktop path for an active user (~/Desktop on linux
- *    // or C:\Documents and Settings\username\Desktop on windows).
- *    let desktopPath = require('system').pathFor('Desk');
- */
-exports.pathFor = function pathFor(id) {
-  return directoryService.get(id, Ci.nsIFile).path;
-};
-
-/**
- * What platform you're running on (all lower case string).
- * For possible values see:
- * https://developer.mozilla.org/en/OS_TARGET
- */
-exports.platform = runtime.OS.toLowerCase();
-
-const [, architecture, compiler] = runtime.XPCOMABI ?
-                                   runtime.XPCOMABI.match(/^([^-]*)-(.*)$/) :
-                                   [, null, null];
-
-/**
- * What processor architecture you're running on:
- * `'arm', 'ia32', or 'x64'`.
- */
-exports.architecture = architecture;
-
-/**
- * What compiler used for build:
- * `'msvc', 'n32', 'gcc2', 'gcc3', 'sunc', 'ibmc'...`
- */
-exports.compiler = compiler;
-
-/**
- * The application's build ID/date, for example "2004051604".
- */
-exports.build = appInfo.appBuildID;
-
-/**
- * The XUL application's UUID.
- * This has traditionally been in the form
- * `{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}` but for some applications it may
- * be: "appname@vendor.tld".
- */
-exports.id = appInfo.ID;
-
-/**
- * The name of the application.
- */
-exports.name = appInfo.name;
-
-/**
- * The XUL application's version, for example "0.8.0+" or "3.7a1pre".
- */
-exports.version = appInfo.version;
-
-/**
- * XULRunner version.
- */
-exports.platformVersion = appInfo.platformVersion;
-
-
-/**
- * The name of the application vendor, for example "Mozilla".
- */
-exports.vendor = appInfo.vendor;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/environment.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  "stability": "stable"
-};
-
-const { Cc, Ci } = require('chrome');
-const { get, set, exists } = Cc['@mozilla.org/process/environment;1'].
-                             getService(Ci.nsIEnvironment);
-
-exports.env = new Proxy({}, {
-  deleteProperty(target, property) {
-    set(property, null);
-    return true;
-  },
-
-  get(target, property, receiver) {
-    return get(property) || undefined;
-  },
-
-  has(target, property) {
-    return exists(property);
-  },
-
-  set(target, property, value, receiver) {
-    set(property, value);
-    return true;
-  }
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/events.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-const { Cc, Ci, Cu } = require('chrome');
-const { Unknown } = require('../platform/xpcom');
-const { Class } = require('../core/heritage');
-const { ns } = require('../core/namespace');
-const observerService =
-  Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
-const { addObserver, removeObserver, notifyObservers } = observerService;
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const addObserverNoShim = ShimWaiver.getProperty(observerService, "addObserver");
-const removeObserverNoShim = ShimWaiver.getProperty(observerService, "removeObserver");
-const notifyObserversNoShim = ShimWaiver.getProperty(observerService, "notifyObservers");
-const unloadSubject = require('@loader/unload');
-
-const Subject = Class({
-  extends: Unknown,
-  initialize: function initialize(object) {
-    // Double-wrap the object and set a property identifying the
-    // wrappedJSObject as one of our wrappers to distinguish between
-    // subjects that are one of our wrappers (which we should unwrap
-    // when notifying our observers) and those that are real JS XPCOM
-    // components (which we should pass through unaltered).
-    this.wrappedJSObject = {
-      observersModuleSubjectWrapper: true,
-      object: object
-    };
-  },
-  getScriptableHelper: function() {},
-  getInterfaces: function() {}
-});
-
-function emit(type, event, shimmed = false) {
-  // From bug 910599
-  // We must test to see if 'subject' or 'data' is a defined property
-  // of the event object, but also allow primitives to be passed in,
-  // which the `in` operator breaks, yet `null` is an object, hence
-  // the long conditional
-  let subject = event && typeof event === 'object' && 'subject' in event ?
-    Subject(event.subject) :
-    null;
-  let data = event && typeof event === 'object' ?
-    // An object either returns its `data` property or null
-    ('data' in event ? event.data : null) :
-    // All other types return themselves (and cast to strings/null
-    // via observer service)
-    event;
-  if (shimmed) {
-    notifyObservers(subject, type, data);
-  } else {
-    notifyObserversNoShim(subject, type, data);
-  }
-}
-exports.emit = emit;
-
-const Observer = Class({
-  extends: Unknown,
-  initialize: function initialize(listener) {
-    this.listener = listener;
-  },
-  interfaces: [ 'nsIObserver', 'nsISupportsWeakReference' ],
-  observe: function(subject, topic, data) {
-    // Extract the wrapped object for subjects that are one of our
-    // wrappers around a JS object.  This way we support both wrapped
-    // subjects created using this module and those that are real
-    // XPCOM components.
-    if (subject && typeof(subject) == 'object' &&
-        ('wrappedJSObject' in subject) &&
-        ('observersModuleSubjectWrapper' in subject.wrappedJSObject))
-      subject = subject.wrappedJSObject.object;
-
-    try {
-      this.listener({
-        type: topic,
-        subject: subject,
-        data: data
-      });
-    }
-    catch (error) {
-      console.exception(error);
-    }
-  }
-});
-
-const subscribers = ns();
-
-function on(type, listener, strong, shimmed = false) {
-  // Unless last optional argument is `true` we use a weak reference to a
-  // listener.
-  let weak = !strong;
-  // Take list of observers associated with given `listener` function.
-  let observers = subscribers(listener);
-  // If `observer` for the given `type` is not registered yet, then
-  // associate an `observer` and register it.
-  if (!(type in observers)) {
-    let observer = Observer(listener);
-    observers[type] = observer;
-    if (shimmed) {
-      addObserver(observer, type, weak);
-    } else {
-      addObserverNoShim(observer, type, weak);
-    }
-    // WeakRef gymnastics to remove all alive observers on unload
-    let ref = Cu.getWeakReference(observer);
-    weakRefs.set(observer, ref);
-    stillAlive.set(ref, type);
-    wasShimmed.set(ref, shimmed);
-  }
-}
-exports.on = on;
-
-function once(type, listener, shimmed = false) {
-  // Note: this code assumes order in which listeners are called, which is fine
-  // as long as dispatch happens in same order as listener registration which
-  // is the case now. That being said we should be aware that this may break
-  // in a future if order will change.
-  on(type, listener, shimmed);
-  on(type, function cleanup() {
-    off(type, listener, shimmed);
-    off(type, cleanup, shimmed);
-  }, true, shimmed);
-}
-exports.once = once;
-
-function off(type, listener, shimmed = false) {
-  // Take list of observers as with the given `listener`.
-  let observers = subscribers(listener);
-  // If `observer` for the given `type` is registered, then
-  // remove it & unregister.
-  if (type in observers) {
-    let observer = observers[type];
-    delete observers[type];
-    if (shimmed) {
-      removeObserver(observer, type);
-    } else {
-      removeObserverNoShim(observer, type);
-    }
-    stillAlive.delete(weakRefs.get(observer));
-    wasShimmed.delete(weakRefs.get(observer));
-  }
-}
-exports.off = off;
-
-// must use WeakMap to keep reference to all the WeakRefs (!), see bug 986115
-var weakRefs = new WeakMap();
-
-// and we're out of beta, we're releasing on time!
-var stillAlive = new Map();
-
-var wasShimmed = new Map();
-
-on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
-  // using logic from ./unload, to avoid a circular module reference
-  if (subject.wrappedJSObject === unloadSubject) {
-    off('sdk:loader:destroy', onunload, false);
-
-    // don't bother
-    if (reason === 'shutdown')
-      return;
-
-    // Wait until the next tick to let other shutdown handlers finish first.
-    Promise.resolve().then(() => {
-      stillAlive.forEach((type, ref) => {
-        let observer = ref.get();
-        if (observer) {
-          if (wasShimmed.get(ref)) {
-            removeObserver(observer, type);
-          } else {
-            removeObserverNoShim(observer, type);
-          }
-        }
-      });
-    });
-  }
-}, true, false);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/globals.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-defineLazyGetter(this, "console", () => new (require('../console/plain-text').PlainTextConsole)());
-
-exports = module.exports = {};
-
-defineLazyGetter(exports, "console", () => console);
-
-// Provide CommonJS `define` to allow authoring modules in a format that can be
-// loaded both into jetpack and into browser via AMD loaders.
-
-// `define` is provided as a lazy getter that binds below defined `define`
-// function to the module scope, so that require, exports and module
-// variables remain accessible.
-defineLazyGetter(exports, 'define', function() {
-  return (...args) => {
-    let factory = args.pop();
-    factory.call(this, this.require, this.exports, this.module);
-  };
-});
-
-function defineLazyGetter(object, prop, getter) {
-  let redefine = (obj, value) => {
-    Object.defineProperty(obj, prop, {
-      configurable: true,
-      writable: true,
-      value,
-    });
-    return value;
-  };
-
-  Object.defineProperty(object, prop, {
-    configurable: true,
-    get() {
-      return redefine(this, getter.call(this));
-    },
-    set(value) {
-      redefine(this, value);
-    }
-  });
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/process.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const {
-  exit, version, stdout, stderr, platform, architecture
-} = require("../system");
-
-/**
- * Supported
- */
-
-exports.stdout = stdout;
-exports.stderr = stderr;
-exports.version = version;
-exports.versions = {};
-exports.config = {};
-exports.arch = architecture;
-exports.platform = platform;
-exports.exit = exit;
-
-/**
- * Partial support
- */
-
-// An alias to `setTimeout(fn, 0)`, which isn't the same as node's `nextTick`,
-// but atleast ensures it'll occur asynchronously
-exports.nextTick = (callback) => setTimeout(callback, 0);
-
-/**
- * Unsupported
- */
-
-exports.maxTickDepth = 1000;
-exports.pid = 0;
-exports.title = "";
-exports.stdin = {};
-exports.argv = [];
-exports.execPath = "";
-exports.execArgv = [];
-exports.abort = function () {};
-exports.chdir = function () {};
-exports.cwd = function () {};
-exports.env = {};
-exports.getgid = function () {};
-exports.setgid = function () {};
-exports.getuid = function () {};
-exports.setuid = function () {};
-exports.getgroups = function () {};
-exports.setgroups = function () {};
-exports.initgroups = function () {};
-exports.kill = function () {};
-exports.memoryUsage = function () {};
-exports.umask = function () {};
-exports.uptime = function () {};
-exports.hrtime = function () {};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/runtime.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci } = require("chrome");
-const runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
-
-exports.inSafeMode = runtime.inSafeMode;
-exports.OS = runtime.OS;
-exports.processType = runtime.processType;
-exports.widgetToolkit = runtime.widgetToolkit;
-exports.processID = runtime.processID;
-
-// Attempt to access `XPCOMABI` may throw exception, in which case exported
-// `XPCOMABI` will be set to `null`.
-// https://mxr.mozilla.org/mozilla-central/source/toolkit/xre/nsAppRunner.cpp#732
-try {
-  exports.XPCOMABI = runtime.XPCOMABI;
-}
-catch (error) {
-  exports.XPCOMABI = null;
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/unload.js
+++ /dev/null
@@ -1,104 +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/. */
-
-// Parts of this module were taken from narwhal:
-//
-// http://narwhaljs.org
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cu } = require('chrome');
-const { on, off } = require('./events');
-const unloadSubject = require('@loader/unload');
-
-const observers = [];
-const unloaders = [];
-
-function WeakObserver(inner) {
-  this._inner = Cu.getWeakReference(inner);
-}
-
-Object.defineProperty(WeakObserver.prototype, 'value', {
-  get: function() { this._inner.get() }
-});
-
-var when = exports.when = function when(observer, opts) {
-  opts = opts || {};
-  for (var i = 0; i < observers.length; ++i) {
-    if (observers[i] === observer || observers[i].value === observer) {
-      return;
-    }
-  }
-  if (opts.weak) {
-    observers.unshift(new WeakObserver(observer));
-  } else {
-    observers.unshift(observer);
-  }
-};
-
-var ensure = exports.ensure = function ensure(obj, destructorName) {
-  if (!destructorName)
-    destructorName = "unload";
-  if (!(destructorName in obj))
-    throw new Error("object has no '" + destructorName + "' property");
-
-  let called = false;
-  let originalDestructor = obj[destructorName];
-
-  function unloadWrapper(reason) {
-    if (!called) {
-      called = true;
-      let index = unloaders.indexOf(unloadWrapper);
-      if (index == -1)
-        throw new Error("internal error: unloader not found");
-      unloaders.splice(index, 1);
-      originalDestructor.call(obj, reason);
-      originalDestructor = null;
-      destructorName = null;
-      obj = null;
-    }
-  };
-
-  // TODO: Find out why the order is inverted here. It seems that
-  // it may be causing issues!
-  unloaders.push(unloadWrapper);
-
-  obj[destructorName] = unloadWrapper;
-};
-
-function unload(reason) {
-  observers.forEach(function(observer) {
-    try {
-      if (observer instanceof WeakObserver) {
-        observer = observer.value;
-      }
-      if (typeof observer === 'function') {
-        observer(reason);
-      }
-    }
-    catch (error) {
-      console.exception(error);
-    }
-  });
-}
-
-when(function(reason) {
-  unloaders.slice().forEach(function(unloadWrapper) {
-    unloadWrapper(reason);
-  });
-});
-
-on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
-  // If this loader is unload then `subject.wrappedJSObject` will be
-  // `destructor`.
-  if (subject.wrappedJSObject === unloadSubject) {
-    off('sdk:loader:destroy', onunload);
-    unload(reason);
-  }
-// Note that we use strong reference to listener here to make sure it's not
-// GC-ed, which may happen otherwise since nothing keeps reference to `onunolad`
-// function.
-}, true);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/xul-app.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { XulApp } = require("./xul-app.jsm");
-
-Object.keys(XulApp).forEach(k => exports[k] = XulApp[k]);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/xul-app.jsm
+++ /dev/null
@@ -1,242 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-this.EXPORTED_SYMBOLS = [ "XulApp" ];
-
-var { classes: Cc, interfaces: Ci } = Components;
-
-var exports = {};
-this.XulApp = exports;
-
-var appInfo;
-
-// NOTE: below is required to avoid failing xpcshell tests,
-//       which do not implement nsIXULAppInfo
-// See Bug 1114752 https://bugzilla.mozilla.org/show_bug.cgi?id=1114752
-try {
- appInfo = Cc["@mozilla.org/xre/app-info;1"]
-              .getService(Ci.nsIXULAppInfo);
-}
-catch (e) {
-  // xpcshell test case
-  appInfo = {};
-}
-var vc = Cc["@mozilla.org/xpcom/version-comparator;1"]
-         .getService(Ci.nsIVersionComparator);
-
-var ID = exports.ID = appInfo.ID;
-var name = exports.name = appInfo.name;
-var version = exports.version = appInfo.version;
-var platformVersion = exports.platformVersion = appInfo.platformVersion;
-
-// The following mapping of application names to GUIDs was taken from:
-//
-//   https://addons.mozilla.org/en-US/firefox/pages/appversions
-//
-// Using the GUID instead of the app's name is preferable because sometimes
-// re-branded versions of a product have different names: for instance,
-// Firefox, Minefield, Iceweasel, and Shiretoko all have the same
-// GUID.
-
-var ids = exports.ids = {
-  Firefox: "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}",
-  Mozilla: "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}",
-  SeaMonkey: "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}",
-  Fennec: "{aa3c5121-dab2-40e2-81ca-7ea25febc110}",
-  Thunderbird: "{3550f703-e582-4d05-9a08-453d09bdfdc6}",
-  Instantbird: "{33cb9019-c295-46dd-be21-8c4936574bee}"
-};
-
-function is(name) {
-  if (!(name in ids))
-    throw new Error("Unkown Mozilla Application: " + name);
-  return ID == ids[name];
-};
-exports.is = is;
-
-function isOneOf(names) {
-  for (var i = 0; i < names.length; i++)
-    if (is(names[i]))
-      return true;
-  return false;
-};
-exports.isOneOf = isOneOf;
-
-/**
- * Use this to check whether the given version (e.g. xulApp.platformVersion)
- * is in the given range. Versions must be in version comparator-compatible
- * format. See MDC for details:
- * https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIVersionComparator
- */
-var versionInRange = exports.versionInRange =
-function versionInRange(version, lowInclusive, highExclusive) {
-  return (vc.compare(version, lowInclusive) >= 0) &&
-         (vc.compare(version, highExclusive) < 0);
-}
-
-const reVersionRange = /^((?:<|>)?=?)?\s*((?:\d+[\S]*)|\*)(?:\s+((?:<|>)=?)?(\d+[\S]+))?$/;
-const reOnlyInifinity = /^[<>]?=?\s*[*x]$/;
-const reSubInfinity = /\.[*x]/g;
-const reHyphenRange = /^(\d+.*?)\s*-\s*(\d+.*?)$/;
-const reRangeSeparator = /\s*\|\|\s*/;
-
-const compares = {
-  "=": function (c) { return c === 0 },
-  ">=": function (c) { return c >= 0 },
-  "<=": function (c) { return c <= 0},
-  "<": function (c) { return c < 0 },
-  ">": function (c) { return c > 0 }
-}
-
-function normalizeRange(range) {
-    return range
-        .replace(reOnlyInifinity, "")
-        .replace(reSubInfinity, ".*")
-        .replace(reHyphenRange, ">=$1 <=$2")
-}
-
-/**
- * Compare the versions given, using the comparison operator provided.
- * Internal use only.
- *
- * @example
- *  compareVersion("1.2", "<=", "1.*") // true
- *
- * @param {String} version
- *  A version to compare
- *
- * @param {String} comparison
- *  The comparison operator
- *
- * @param {String} compareVersion
- *  A version to compare
- */
-function compareVersion(version, comparison, compareVersion) {
-  let hasWildcard = compareVersion.indexOf("*") !== -1;
-
-  comparison = comparison || "=";
-
-  if (hasWildcard) {
-    switch (comparison) {
-      case "=":
-        let zeroVersion = compareVersion.replace(reSubInfinity, ".0");
-        return versionInRange(version, zeroVersion, compareVersion);
-      case ">=":
-        compareVersion = compareVersion.replace(reSubInfinity, ".0");
-        break;
-    }
-  }
-
-  let compare = compares[comparison];
-
-  return typeof compare === "function" && compare(vc.compare(version, compareVersion));
-}
-
-/**
- * Returns `true` if `version` satisfies the `versionRange` given.
- * If only an argument is passed, is used as `versionRange` and compared against
- * `xulApp.platformVersion`.
- *
- * `versionRange` is either a string which has one or more space-separated
- * descriptors, or a range like "fromVersion - toVersion".
- * Version range descriptors may be any of the following styles:
- *
- * - "version" Must match `version` exactly
- * - "=version" Same as just `version`
- * - ">version" Must be greater than `version`
- * - ">=version" Must be greater or equal than `version`
- * - "<version" Must be less than `version`
- * - "<=version" Must be less or equal than `version`
- * - "1.2.x" or "1.2.*" See 'X version ranges' below
- * - "*" or "" (just an empty string) Matches any version
- * - "version1 - version2" Same as ">=version1 <=version2"
- * - "range1 || range2" Passes if either `range1` or `range2` are satisfied
- *
- * For example, these are all valid:
- * - "1.0.0 - 2.9999.9999"
- * - ">=1.0.2 <2.1.2"
- * - ">1.0.2 <=2.3.4"
- * - "2.0.1"
- * - "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
- * - "2.x" (equivalent to "2.*")
- * - "1.2.x" (equivalent to "1.2.*" and ">=1.2.0 <1.3.0")
- */
-function satisfiesVersion(version, versionRange) {
-  if (arguments.length === 1) {
-    versionRange = version;
-    version = appInfo.version;
-  }
-
-  let ranges = versionRange.trim().split(reRangeSeparator);
-
-  return ranges.some(function(range) {
-    range = normalizeRange(range);
-
-    // No versions' range specified means that any version satisfies the
-    // requirements.
-    if (range === "")
-      return true;
-
-    let matches = range.match(reVersionRange);
-
-    if (!matches)
-      return false;
-
-    let [, lowMod, lowVer, highMod, highVer] = matches;
-
-    return compareVersion(version, lowMod, lowVer) && (highVer !== undefined
-      ? compareVersion(version, highMod, highVer)
-      : true);
-  });
-}
-exports.satisfiesVersion = satisfiesVersion;
-
-/**
- * Ensure the current application satisfied the requirements specified in the
- * module given. If not, an exception related to the incompatibility is
- * returned; `null` otherwise.
- *
- * @param {Object} module
- *  The module to check
- * @returns {Error}
- */
-function incompatibility(module) {
-  let { metadata, id } = module;
-
-  // if metadata or engines are not specified we assume compatibility is not
-  // an issue.
-  if (!metadata || !("engines" in metadata))
-    return null;
-
-  let { engines } = metadata;
-
-  if (engines === null || typeof(engines) !== "object")
-    return new Error("Malformed engines' property in metadata");
-
-  let applications = Object.keys(engines);
-
-  let versionRange;
-  applications.forEach(function(name) {
-    if (is(name)) {
-      versionRange = engines[name];
-      // Continue iteration. We want to ensure the module doesn't
-      // contain a typo in the applications' name or some unknown
-      // application - `is` function throws an exception in that case.
-    }
-  });
-
-  if (typeof(versionRange) === "string") {
-    if (satisfiesVersion(versionRange))
-      return null;
-
-    return new Error("Unsupported Application version: The module " + id +
-            " currently supports only version " + versionRange + " of " +
-            name + ".");
-  }
-
-  return new Error("Unsupported Application: The module " + id +
-            " currently supports only " + applications.join(", ") + ".")
-}
-exports.incompatibility = incompatibility;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cu } = require("chrome");
-const { Task } = require("resource://gre/modules/Task.jsm", {});
-const { defer } = require("sdk/core/promise");
-const BaseAssert = require("sdk/test/assert").Assert;
-const { isFunction, isObject, isGenerator } = require("sdk/lang/type");
-const { extend } = require("sdk/util/object");
-
-exports.Assert = BaseAssert;
-
-/**
- * Function takes test `suite` object in CommonJS format and defines all of the
- * tests from that suite and nested suites in a jetpack format on a given
- * `target` object. Optionally third argument `prefix` can be passed to prefix
- * all the test names.
- */
-function defineTestSuite(target, suite, prefix) {
-  prefix = prefix || "";
-  // If suite defines `Assert` that's what `assert` object have to be created
-  // from and passed to a test function (This allows custom assertion functions)
-  // See for details: http://wiki.commonjs.org/wiki/Unit_Testing/1.1
-  let Assert = suite.Assert || BaseAssert;
-  // Going through each item in the test suite and wrapping it into a
-  // Jetpack test format.
-  Object.keys(suite).forEach(function(key) {
-     // If name starts with test then it's a test function or suite.
-    if (key.indexOf("test") === 0) {
-      let test = suite[key];
-
-      // For each test function so we create a wrapper test function in a
-      // jetpack format and copy that to a `target` exports.
-      if (isFunction(test)) {
-
-        // Since names of the test may match across suites we use full object
-        // path as a name to avoid overriding same function.
-        target[prefix + key] = function(options) {
-
-          // Creating `assert` functions for this test.
-          let assert = Assert(options);
-          assert.end = () => options.done();
-
-          // If test function is a generator use a task JS to allow yield-ing
-          // style test runs.
-          if (isGenerator(test)) {
-            options.waitUntilDone();
-            Task.spawn(test.bind(null, assert)).
-                catch(assert.fail).
-                then(assert.end);
-          }
-
-          // If CommonJS test function expects more than one argument
-          // it means that test is async and second argument is a callback
-          // to notify that test is finished.
-          else if (1 < test.length) {
-            // Letting test runner know that test is executed async and
-            // creating a callback function that CommonJS tests will call
-            // once it's done.
-            options.waitUntilDone();
-            test(assert, function() {
-              options.done();
-            });
-          }
-
-          // Otherwise CommonJS test is synchronous so we call it only with
-          // one argument.
-          else {
-            test(assert);
-          }
-        }
-      }
-
-      // If it's an object then it's a test suite containing test function
-      // and / or nested test suites. In that case we just extend prefix used
-      // and call this function to copy and wrap tests from nested suite.
-      else if (isObject(test)) {
-        // We need to clone `tests` instead of modifying it, since it's very
-        // likely that it is frozen (usually test suites imported modules).
-        test = extend(Object.prototype, test, {
-          Assert: test.Assert || Assert
-        });
-        defineTestSuite(target, test, prefix + key + ".");
-      }
-    }
-  });
-}
-
-/**
- * This function is a CommonJS test runner function, but since Jetpack test
- * runner and test format is different from CommonJS this function shims given
- * `exports` with all its tests into a Jetpack test format so that the built-in
- * test runner will be able to run CommonJS test without manual changes.
- */
-exports.run = function run(exports) {
-  // We can't leave old properties on exports since those are test in a CommonJS
-  // format that why we move everything to a new `suite` object.
-  let suite = {};
-  Object.keys(exports).forEach(function(key) {
-    suite[key] = exports[key];
-    delete exports[key];
-  });
-
-  // Now we wrap all the CommonJS tests to a Jetpack format and define
-  // those to a given `exports` object since that where jetpack test runner
-  // will look for them.
-  defineTestSuite(exports, suite);
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/assert.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { isFunction, isNull, isObject, isString,
-        isRegExp, isArray, isDate, isPrimitive,
-        isUndefined, instanceOf, source } = require("../lang/type");
-
-/**
- * The `AssertionError` is defined in assert.
- * @extends Error
- * @example
- *  new assert.AssertionError({
- *    message: message,
- *    actual: actual,
- *    expected: expected
- *  })
- */
-function AssertionError(options) {
-  let assertionError = Object.create(AssertionError.prototype);
-
-  if (isString(options))
-    options = { message: options };
-  if ("actual" in options)
-    assertionError.actual = options.actual;
-  if ("expected" in options)
-    assertionError.expected = options.expected;
-  if ("operator" in options)
-    assertionError.operator = options.operator;
-
-  assertionError.message = options.message;
-  assertionError.stack = new Error().stack;
-  return assertionError;
-}
-AssertionError.prototype = Object.create(Error.prototype, {
-  constructor: { value: AssertionError },
-  name: { value: "AssertionError", enumerable: true },
-  toString: { value: function toString() {
-    let value;
-    if (this.message) {
-      value = this.name + " : " + this.message;
-    }
-    else {
-      value = [
-        this.name + " : ",
-        source(this.expected),
-        this.operator,
-        source(this.actual)
-      ].join(" ");
-    }
-    return value;
-  }}
-});
-exports.AssertionError = AssertionError;
-
-function Assert(logger) {
-  let assert = Object.create(Assert.prototype, { _log: { value: logger }});
-
-  assert.fail = assert.fail.bind(assert);
-  assert.pass = assert.pass.bind(assert);
-
-  return assert;
-}
-
-Assert.prototype = {
-  fail: function fail(e) {
-    if (!e || typeof(e) !== 'object') {
-      this._log.fail(e);
-      return;
-    }
-    let message = e.message;
-    try {
-      if ('operator' in e) {
-        message += [
-          " -",
-          source(e.actual),
-          e.operator,
-          source(e.expected)
-        ].join(" ");
-      }
-    }
-    catch(e) {}
-    this._log.fail(message);
-  },
-  pass: function pass(message) {
-    this._log.pass(message);
-    return true;
-  },
-  error: function error(e) {
-    this._log.exception(e);
-  },
-  ok: function ok(value, message) {
-    if (!!!value) {
-      this.fail({
-        actual: value,
-        expected: true,
-        message: message,
-        operator: "=="
-      });
-      return false;
-    }
-
-    this.pass(message);
-    return true;
-  },
-
-  /**
-   * The equality assertion tests shallow, coercive equality with `==`.
-   * @example
-   *    assert.equal(1, 1, "one is one");
-   */
-  equal: function equal(actual, expected, message) {
-    if (actual == expected) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "=="
-    });
-    return false;
-  },
-
-  /**
-   * The non-equality assertion tests for whether two objects are not equal
-   * with `!=`.
-   * @example
-   *    assert.notEqual(1, 2, "one is not two");
-   */
-  notEqual: function notEqual(actual, expected, message) {
-    if (actual != expected) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "!=",
-    });
-    return false;
-  },
-
-  /**
-   * The equivalence assertion tests a deep (with `===`) equality relation.
-   * @example
-   *    assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects")
-   */
-   deepEqual: function deepEqual(actual, expected, message) {
-    if (isDeepEqual(actual, expected)) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "deepEqual"
-    });
-    return false;
-  },
-
-  /**
-   * The non-equivalence assertion tests for any deep (with `===`) inequality.
-   * @example
-   *    assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }),
-   *                        "object's inherit from different prototypes");
-   */
-  notDeepEqual: function notDeepEqual(actual, expected, message) {
-    if (!isDeepEqual(actual, expected)) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "notDeepEqual"
-    });
-    return false;
-  },
-
-  /**
-   * The strict equality assertion tests strict equality, as determined by
-   * `===`.
-   * @example
-   *    assert.strictEqual(null, null, "`null` is `null`")
-   */
-  strictEqual: function strictEqual(actual, expected, message) {
-    if (actual === expected) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "==="
-    });
-    return false;
-  },
-
-  /**
-   * The strict non-equality assertion tests for strict inequality, as
-   * determined by `!==`.
-   * @example
-   *    assert.notStrictEqual(null, undefined, "`null` is not `undefined`");
-   */
-  notStrictEqual: function notStrictEqual(actual, expected, message) {
-    if (actual !== expected) {
-      this.pass(message);
-      return true;
-    }
-
-    this.fail({
-      actual: actual,
-      expected: expected,
-      message: message,
-      operator: "!=="
-    });
-    return false;
-  },
-
-  /**
-   * The assertion whether or not given `block` throws an exception. If optional
-   * `Error` argument is provided and it's type of function thrown error is
-   * asserted to be an instance of it, if type of `Error` is string then message
-   * of throw exception is asserted to contain it.
-   * @param {Function} block
-   *    Function that is expected to throw.
-   * @param {Error|RegExp} [Error]
-   *    Error constructor that is expected to be thrown or a string that
-   *    must be contained by a message of the thrown exception, or a RegExp
-   *    matching a message of the thrown exception.
-   * @param {String} message
-   *    Description message
-   *
-   * @examples
-   *
-   *    assert.throws(function block() {
-   *      doSomething(4)
-   *    }, "Object is expected", "Incorrect argument is passed");
-   *
-   *    assert.throws(function block() {
-   *      Object.create(5)
-   *    }, TypeError, "TypeError is thrown");
-   */
-  throws: function throws(block, Error, message) {
-    let threw = false;
-    let exception = null;
-
-    // If third argument is not provided and second argument is a string it
-    // means that optional `Error` argument was not passed, so we shift
-    // arguments.
-    if (isString(Error) && isUndefined(message)) {
-      message = Error;
-      Error = undefined;
-    }
-
-    // Executing given `block`.
-    try {
-      block();
-    }
-    catch (e) {
-      threw = true;
-      exception = e;
-    }
-
-    // If exception was thrown and `Error` argument was not passed assert is
-    // passed.
-    if (threw && (isUndefined(Error) ||
-                 // If passed `Error` is RegExp using it's test method to
-                 // assert thrown exception message.
-                 (isRegExp(Error) && (Error.test(exception.message) || Error.test(exception.toString()))) ||
-                 // If passed `Error` is a constructor function testing if
-                 // thrown exception is an instance of it.
-                 (isFunction(Error) && instanceOf(exception, Error))))
-    {
-      this.pass(message);
-      return true;
-    }
-
-    // Otherwise we report assertion failure.
-    let failure = {
-      message: message,
-      operator: "matches"
-    };
-
-    if (exception) {
-      failure.actual = exception.message || exception.toString();
-    }
-
-    if (Error) {
-      failure.expected = Error.toString();
-    }
-
-    this.fail(failure);
-    return false;
-  }
-};
-exports.Assert = Assert;
-
-function isDeepEqual(actual, expected) {
-  // 7.1. All identical values are equivalent, as determined by ===.
-  if (actual === expected) {
-    return true;
-  }
-
-  // 7.2. If the expected value is a Date object, the actual value is
-  // equivalent if it is also a Date object that refers to the same time.
-  else if (isDate(actual) && isDate(expected)) {
-    return actual.getTime() === expected.getTime();
-  }
-
-  // XXX specification bug: this should be specified
-  else if (isPrimitive(actual) || isPrimitive(expected)) {
-    return expected === actual;
-  }
-
-  // 7.3. Other pairs that do not both pass typeof value == "object",
-  // equivalence is determined by ==.
-  else if (!isObject(actual) && !isObject(expected)) {
-    return actual == expected;
-  }
-
-  // 7.4. For all other Object pairs, including Array objects, equivalence is
-  // determined by having the same number of owned properties (as verified
-  // with Object.prototype.hasOwnProperty.call), the same set of keys
-  // (although not necessarily the same order), equivalent values for every
-  // corresponding key, and an identical "prototype" property. Note: this
-  // accounts for both named and indexed properties on Arrays.
-  else {
-    return actual.prototype === expected.prototype &&
-           isEquivalent(actual, expected);
-  }
-}
-
-function isEquivalent(a, b, stack) {
-  let aKeys = Object.keys(a);
-  let bKeys = Object.keys(b);
-
-  return aKeys.length === bKeys.length &&
-          isArrayEquivalent(aKeys.sort(), bKeys.sort()) &&
-          aKeys.every(function(key) {
-            return isDeepEqual(a[key], b[key], stack)
-          });
-}
-
-function isArrayEquivalent(a, b, stack) {
-  return isArray(a) && isArray(b) &&
-         a.every(function(value, index) {
-           return isDeepEqual(value, b[index]);
-         });
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/harness.js
+++ /dev/null
@@ -1,606 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cc, Ci, Cu } = require("chrome");
-const { Loader } = require('./loader');
-const { serializeStack, parseStack  } = require("toolkit/loader");
-const { setTimeout } = require('../timers');
-const { PlainTextConsole } = require("../console/plain-text");
-const { when: unload } = require("../system/unload");
-lazyRequire(this, "../console/traceback", "format", "fromException");
-const system = require("../system");
-const { defer } = require('../core/promise');
-const { extend } = require('../core/heritage');
-
-// Trick manifest builder to make it think we need these modules ?
-const unit = require("../deprecated/unit-test");
-const test = require("../../test");
-const url = require("../url");
-
-function emptyPromise() {
-  let { promise, resolve } = defer();
-  resolve();
-  return promise;
-}
-
-var cService = Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService);
-
-// The console used to log messages
-var testConsole;
-
-// Cuddlefish loader in which we load and execute tests.
-var loader;
-
-// Function to call when we're done running tests.
-var onDone;
-
-// Function to print text to a console, w/o CR at the end.
-var print;
-
-// How many more times to run all tests.
-var iterationsLeft;
-
-// Whether to report memory profiling information.
-var profileMemory;
-
-// Whether we should stop as soon as a test reports a failure.
-var stopOnError;
-
-// Function to call to retrieve a list of tests to execute
-var findAndRunTests;
-
-// Combined information from all test runs.
-var results;
-
-// A list of the compartments and windows loaded after startup
-var startLeaks;
-
-// JSON serialization of last memory usage stats; we keep it stringified
-// so we don't actually change the memory usage stats (in terms of objects)
-// of the JSRuntime we're profiling.
-var lastMemoryUsage;
-
-function analyzeRawProfilingData(data) {
-  var graph = data.graph;
-  var shapes = {};
-
-  // Convert keys in the graph from strings to ints.
-  // TODO: Can we get rid of this ridiculousness?
-  var newGraph = {};
-  for (id in graph) {
-    newGraph[parseInt(id)] = graph[id];
-  }
-  graph = newGraph;
-
-  var modules = 0;
-  var moduleIds = [];
-  var moduleObjs = {UNKNOWN: 0};
-  for (let name in data.namedObjects) {
-    moduleObjs[name] = 0;
-    moduleIds[data.namedObjects[name]] = name;
-    modules++;
-  }
-
-  var count = 0;
-  for (id in graph) {
-    var parent = graph[id].parent;
-    while (parent) {
-      if (parent in moduleIds) {
-        var name = moduleIds[parent];
-        moduleObjs[name]++;
-        break;
-      }
-      if (!(parent in graph)) {
-        moduleObjs.UNKNOWN++;
-        break;
-      }
-      parent = graph[parent].parent;
-    }
-    count++;
-  }
-
-  print("\nobject count is " + count + " in " + modules + " modules" +
-        " (" + data.totalObjectCount + " across entire JS runtime)\n");
-  if (lastMemoryUsage) {
-    var last = JSON.parse(lastMemoryUsage);
-    var diff = {
-      moduleObjs: dictDiff(last.moduleObjs, moduleObjs),
-      totalObjectClasses: dictDiff(last.totalObjectClasses,
-                                   data.totalObjectClasses)
-    };
-
-    for (let name in diff.moduleObjs)
-      print("  " + diff.moduleObjs[name] + " in " + name + "\n");
-    for (let name in diff.totalObjectClasses)
-      print("  " + diff.totalObjectClasses[name] + " instances of " +
-            name + "\n");
-  }
-  lastMemoryUsage = JSON.stringify(
-    {moduleObjs: moduleObjs,
-     totalObjectClasses: data.totalObjectClasses}
-  );
-}
-
-function dictDiff(last, curr) {
-  var diff = {};
-
-  for (let name in last) {
-    var result = (curr[name] || 0) - last[name];
-    if (result)
-      diff[name] = (result > 0 ? "+" : "") + result;
-  }
-  for (let name in curr) {
-    var result = curr[name] - (last[name] || 0);
-    if (result)
-      diff[name] = (result > 0 ? "+" : "") + result;
-  }
-  return diff;
-}
-
-var gWeakrefInfo;
-
-function showResults() {
-  let { promise, resolve } = defer();
-
-  if (gWeakrefInfo) {
-    gWeakrefInfo.forEach(
-      function(info) {
-        var ref = info.weakref.get();
-        if (ref !== null) {
-          var data = ref.__url__ ? ref.__url__ : ref;
-          var warning = data == "[object Object]"
-            ? "[object " + data.constructor.name + "(" +
-              Object.keys(data).join(", ") + ")]"
-            : data;
-          console.warn("LEAK", warning, info.bin);
-        }
-      }
-    );
-  }
-
-  onDone(results);
-
-  resolve();
-  return promise;
-}
-
-function cleanup() {
-  let coverObject = {};
-  try {
-    loader.unload();
-
-    if (loader.globals.console.errorsLogged && !results.failed) {
-      results.failed++;
-      console.error("warnings and/or errors were logged.");
-    }
-
-    if (consoleListener.errorsLogged && !results.failed) {
-      console.warn(consoleListener.errorsLogged + " " +
-                   "warnings or errors were logged to the " +
-                   "platform's nsIConsoleService, which could " +
-                   "be of no consequence; however, they could also " +
-                   "be indicative of aberrant behavior.");
-    }
-
-    // read the code coverage object, if it exists, from CoverJS-moz
-    if (typeof loader.globals.global == "object") {
-      coverObject = loader.globals.global['__$coverObject'] || {};
-    }
-
-    consoleListener.errorsLogged = 0;
-    loader = null;
-
-    consoleListener.unregister();
-
-    Cu.forceGC();
-  }
-  catch (e) {
-    results.failed++;
-    console.error("unload.send() threw an exception.");
-    console.exception(e);
-  };
-
-  setTimeout(showResults, 1);
-
-  // dump the coverobject
-  if (Object.keys(coverObject).length){
-    const self = require('sdk/self');
-    const {pathFor} = require("sdk/system");
-    let file = require('sdk/io/file');
-    const {env} = require('sdk/system/environment');
-    console.log("CWD:", env.PWD);
-    let out = file.join(env.PWD,'coverstats-'+self.id+'.json');
-    console.log('coverstats:', out);
-    let outfh = file.open(out,'w');
-    outfh.write(JSON.stringify(coverObject,null,2));
-    outfh.flush();
-    outfh.close();
-  }
-}
-
-function getPotentialLeaks() {
-  Cu.forceGC();
-
-  // Things we can assume are part of the platform and so aren't leaks
-  let GOOD_BASE_URLS = [
-    "chrome://",
-    "resource:///",
-    "resource://app/",
-    "resource://gre/",
-    "resource://gre-resources/",
-    "resource://pdf.js/",
-    "resource://pdf.js.components/",
-    "resource://services-common/",
-    "resource://services-crypto/",
-    "resource://services-sync/"
-  ];
-
-  let ioService = Cc["@mozilla.org/network/io-service;1"].
-                 getService(Ci.nsIIOService);
-  let uri = ioService.newURI("chrome://global/content/", "UTF-8");
-  let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
-                  getService(Ci.nsIChromeRegistry);
-  uri = chromeReg.convertChromeURL(uri);
-  let spec = uri.spec;
-  let pos = spec.indexOf("!/");
-  GOOD_BASE_URLS.push(spec.substring(0, pos + 2));
-
-  let zoneRegExp = new RegExp("^explicit/js-non-window/zones/zone[^/]+/compartment\\((.+)\\)");
-  let compartmentRegexp = new RegExp("^explicit/js-non-window/compartments/non-window-global/compartment\\((.+)\\)/");
-  let compartmentDetails = new RegExp("^([^,]+)(?:, (.+?))?(?: \\(from: (.*)\\))?$");
-  let windowRegexp = new RegExp("^explicit/window-objects/top\\((.*)\\)/active");
-  let windowDetails = new RegExp("^(.*), id=.*$");
-
-  function isPossibleLeak(item) {
-    if (!item.location)
-      return false;
-
-    for (let url of GOOD_BASE_URLS) {
-      if (item.location.substring(0, url.length) == url) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  let compartments = {};
-  let windows = {};
-  function logReporter(process, path, kind, units, amount, description) {
-    let matches;
-
-    if ((matches = compartmentRegexp.exec(path)) || (matches = zoneRegExp.exec(path))) {
-      if (matches[1] in compartments)
-        return;
-
-      let details = compartmentDetails.exec(matches[1]);
-      if (!details) {
-        console.error("Unable to parse compartment detail " + matches[1]);
-        return;
-      }
-
-      let item = {
-        path: matches[1],
-        principal: details[1],
-        location: details[2] ? details[2].replace(/\\/g, "/") : undefined,
-        source: details[3] ? details[3].split(" -> ").reverse() : undefined,
-        toString: function() {
-          return this.location;
-        }
-      };
-
-      if (!isPossibleLeak(item))
-        return;
-
-      compartments[matches[1]] = item;
-      return;
-    }
-
-    if ((matches = windowRegexp.exec(path))) {
-      if (matches[1] in windows)
-        return;
-
-      let details = windowDetails.exec(matches[1]);
-      if (!details) {
-        console.error("Unable to parse window detail " + matches[1]);
-        return;
-      }
-
-      let item = {
-        path: matches[1],
-        location: details[1].replace(/\\/g, "/"),
-        source: [details[1].replace(/\\/g, "/")],
-        toString: function() {
-          return this.location;
-        }
-      };
-
-      if (!isPossibleLeak(item))
-        return;
-
-      windows[matches[1]] = item;
-    }
-  }
-
-  Cc["@mozilla.org/memory-reporter-manager;1"]
-    .getService(Ci.nsIMemoryReporterManager)
-    .getReportsForThisProcess(logReporter, null, /* anonymize = */ false);
-
-  return { compartments: compartments, windows: windows };
-}
-
-function nextIteration(tests) {
-  if (tests) {
-    results.passed += tests.passed;
-    results.failed += tests.failed;
-
-    let testRun = [];
-    for (let test of tests.testRunSummary) {
-      let testCopy = {};
-      for (let info in test) {
-        testCopy[info] = test[info];
-      }
-      testRun.push(testCopy);
-    }
-
-    results.testRuns.push(testRun);
-    iterationsLeft--;
-
-    checkForEnd();
-  }
-  else {
-    checkForEnd();
-  }
-}
-
-function checkForEnd() {
-  if (iterationsLeft && (!stopOnError || results.failed == 0)) {
-    // Pass the loader which has a hooked console that doesn't dispatch
-    // errors to the JS console and avoid firing false alarm in our
-    // console listener
-    findAndRunTests(loader, nextIteration);
-  }
-  else {
-    setTimeout(cleanup, 0);
-  }
-}
-
-var POINTLESS_ERRORS = [
-  'Invalid chrome URI:',
-  'OpenGL LayerManager Initialized Succesfully.',
-  '[JavaScript Error: "TelemetryStopwatch:',
-  'reference to undefined property',
-  '[JavaScript Error: "The character encoding of the HTML document was ' +
-    'not declared.',
-  '[Javascript Warning: "Error: Failed to preserve wrapper of wrapped ' +
-    'native weak map key',
-  '[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;
-  },
-
-  unregister: function() {
-    if (!this.registered)
-      return;
-    cService.unregisterListener(this);
-    this.registered = false;
-  },
-
-  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 = POINTLESS_ERRORS.filter(err => message.indexOf(err) >= 0);
-    if (pointless.length == 0 && message)
-      testConsole.log(message);
-  }
-};
-
-function TestRunnerConsole(base, options) {
-  let proto = extend(base, {
-    errorsLogged: 0,
-    warn: function warn() {
-      this.errorsLogged++;
-      base.warn.apply(base, arguments);
-    },
-    error: function error() {
-      this.errorsLogged++;
-      base.error.apply(base, arguments);
-    },
-    info: function info(first) {
-      if (options.verbose)
-        base.info.apply(base, arguments);
-      else
-        if (first == "pass:")
-          print(".");
-    },
-  });
-  return Object.create(proto);
-}
-
-function stringify(arg) {
-  try {
-    return String(arg);
-  }
-  catch(ex) {
-    return "<toString() error>";
-  }
-}
-
-function stringifyArgs(args) {
-  return Array.map(args, stringify).join(" ");
-}
-
-function TestRunnerTinderboxConsole(base, options) {
-  this.base = base;
-  this.print = options.print;
-  this.verbose = options.verbose;
-  this.errorsLogged = 0;
-
-  // Binding all the public methods to an instance so that they can be used
-  // as callback / listener functions straightaway.
-  this.log = this.log.bind(this);
-  this.info = this.info.bind(this);
-  this.warn = this.warn.bind(this);
-  this.error = this.error.bind(this);
-  this.debug = this.debug.bind(this);
-  this.exception = this.exception.bind(this);
-  this.trace = this.trace.bind(this);
-};
-
-TestRunnerTinderboxConsole.prototype = {
-  testMessage: function testMessage(pass, expected, test, message) {
-    let type = "TEST-";
-    if (expected) {
-      if (pass)
-        type += "PASS";
-      else
-        type += "KNOWN-FAIL";
-    }
-    else {
-      this.errorsLogged++;
-      if (pass)
-        type += "UNEXPECTED-PASS";
-      else
-        type += "UNEXPECTED-FAIL";
-    }
-
-    this.print(type + " | " + test + " | " + message + "\n");
-    if (!expected)
-      this.trace();
-  },
-
-  log: function log() {
-    this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
-  },
-
-  info: function info(first) {
-    this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
-  },
-
-  warn: function warn() {
-    this.errorsLogged++;
-    this.print("TEST-UNEXPECTED-FAIL | " + stringifyArgs(arguments) + "\n");
-  },
-
-  error: function error() {
-    this.errorsLogged++;
-    this.print("TEST-UNEXPECTED-FAIL | " + stringifyArgs(arguments) + "\n");
-    this.base.error.apply(this.base, arguments);
-  },
-
-  debug: function debug() {
-    this.print("TEST-INFO | " + stringifyArgs(arguments) + "\n");
-  },
-
-  exception: function exception(e) {
-    this.print("An exception occurred.\n" +
-               require("../console/traceback").format(e) + "\n" + e + "\n");
-  },
-
-  trace: function trace() {
-    var traceback = require("../console/traceback");
-    var stack = traceback.get();
-    stack.splice(-1, 1);
-    this.print("TEST-INFO | " + stringify(traceback.format(stack)) + "\n");
-  }
-};
-
-var runTests = exports.runTests = function runTests(options) {
-  iterationsLeft = options.iterations;
-  profileMemory = options.profileMemory;
-  stopOnError = options.stopOnError;
-  onDone = options.onDone;
-  print = options.print;
-  findAndRunTests = options.findAndRunTests;
-
-  results = {
-    passed: 0,
-    failed: 0,
-    testRuns: []
-  };
-
-  try {
-    consoleListener.register();
-    print("Running tests on " + system.name + " " + system.version +
-          "/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, {
-      console: testConsole,
-      global: {} // useful for storing things like coverage testing.
-    });
-
-    // Load these before getting initial leak stats as they will still be in
-    // memory when we check later
-    require("../deprecated/unit-test");
-    require("../deprecated/unit-test-finder");
-    if (profileMemory)
-      startLeaks = getPotentialLeaks();
-
-    nextIteration();
-  } catch (e) {
-    let frames = fromException(e).reverse().reduce(function(frames, frame) {
-      if (frame.fileName.split("/").pop() === "unit-test-finder.js")
-        frames.done = true
-      if (!frames.done) frames.push(frame)
-
-      return frames
-    }, [])
-
-    let prototype = typeof(e) === "object" ? e.constructor.prototype :
-                    Error.prototype;
-    let stack = serializeStack(frames.reverse());
-
-    let error = Object.create(prototype, {
-      message: { value: e.message, writable: true, configurable: true },
-      fileName: { value: e.fileName, writable: true, configurable: true },
-      lineNumber: { value: e.lineNumber, writable: true, configurable: true },
-      stack: { value: stack, writable: true, configurable: true },
-      toString: { value: () => String(e), writable: true, configurable: true },
-    });
-
-    print("Error: " + error + " \n " + format(error));
-    onDone({passed: 0, failed: 1});
-  }
-};
-
-unload(_ => consoleListener.unregister());
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/loader.js
+++ /dev/null
@@ -1,123 +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 { resolveURI, Require,
-        unload, override, descriptor } = require('../../toolkit/loader');
-const { ensure } = require('../system/unload');
-const addonWindow = require('../addon/window');
-const { PlainTextConsole } = require('sdk/console/plain-text');
-
-var defaultGlobals = override(require('../system/globals'), {
-  console: console
-});
-
-function CustomLoader(module, globals, packaging, overrides={}) {
-  let options = packaging || require("@loader/options");
-  options = override(options, {
-    id: overrides.id || options.id,
-    globals: override(defaultGlobals, globals || {}),
-    modules: override(override(options.modules || {}, overrides.modules || {}), {
-      'sdk/addon/window': addonWindow
-    })
-  });
-
-  let loaderModule = options.isNative ? '../../toolkit/loader' : '../loader/cuddlefish';
-  let { Loader } = require(loaderModule);
-  let loader = Loader(options);
-  let wrapper = Object.create(loader, descriptor({
-    require: Require(loader, module),
-    sandbox: function(id) {
-      let requirement = loader.resolve(id, module.id);
-      if (!requirement)
-        requirement = id;
-      let uri = resolveURI(requirement, loader.mapping);
-      return loader.sandboxes[uri];
-    },
-    unload: function(reason) {
-      unload(loader, reason);
-    }
-  }));
-  ensure(wrapper);
-  return wrapper;
-};
-exports.Loader = CustomLoader;
-
-function HookedPlainTextConsole(hook, print, innerID) {
-  this.log = hook.bind(null, "log", innerID);
-  this.info = hook.bind(null, "info", innerID);
-  this.warn = hook.bind(null, "warn", innerID);
-  this.error = hook.bind(null, "error", innerID);
-  this.debug = hook.bind(null, "debug", innerID);
-  this.exception = hook.bind(null, "exception", innerID);
-  this.time = hook.bind(null, "time", innerID);
-  this.timeEnd = hook.bind(null, "timeEnd", innerID);
-
-  this.__exposedProps__ = {
-    log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw",
-    exception: "rw", time: "rw", timeEnd: "rw"
-  };
-}
-
-// Creates a custom loader instance whose console module is hooked in order
-// to avoid printing messages to the console, and instead, expose them in the
-// returned `messages` array attribute
-exports.LoaderWithHookedConsole = function (module, callback) {
-  let messages = [];
-  function hook(type, innerID, msg) {
-    messages.push({ type: type, msg: msg, innerID: innerID });
-    if (callback)
-      callback(type, msg, innerID);
-  }
-
-  return {
-    loader: CustomLoader(module, {
-      console: new HookedPlainTextConsole(hook, null, null)
-    }, null, {
-      modules: {
-        'sdk/console/plain-text': {
-          PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
-        }
-      }
-    }),
-    messages: messages
-  };
-}
-
-// Same than LoaderWithHookedConsole with lower level, instead we get what is
-// actually printed to the command line console
-exports.LoaderWithHookedConsole2 = function (module, callback) {
-  let messages = [];
-  return {
-    loader: CustomLoader(module, {
-      console: new PlainTextConsole(function (msg) {
-        messages.push(msg);
-        if (callback)
-          callback(msg);
-      })
-    }),
-    messages: messages
-  };
-}
-
-// Creates a custom loader with a filtered console. The callback is passed every
-// console message type and message and if it returns false the message will
-// not be logged normally
-exports.LoaderWithFilteredConsole = function (module, callback) {
-  function hook(type, innerID, msg) {
-    if (callback && callback(type, msg, innerID) == false)
-      return;
-    console[type](msg);
-  }
-
-  return CustomLoader(module, {
-    console: new HookedPlainTextConsole(hook, null, null)
-  }, null, {
-    modules: {
-      'sdk/console/plain-text': {
-        PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
-      }
-    }
-  });
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/options.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/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const options = require("@test/options");
-const { id } = require("../self");
-const { get } = require("../preferences/service");
-
-const readPref = (key) => get("extensions." + id + ".sdk." + key);
-
-exports.iterations = readPref("test.iterations") || options.iterations;
-exports.filter = readPref("test.filter") || options.filter;
-exports.profileMemory = readPref("profile.memory") || options.profileMemory;
-exports.stopOnError = readPref("test.stop") || options.stopOnError;
-exports.keepOpen = readPref("test.keepOpen") || false;
-exports.verbose = (readPref("output.logLevel") == "verbose") || options.verbose;
-exports.parseable = (readPref("output.format") == "tbpl") || options.parseable;
-exports.checkMemory = readPref("profile.leaks") || options.check_memory;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/test/utils.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-lazyRequire(this, '../core/promise', "defer");
-lazyRequire(this, '../timers', "setInterval", "clearInterval");
-lazyRequire(this, "../tabs/utils", "getTabs", "closeTab");
-lazyRequire(this, "../window/utils", {"windows": "getWindows"});
-lazyRequire(this, "../window/helpers", {"close": "closeWindow"});
-lazyRequire(this, "../lang/type", "isGenerator");
-lazyRequire(this, "../system/environment", "env");
-const { Task } = require("resource://gre/modules/Task.jsm");
-
-const getTestNames = (exports) =>
-  Object.keys(exports).filter(name => /^test/.test(name));
-
-const isTestAsync = ({length}) => length > 1;
-const isHelperAsync = ({length}) => length > 2;
-
-/*
- * Takes an `exports` object of a test file and a function `beforeFn`
- * to be run before each test. `beforeFn` is called with a `name` string
- * as the first argument of the test name, and may specify a second
- * argument function `done` to indicate that this function should
- * resolve asynchronously
- */
-function before (exports, beforeFn) {
-  getTestNames(exports).map(name => {
-    let testFn = exports[name];
-
-    // GENERATOR TESTS
-    if (isGenerator(testFn) && isGenerator(beforeFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(beforeFn.bind(null, name, assert));
-        yield Task.spawn(testFn.bind(null, assert));
-      }
-    }
-    else if (isGenerator(testFn) && !isHelperAsync(beforeFn)) {
-      exports[name] = function*(assert) {
-        beforeFn(name, assert);
-        yield Task.spawn(testFn.bind(null, assert));
-      }
-    }
-    else if (isGenerator(testFn) && isHelperAsync(beforeFn)) {
-      exports[name] = function*(assert) {
-        yield new Promise(resolve => beforeFn(name, assert, resolve));
-        yield Task.spawn(testFn.bind(null, assert));
-      }
-    }
-    // SYNC TESTS
-    else if (!isTestAsync(testFn) && isGenerator(beforeFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(beforeFn.bind(null, name, assert));
-        testFn(assert);
-      };
-    }
-    else if (!isTestAsync(testFn) && !isHelperAsync(beforeFn)) {
-      exports[name] = function (assert) {
-        beforeFn(name, assert);
-        testFn(assert);
-      };
-    }
-    else if (!isTestAsync(testFn) && isHelperAsync(beforeFn)) {
-      exports[name] = function (assert, done) {
-        beforeFn(name, assert, () => {
-          testFn(assert);
-          done();
-        });
-      };
-    }
-    // ASYNC TESTS
-    else if (isTestAsync(testFn) && isGenerator(beforeFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(beforeFn.bind(null, name, assert));
-        yield new Promise(resolve => testFn(assert, resolve));
-      };
-    }
-    else if (isTestAsync(testFn) && !isHelperAsync(beforeFn)) {
-      exports[name] = function (assert, done) {
-        beforeFn(name, assert);
-        testFn(assert, done);
-      };
-    }
-    else if (isTestAsync(testFn) && isHelperAsync(beforeFn)) {
-      exports[name] = function (assert, done) {
-        beforeFn(name, assert, () => {
-          testFn(assert, done);
-        });
-      };
-    }
-  });
-}
-exports.before = before;
-
-/*
- * Takes an `exports` object of a test file and a function `afterFn`
- * to be run after each test. `afterFn` is called with a `name` string
- * as the first argument of the test name, and may specify a second
- * argument function `done` to indicate that this function should
- * resolve asynchronously
- */
-function after (exports, afterFn) {
-  getTestNames(exports).map(name => {
-    let testFn = exports[name];
-
-    // GENERATOR TESTS
-    if (isGenerator(testFn) && isGenerator(afterFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(testFn.bind(null, assert));
-        yield Task.spawn(afterFn.bind(null, name, assert));
-      }
-    }
-    else if (isGenerator(testFn) && !isHelperAsync(afterFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(testFn.bind(null, assert));
-        afterFn(name, assert);
-      }
-    }
-    else if (isGenerator(testFn) && isHelperAsync(afterFn)) {
-      exports[name] = function*(assert) {
-        yield Task.spawn(testFn.bind(null, assert));
-        yield new Promise(resolve => afterFn(name, assert, resolve));
-      }
-    }
-    // SYNC TESTS
-    else if (!isTestAsync(testFn) && isGenerator(afterFn)) {
-      exports[name] = function*(assert) {
-        testFn(assert);
-        yield Task.spawn(afterFn.bind(null, name, assert));
-      };
-    }
-    else if (!isTestAsync(testFn) && !isHelperAsync(afterFn)) {
-      exports[name] = function (assert) {
-        testFn(assert);
-        afterFn(name, assert);
-      };
-    }
-    else if (!isTestAsync(testFn) && isHelperAsync(afterFn)) {
-      exports[name] = function (assert, done) {
-        testFn(assert);
-        afterFn(name, assert, done);
-      };
-    }
-    // ASYNC TESTS
-    else if (isTestAsync(testFn) && isGenerator(afterFn)) {
-      exports[name] = function*(assert) {
-        yield new Promise(resolve => testFn(assert, resolve));
-        yield Task.spawn(afterFn.bind(null, name, assert));
-      };
-    }
-    else if (isTestAsync(testFn) && !isHelperAsync(afterFn)) {
-      exports[name] = function*(assert) {
-        yield new Promise(resolve => testFn(assert, resolve));
-        afterFn(name, assert);
-      };
-    }
-    else if (isTestAsync(testFn) && isHelperAsync(afterFn)) {
-      exports[name] = function*(assert) {
-        yield new Promise(resolve => testFn(assert, resolve));
-        yield new Promise(resolve => afterFn(name, assert, resolve));
-      };
-    }
-  });
-}
-exports.after = after;
-
-function waitUntil (predicate, delay) {
-  let { promise, resolve } = defer();
-  let interval = setInterval(() => {
-    if (!predicate()) return;
-    clearInterval(interval);
-    resolve();
-  }, delay || 10);
-  return promise;
-}
-exports.waitUntil = waitUntil;
-
-var cleanUI = function cleanUI() {
-  let { promise, resolve } = defer();
-
-  resolve();
-
-  return promise;
-}
-exports.cleanUI = cleanUI;
-
-exports.isTravisCI = ("TRAVIS" in env && "CI" in env);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/timers.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  "stability": "stable"
-};
-
-const { CC, Cc, Ci } = require("chrome");
-const { when: unload } = require("./system/unload");
-
-const { TYPE_ONE_SHOT, TYPE_REPEATING_SLACK } = Ci.nsITimer;
-const Timer = CC("@mozilla.org/timer;1", "nsITimer");
-const timers = Object.create(null);
-const threadManager = Cc["@mozilla.org/thread-manager;1"].
-                      getService(Ci.nsIThreadManager);
-const prefBranch = Cc["@mozilla.org/preferences-service;1"].
-                    getService(Ci.nsIPrefService).
-                    QueryInterface(Ci.nsIPrefBranch);
-
-var MIN_DELAY = 4;
-// Try to get min timeout delay used by browser.
-try { MIN_DELAY = prefBranch.getIntPref("dom.min_timeout_value"); } finally {}
-
-
-// Last timer id.
-var lastID = 0;
-
-// Sets typer either by timeout or by interval
-// depending on a given type.
-function setTimer(type, callback, delay, ...args) {
-  let id = ++ lastID;
-  let timer = timers[id] = Timer();
-  timer.initWithCallback({
-    notify: function notify() {
-      try {
-        if (type === TYPE_ONE_SHOT)
-          delete timers[id];
-        callback.apply(null, args);
-      }
-      catch(error) {
-        console.exception(error);
-      }
-    }
-  }, Math.max(delay || MIN_DELAY), type);
-  return id;
-}
-
-function unsetTimer(id) {
-  let timer = timers[id];
-  delete timers[id];
-  if (timer) timer.cancel();
-}
-
-var immediates = new Map();
-
-var dispatcher = _ => {
-  // Allow scheduling of a new dispatch loop.
-  dispatcher.scheduled = false;
-  // Take a snapshot of timer `id`'s that have being present before
-  // starting a dispatch loop, in order to ignore timers registered
-  // in side effect to dispatch while also skipping immediates that
-  // were removed in side effect.
-  let ids = [...immediates.keys()];
-  for (let id of ids) {
-    let immediate = immediates.get(id);
-    if (immediate) {
-      immediates.delete(id);
-      try { immediate(); }
-      catch (error) { console.exception(error); }
-    }
-  }
-}
-
-function setImmediate(callback, ...params) {
-  let id = ++ lastID;
-  // register new immediate timer with curried params.
-  immediates.set(id, _ => callback.apply(callback, params));
-  // if dispatch loop is not scheduled schedule one. Own scheduler
-  if (!dispatcher.scheduled) {
-    dispatcher.scheduled = true;
-    threadManager.dispatchToMainThread(dispatcher);
-  }
-  return id;
-}
-
-function clearImmediate(id) {
-  immediates.delete(id);
-}
-
-// Bind timers so that toString-ing them looks same as on native timers.
-exports.setImmediate = setImmediate.bind(null);
-exports.clearImmediate = clearImmediate.bind(null);
-exports.setTimeout = setTimer.bind(null, TYPE_ONE_SHOT);
-exports.setInterval = setTimer.bind(null, TYPE_REPEATING_SLACK);
-exports.clearTimeout = unsetTimer.bind(null);
-exports.clearInterval = unsetTimer.bind(null);
-
-// all timers are cleared out on unload.
-unload(function() {
-  immediates.clear();
-  Object.keys(timers).forEach(unsetTimer)
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/uri/resource.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const {Cc, Ci} = require("chrome");
-const ioService = Cc["@mozilla.org/network/io-service;1"].
-                  getService(Ci.nsIIOService);
-const resourceHandler = ioService.getProtocolHandler("resource").
-                        QueryInterface(Ci.nsIResProtocolHandler);
-
-const URI = (uri, base=null) =>
-  ioService.newURI(uri, null, base && URI(base))
-
-const mount = (domain, uri) =>
-  resourceHandler.setSubstitution(domain, ioService.newURI(uri));
-exports.mount = mount;
-
-const unmount = (domain, uri) =>
-  resourceHandler.setSubstitution(domain, null);
-exports.unmount = unmount;
-
-const domain = 1;
-const path = 2;
-const resolve = (uri) => {
-  const match = /resource\:\/\/([^\/]+)\/{0,1}([\s\S]*)/.exec(uri);
-  const domain = match && match[1];
-  const path = match && match[2];
-  return !match ? null :
-         !resourceHandler.hasSubstitution(domain) ? null :
-  resourceHandler.resolveURI(URI(`/${path}`, `resource://${domain}/`));
-}
-exports.resolve = resolve;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/url.js
+++ /dev/null
@@ -1,349 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cc, Ci, Cr, Cu } = require("chrome");
-
-const { Class } = require("./core/heritage");
-const base64 = require("./base64");
-var tlds = Cc["@mozilla.org/network/effective-tld-service;1"]
-          .getService(Ci.nsIEffectiveTLDService);
-
-var ios = Cc['@mozilla.org/network/io-service;1']
-          .getService(Ci.nsIIOService);
-
-var resProt = ios.getProtocolHandler("resource")
-              .QueryInterface(Ci.nsIResProtocolHandler);
-
-var URLParser = Cc["@mozilla.org/network/url-parser;1?auth=no"]
-                .getService(Ci.nsIURLParser);
-
-const { Services } = Cu.import("resource://gre/modules/Services.jsm");
-
-function newURI(uriStr, base) {
-  try {
-    let baseURI = base ? ios.newURI(base) : null;
-    return ios.newURI(uriStr, null, baseURI);
-  }
-  catch (e) {
-    if (e.result == Cr.NS_ERROR_MALFORMED_URI) {
-      throw new Error("malformed URI: " + uriStr);
-    }
-    if (e.result == Cr.NS_ERROR_FAILURE ||
-        e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
-      throw new Error("invalid URI: " + uriStr);
-    }
-  }
-}
-
-function resolveResourceURI(uri) {
-  var resolved;
-  try {
-    resolved = resProt.resolveURI(uri);
-  }
-  catch (e) {
-    if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
-      throw new Error("resource does not exist: " + uri.spec);
-    }
-  }
-  return resolved;
-}
-
-var fromFilename = exports.fromFilename = function fromFilename(path) {
-  var file = Cc['@mozilla.org/file/local;1']
-             .createInstance(Ci.nsIFile);
-  file.initWithPath(path);
-  return ios.newFileURI(file).spec;
-};
-
-var toFilename = exports.toFilename = function toFilename(url) {
-  var uri = newURI(url);
-  if (uri.scheme == "resource")
-    uri = newURI(resolveResourceURI(uri));
-  if (uri.scheme == "chrome") {
-    var channel = ios.newChannelFromURI2(uri,
-                                         null,      // aLoadingNode
-                                         Services.scriptSecurityManager.getSystemPrincipal(),
-                                         null,      // aTriggeringPrincipal
-                                         Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                                         Ci.nsIContentPolicy.TYPE_OTHER);
-    try {
-      channel = channel.QueryInterface(Ci.nsIFileChannel);
-      return channel.file.path;
-    }
-    catch (e) {
-      if (e.result == Cr.NS_NOINTERFACE) {
-        throw new Error("chrome url isn't on filesystem: " + url);
-      }
-    }
-  }
-  if (uri.scheme == "file") {
-    var file = uri.QueryInterface(Ci.nsIFileURL).file;
-    return file.path;
-  }
-  throw new Error("cannot map to filename: " + url);
-};
-
-function URL(url, base) {
-  if (!(this instanceof URL)) {
-     return new URL(url, base);
-  }
-
-  var uri = newURI(url, base);
-
-  var userPass = null;
-  try {
-    userPass = uri.userPass ? uri.userPass : null;
-  }
-  catch (e) {
-    if (e.result != Cr.NS_ERROR_FAILURE) {
-      throw e;
-    }
-  }
-
-  var host = null;
-  try {
-    host = uri.host;
-  }
-  catch (e) {
-    if (e.result != Cr.NS_ERROR_FAILURE) {
-      throw e;
-    }
-  }
-
-  var port = null;
-  try {
-    port = uri.port == -1 ? null : uri.port;
-  }
-  catch (e) {
-    if (e.result != Cr.NS_ERROR_FAILURE) {
-      throw e;
-    }
-  }
-
-  let fileName = "/";
-  try {
-    fileName = uri.QueryInterface(Ci.nsIURL).fileName;
-  } catch (e) {
-    if (e.result != Cr.NS_NOINTERFACE) {
-      throw e;
-    }
-  }
-
-  let uriData = [uri.pathQueryRef, uri.pathQueryRef.length, {}, {}, {}, {}, {}, {}];
-  URLParser.parsePath.apply(URLParser, uriData);
-  let [{ value: filepathPos }, { value: filepathLen },
-    { value: queryPos }, { value: queryLen },
-    { value: refPos }, { value: refLen }] = uriData.slice(2);
-
-  let hash = uri.ref ? "#" + uri.ref : "";
-  let pathname = uri.pathQueryRef.substr(filepathPos, filepathLen);
-  let search = uri.pathQueryRef.substr(queryPos, queryLen);
-  search = search ? "?" + search : "";
-
-  this.__defineGetter__("fileName", () => fileName);
-  this.__defineGetter__("scheme", () => uri.scheme);
-  this.__defineGetter__("userPass", () => userPass);
-  this.__defineGetter__("host", () => host);
-  this.__defineGetter__("hostname", () => host);
-  this.__defineGetter__("port", () => port);
-  this.__defineGetter__("path", () => uri.pathQueryRef);
-  this.__defineGetter__("pathname", () => pathname);
-  this.__defineGetter__("hash", () => hash);
-  this.__defineGetter__("href", () => uri.spec);
-  this.__defineGetter__("origin", () => uri.prePath);
-  this.__defineGetter__("protocol", () => uri.scheme + ":");
-  this.__defineGetter__("search", () => search);
-
-  Object.defineProperties(this, {
-    toString: {
-      value() {
-        return new String(uri.spec).toString();
-      },
-      enumerable: false
-    },
-    valueOf: {
-      value() {
-        return new String(uri.spec).valueOf();
-      },
-      enumerable: false
-    },
-    toSource: {
-      value() {
-        return new String(uri.spec).toSource();
-      },
-      enumerable: false
-    },
-    // makes more sense to flatten to string, easier to travel across JSON
-    toJSON: {
-      value() {
-        return new String(uri.spec).toString();
-      },
-      enumerable: false
-    }
-  });
-
-  return this;
-};
-
-URL.prototype = Object.create(String.prototype);
-exports.URL = URL;
-
-/**
- * Parse and serialize a Data URL.
- *
- * See: http://tools.ietf.org/html/rfc2397
- *
- * Note: Could be extended in the future to decode / encode automatically binary
- * data.
- */
-const DataURL = Class({
-
-  get base64 () {
-    return "base64" in this.parameters;
-  },
-
-  set base64 (value) {
-    if (value)
-      this.parameters["base64"] = "";
-    else
-      delete this.parameters["base64"];
-  },
-  /**
-  * Initialize the Data URL object. If a uri is given, it will be parsed.
-  *
-  * @param {String} [uri] The uri to parse
-  *
-  * @throws {URIError} if the Data URL is malformed
-   */
-  initialize: function(uri) {
-    // Due to bug 751834 it is not possible document and define these
-    // properties in the prototype.
-
-    /**
-     * An hashmap that contains the parameters of the Data URL. By default is
-     * empty, that accordingly to RFC is equivalent to {"charset" : "US-ASCII"}
-     */
-    this.parameters = {};
-
-    /**
-     * The MIME type of the data. By default is empty, that accordingly to RFC
-     * is equivalent to "text/plain"
-     */
-    this.mimeType = "";
-
-    /**
-     * The string that represent the data in the Data URL
-     */
-    this.data = "";
-
-    if (typeof uri === "undefined")
-      return;
-
-    uri = String(uri);
-
-    let matches = uri.match(/^data:([^,]*),(.*)$/i);
-
-    if (!matches)
-      throw new URIError("Malformed Data URL: " + uri);
-
-    let mediaType = matches[1].trim();
-
-    this.data = decodeURIComponent(matches[2].trim());
-
-    if (!mediaType)
-      return;
-
-    let parametersList = mediaType.split(";");
-
-    this.mimeType = parametersList.shift().trim();
-
-    for (let parameter, i = 0; parameter = parametersList[i++];) {
-      let pairs = parameter.split("=");
-      let name = pairs[0].trim();
-      let value = pairs.length > 1 ? decodeURIComponent(pairs[1].trim()) : "";
-
-      this.parameters[name] = value;
-    }
-
-    if (this.base64)
-      this.data = base64.decode(this.data);
-
-  },
-
-  /**
-   * Returns the object as a valid Data URL string
-   *
-   * @returns {String} The Data URL
-   */
-  toString : function() {
-    let parametersList = [];
-
-    for (let name in this.parameters) {
-      let encodedParameter = encodeURIComponent(name);
-      let value = this.parameters[name];
-
-      if (value)
-        encodedParameter += "=" + encodeURIComponent(value);
-
-      parametersList.push(encodedParameter);
-    }
-
-    // If there is at least a parameter, add an empty string in order
-    // to start with a `;` on join call.
-    if (parametersList.length > 0)
-      parametersList.unshift("");
-
-    let data = this.base64 ? base64.encode(this.data) : this.data;
-
-    return "data:" +
-      this.mimeType +
-      parametersList.join(";") + "," +
-      encodeURIComponent(data);
-  }
-});
-
-exports.DataURL = DataURL;
-
-var getTLD = exports.getTLD = function getTLD (url) {
-  let uri = newURI(url.toString());
-  let tld = null;
-  try {
-    tld = tlds.getPublicSuffix(uri);
-  }
-  catch (e) {
-    if (e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS &&
-        e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
-      throw e;
-    }
-  }
-  return tld;
-};
-
-var isValidURI = exports.isValidURI = function (uri) {
-  try {
-    newURI(uri);
-  }
-  catch(e) {
-    return false;
-  }
-  return true;
-}
-
-function isLocalURL(url) {
-  if (String(url).indexOf('./') === 0)
-    return true;
-
-  try {
-    return ['resource', 'data', 'chrome'].indexOf(URL(url).scheme) > -1;
-  }
-  catch(e) {}
-
-  return false;
-}
-exports.isLocalURL = isLocalURL;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/url/utils.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";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Cc, Ci, Cr } = require("chrome");
-const IOService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-const { isValidURI } = require("../url");
-const { method } = require("../../method/core");
-
-function newURI (uri) {
-  if (!isValidURI(uri))
-    throw new Error("malformed URI: " + uri);
-  return IOService.newURI(uri);
-}
-exports.newURI = newURI;
-
-var getURL = method('sdk/url:getURL');
-getURL.define(String, url => url);
-getURL.define(function (object) {
-  return null;
-});
-exports.getURL = getURL;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/array.js
+++ /dev/null
@@ -1,123 +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"
-};
-
-/**
- * Returns `true` if given `array` contain given `element` or `false`
- * otherwise.
- * @param {Array} array
- *    Target array.
- * @param {Object|String|Number|Boolean} element
- *    Element being looked up.
- * @returns {Boolean}
- */
-var has = exports.has = function has(array, element) {
-  // shorter and faster equivalent of `array.indexOf(element) >= 0`
-  return !!~array.indexOf(element);
-};
-var hasAny = exports.hasAny = function hasAny(array, elements) {
-  if (arguments.length < 2)
-    return false;
-  if (!Array.isArray(elements))
-    elements = [ elements ];
-  return array.some(function (element) {
-      return has(elements, element);
-  });
-};
-
-/**
- * Adds given `element` to the given `array` if it does not contain it yet.
- * `true` is returned if element was added otherwise `false` is returned.
- * @param {Array} array
- *    Target array.
- * @param {Object|String|Number|Boolean} element
- *    Element to be added.
- * @returns {Boolean}
- */
-var add = exports.add = function add(array, element) {
-  var result;
-  if ((result = !has(array, element)))
-    array.push(element);
-
-  return result;
-};
-
-/**
- * Removes first occurrence of the given `element` from the given `array`. If
- * `array` does not contain given `element` `false` is returned otherwise
- * `true` is returned.
- * @param {Array} array
- *    Target array.
- * @param {Object|String|Number|Boolean} element
- *    Element to be removed.
- * @returns {Boolean}
- */
-exports.remove = function remove(array, element) {
-  var result;
-  if ((result = has(array, element)))
-    array.splice(array.indexOf(element), 1);
-
-  return result;
-};
-
-/**
- * Produces a duplicate-free version of the given `array`.
- * @param {Array} array
- *    Source array.
- * @returns {Array}
- */
-function unique(array) {
-  return array.reduce(function(result, item) {
-    add(result, item);
-    return result;
-  }, []);
-};
-exports.unique = unique;
-
-/**
- * Produce an array that contains the union: each distinct element from all
- * of the passed-in arrays.
- */
-function union() {
-  return unique(Array.concat.apply(null, arguments));
-};
-exports.union = union;
-
-exports.flatten = function flatten(array){
-   var flat = [];
-   for (var i = 0, l = array.length; i < l; i++) {
-    flat = flat.concat(Array.isArray(array[i]) ? flatten(array[i]) : array[i]);
-   }
-   return flat;
-};
-
-function fromIterator(iterator) {
-  let array = [];
-  if (iterator.__iterator__) {
-    for (let item of iterator)
-      array.push(item);
-  }
-  else {
-    for (let item of iterator)
-      array.push(item);
-  }
-  return array;
-}
-exports.fromIterator = fromIterator;
-
-function find(array, predicate, fallback) {
-  var index = 0;
-  var count = array.length;
-  while (index < count) {
-    var value = array[index];
-    if (predicate(value)) return value;
-    else index = index + 1;
-  }
-  return fallback;
-}
-exports.find = find;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/collection.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": "experimental"
-};
-
-exports.Collection = Collection;
-
-/**
- * Adds a collection property to the given object.  Setting the property to a
- * scalar value empties the collection and adds the value.  Setting it to an
- * array empties the collection and adds all the items in the array.
- *
- * @param obj
- *        The property will be defined on this object.
- * @param propName
- *        The name of the property.
- * @param array
- *        If given, this will be used as the collection's backing array.
- */
-exports.addCollectionProperty = function addCollProperty(obj, propName, array) {
-  array = array || [];
-  let publicIface = new Collection(array);
-
-  Object.defineProperty(obj, propName, {
-    configurable: true,
-    enumerable: true,
-
-    set: function set(itemOrItems) {
-      array.splice(0, array.length);
-      publicIface.add(itemOrItems);
-    },
-
-    get: function get() {
-      return publicIface;
-    }
-  });
-};
-
-/**
- * A collection is ordered, like an array, but its items are unique, like a set.
- *
- * @param array
- *        The collection is backed by an array.  If this is given, it will be
- *        used as the backing array.  This way the caller can fully control the
- *        collection.  Otherwise a new empty array will be used, and no one but
- *        the collection will have access to it.
- */
-function Collection(array) {
-  array = array || [];
-
-  /**
-   * Provides iteration over the collection.  Items are yielded in the order
-   * they were added.
-   */
-  this[Symbol.iterator] = function* Collection___iterator__() {
-    let items = array.slice();
-    for (let i = 0; i < items.length; i++)
-      yield items[i];
-  };
-
-  /**
-   * The number of items in the collection.
-   */
-  this.__defineGetter__("length", function Collection_get_length() {
-    return array.length;
-  });
-
-  /**
-   * Adds a single item or an array of items to the collection.  Any items
-   * already contained in the collection are ignored.
-   *
-   * @param  itemOrItems
-   *         An item or array of items.
-   * @return The collection.
-   */
-  this.add = function Collection_add(itemOrItems) {
-    let items = toArray(itemOrItems);
-    for (let i = 0; i < items.length; i++) {
-      let item = items[i];
-      if (array.indexOf(item) < 0)
-        array.push(item);
-    }
-    return this;
-  };
-
-  /**
-   * Removes a single item or an array of items from the collection.  Any items
-   * not contained in the collection are ignored.
-   *
-   * @param  itemOrItems
-   *         An item or array of items.
-   * @return The collection.
-   */
-  this.remove = function Collection_remove(itemOrItems) {
-    let items = toArray(itemOrItems);
-    for (let i = 0; i < items.length; i++) {
-      let idx = array.indexOf(items[i]);
-      if (idx >= 0)
-        array.splice(idx, 1);
-    }
-    return this;
-  };
-};
-
-function toArray(itemOrItems) {
-  let isArr = itemOrItems &&
-              itemOrItems.constructor &&
-              itemOrItems.constructor.name === "Array";
-  return isArr ? itemOrItems : [itemOrItems];
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/deprecate.js
+++ /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/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-lazyRequire(this, "../console/traceback", "get", "format");
-lazyRequire(this, "../preferences/service", {"get": "getPref"});
-const PREFERENCE = "devtools.errorconsole.deprecation_warnings";
-
-function deprecateUsage(msg) {
-  // Print caller stacktrace in order to help figuring out which code
-  // does use deprecated thing
-  let stack = get().slice(2);
-
-  if (getPref(PREFERENCE)) 
-    console.error("DEPRECATED: " + msg + "\n" + format(stack));
-}
-exports.deprecateUsage = deprecateUsage;
-
-function deprecateFunction(fun, msg) {
-  return function deprecated() {
-    deprecateUsage(msg);
-    return fun.apply(this, arguments);
-  };
-}
-exports.deprecateFunction = deprecateFunction;
-
-function deprecateEvent(fun, msg, evtTypes) {
-  return function deprecateEvent(evtType) {
-  	if (evtTypes.indexOf(evtType) >= 0)
-      deprecateUsage(msg);
-    return fun.apply(this, arguments);
-  };
-}
-exports.deprecateEvent = deprecateEvent;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/dispatcher.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const method = require("method/core");
-
-// Utility function that is just an enhancement over `method` to
-// allow predicate based dispatch in addition to polymorphic
-// dispatch. Unfortunately polymorphic dispatch does not quite
-// cuts it in the world of XPCOM where no types / classes exist
-// and all the XUL nodes share same type / prototype.
-// Probably this is more generic and belongs some place else, but
-// we can move it later once this will be relevant.
-var dispatcher = hint => {
-  const base = method(hint);
-  // Make a map for storing predicate, implementation mappings.
-  let implementations = new Map();
-
-  // Dispatcher function goes through `predicate, implementation`
-  // pairs to find predicate that matches first argument and
-  // returns application of arguments on the associated
-  // `implementation`. If no matching predicate is found delegates
-  // to a `base` polymorphic function.
-  let dispatch = (value, ...rest) => {
-    for (let [predicate, implementation] of implementations) {
-      if (predicate(value))
-        return implementation(value, ...rest);
-    }
-
-    return base(value, ...rest);
-  };
-
-  // Expose base API.
-  dispatch.define = base.define;
-  dispatch.implement = base.implement;
-  dispatch.toString = base.toString;
-
-  // Add a `when` function to allow extending function via
-  // predicates.
-  dispatch.when = (predicate, implementation) => {
-    if (implementations.has(predicate))
-      throw TypeError("Already implemented for the given predicate");
-    implementations.set(predicate, implementation);
-  };
-
-  return dispatch;
-};
-
-exports.dispatcher = dispatcher;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/list.js
+++ /dev/null
@@ -1,77 +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 { Class } = require('../core/heritage');
-const listNS = require('../core/namespace').ns();
-
-const listOptions = {
-  /**
-   * List constructor can take any number of element to populate itself.
-   * @params {Object|String|Number} element
-   * @example
-   *    List(1,2,3).length == 3 // true
-   */
-  initialize: function List() {
-    listNS(this).keyValueMap = [];
-
-    for (let i = 0, ii = arguments.length; i < ii; i++)
-      addListItem(this, arguments[i]);
-  },
-  /**
-   * Number of elements in this list.
-   * @type {Number}
-   */
-  get length() {
-    return listNS(this).keyValueMap.length;
-  },
-   /**
-    * Returns a string representing this list.
-    * @returns {String}
-    */
-  toString: function toString() {
-    return 'List(' + listNS(this).keyValueMap + ')';
-  },
-};
-listOptions[Symbol.iterator] = function iterator() {
-    return listNS(this).keyValueMap.slice(0)[Symbol.iterator]();
-};
-const List = Class(listOptions);
-exports.List = List;
-
-function addListItem(that, value) {
-  let list = listNS(that).keyValueMap,
-      index = list.indexOf(value);
-
-  if (-1 === index) {
-    try {
-      that[that.length] = value;
-    }
-    catch (e) {}
-    list.push(value);
-  }
-}
-exports.addListItem = addListItem;
-
-function removeListItem(that, element) {
-  let list = listNS(that).keyValueMap,
-      index = list.indexOf(element);
-
-  if (0 <= index) {
-    list.splice(index, 1);
-    try {
-      for (let length = list.length; index < length; index++)
-        that[index] = list[index];
-      that[list.length] = undefined;
-    }
-    catch(e){}
-  }
-}
-exports.removeListItem = removeListItem;
-
-exports.listNS = listNS;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/object.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-lazyRequire(this, './array', "flatten");
-
-// Create a shortcut for Array.prototype.slice.call().
-const unbind = Function.call.bind(Function.bind, Function.call);
-const slice = unbind(Array.prototype.slice);
-
-class DefaultWeakMap extends WeakMap {
-  constructor(createItem, items = undefined) {
-    super(items);
-
-    this.createItem = createItem;
-  }
-
-  get(key) {
-    if (!this.has(key)) {
-      this.set(key, this.createItem(key));
-    }
-
-    return super.get(key);
-  }
-}
-
-class DefaultMap extends Map {
-  constructor(createItem, items = undefined) {
-    super(items);
-
-    this.createItem = createItem;
-  }
-
-  get(key) {
-    if (!this.has(key)) {
-      this.set(key, this.createItem(key));
-    }
-
-    return super.get(key);
-  }
-}
-
-Object.assign(exports, {DefaultMap, DefaultWeakMap});
-
-/**
- * Merges all the properties of all arguments into first argument. If two or
- * more argument objects have own properties with the same name, the property
- * is overridden, with precedence from right to left, implying, that properties
- * of the object on the left are overridden by a same named property of the
- * object on the right.
- *
- * Any argument given with "falsy" value - commonly `null` and `undefined` in
- * case of objects - are skipped.
- *
- * @examples
- *    var a = { bar: 0, a: 'a' }
- *    var b = merge(a, { foo: 'foo', bar: 1 }, { foo: 'bar', name: 'b' });
- *    b === a   // true
- *    b.a       // 'a'
- *    b.foo     // 'bar'
- *    b.bar     // 1
- *    b.name    // 'b'
- */
-function merge(source) {
-  let descriptor = {};
-
-  // `Boolean` converts the first parameter to a boolean value. Any object is
-  // converted to `true` where `null` and `undefined` becames `false`. Therefore
-  // the `filter` method will keep only objects that are defined and not null.
-  slice(arguments, 1).filter(Boolean).forEach(function onEach(properties) {
-    getOwnPropertyIdentifiers(properties).forEach(function(name) {
-      descriptor[name] = Object.getOwnPropertyDescriptor(properties, name);
-    });
-  });
-  return Object.defineProperties(source, descriptor);
-}
-exports.merge = merge;
-
-/**
- * Returns an object that inherits from the first argument and contains all the
- * properties from all following arguments.
- * `extend(source1, source2, source3)` is equivalent of
- * `merge(Object.create(source1), source2, source3)`.
- */
-function extend(source) {
-  let rest = slice(arguments, 1);
-  rest.unshift(Object.create(source));
-  return merge.apply(null, rest);
-}
-exports.extend = extend;
-
-function has(obj, key) {
-  return obj.hasOwnProperty(key);
-}
-exports.has = has;
-
-function each(obj, fn) {
-  for (let key in obj) has(obj, key) && fn(obj[key], key, obj);
-}
-exports.each = each;
-
-/**
- * Like `merge`, except no property descriptors are manipulated, for use
- * with platform objects. Identical to underscore's `extend`. Useful for
- * merging XPCOM objects
- */
-function safeMerge(source) {
-  slice(arguments, 1).forEach(function onEach (obj) {
-    for (let prop in obj) source[prop] = obj[prop];
-  });
-  return source;
-}
-exports.safeMerge = safeMerge;
-
-/*
- * Returns a copy of the object without omitted properties
- */
-function omit(source, ...values) {
-  let copy = {};
-  let keys = flatten(values);
-  for (let prop in source)
-    if (!~keys.indexOf(prop))
-      copy[prop] = source[prop];
-  return copy;
-}
-exports.omit = omit;
-
-// get object's own property Symbols and/or Names, including nonEnumerables by default
-function getOwnPropertyIdentifiers(object, options = { names: true, symbols: true, nonEnumerables: true }) {
-  const symbols = !options.symbols ? [] :
-                  Object.getOwnPropertySymbols(object);
-  const names = !options.names ? [] :
-                options.nonEnumerables ? Object.getOwnPropertyNames(object) :
-                Object.keys(object);
-  return [...names, ...symbols];
-}
-exports.getOwnPropertyIdentifiers = getOwnPropertyIdentifiers;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/sequence.js
+++ /dev/null
@@ -1,593 +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"
-};
-
-// Disclamer:
-// In this module we'll have some common argument / variable names
-// to hint their type or behavior.
-//
-// - `f` stands for "function" that is intended to be side effect
-//   free.
-// - `p` stands for "predicate" that is function which returns logical
-//   true or false and is intended to be side effect free.
-// - `x` / `y` single item of the sequence.
-// - `xs` / `ys` sequence of `x` / `y` items where `x` / `y` signifies
-//    type of the items in sequence, so sequence is not of the same item.
-// - `_` used for argument(s) or variable(s) who's values are ignored.
-
-const { complement, flip, identity } = require("../lang/functional");
-lazyRequire(this, "../lang/type", "isArray", "isArguments", "isMap", "isSet",
-            "isGenerator", "isString", "isBoolean", "isNumber");
-
-const Sequence = function Sequence(iterator) {
-  if (!isGenerator(iterator)) {
-    throw TypeError("Expected generator argument");
-  }
-
-  this[Symbol.iterator] = iterator;
-};
-exports.Sequence = Sequence;
-
-const polymorphic = dispatch => x =>
-  x === null ? dispatch.null(null) :
-  x === void(0) ? dispatch.void(void(0)) :
-  isArray(x) ? (dispatch.array || dispatch.indexed)(x) :
-  isString(x) ? (dispatch.string || dispatch.indexed)(x) :
-  isArguments(x) ? (dispatch.arguments || dispatch.indexed)(x) :
-  isMap(x) ? dispatch.map(x) :
-  isSet(x) ? dispatch.set(x) :
-  isNumber(x) ? dispatch.number(x) :
-  isBoolean(x) ? dispatch.boolean(x) :
-  dispatch.default(x);
-
-const nogen = function*() {};
-const empty = () => new Sequence(nogen);
-exports.empty = empty;
-
-const seq = polymorphic({
-  null: empty,
-  void: empty,
-  array: identity,
-  string: identity,
-  arguments: identity,
-  map: identity,
-  set: identity,
-  default: x => x instanceof Sequence ? x : new Sequence(x)
-});
-exports.seq = seq;
-
-// Function to cast seq to string.
-const string = (...etc) => "".concat(...etc);
-exports.string = string;
-
-// Function for casting seq to plain object.
-const object = (...pairs) => {
-  let result = {};
-  for (let [key, value] of pairs)
-    result[key] = value;
-
-  return result;
-};
-exports.object = object;
-
-// Takes `getEnumerator` function that returns `nsISimpleEnumerator`
-// and creates lazy sequence of it's items. Note that function does
-// not take `nsISimpleEnumerator` itslef because that would allow
-// single iteration, which would not be consistent with rest of the
-// lazy sequences.
-const fromEnumerator = getEnumerator => seq(function* () {
-  const enumerator = getEnumerator();
-  while (enumerator.hasMoreElements())
-   yield enumerator.getNext();
-});
-exports.fromEnumerator = fromEnumerator;
-
-// Takes `object` and returns lazy sequence of own `[key, value]`
-// pairs (does not include inherited and non enumerable keys).
-const pairs = polymorphic({
-  null: empty,
-  void: empty,
-  map: identity,
-  indexed: indexed => seq(function* () {
-    const count = indexed.length;
-    let index = 0;
-    while (index < count) {
-      yield [index, indexed[index]];
-      index = index + 1;
-    }
-  }),
-  default: object => seq(function* () {
-    for (let key of Object.keys(object))
-      yield [key, object[key]];
-  })
-});
-exports.pairs = pairs;
-
-const names = polymorphic({
-  null: empty,
-  void: empty,
-  default: object => seq(function*() {
-    for (let name of Object.getOwnPropertyNames(object)) {
-      yield name;
-    }
-  })
-});
-exports.names = names;
-
-const symbols = polymorphic({
-  null: empty,
-  void: empty,
-  default: object => seq(function* () {
-    for (let symbol of Object.getOwnPropertySymbols(object)) {
-      yield symbol;
-    }
-  })
-});
-exports.symbols = symbols;
-
-const keys = polymorphic({
-  null: empty,
-  void: empty,
-  indexed: indexed => seq(function* () {
-    const count = indexed.length;
-    let index = 0;
-    while (index < count) {
-      yield index;
-      index = index + 1;
-    }
-  }),
-  map: map => seq(function* () {
-    for (let [key, _] of map)
-      yield key;
-  }),
-  default: object => seq(function* () {
-    for (let key of Object.keys(object))
-      yield key;
-  })
-});
-exports.keys = keys;
-
-
-const values = polymorphic({
-  null: empty,
-  void: empty,
-  set: identity,
-  indexed: indexed => seq(function* () {
-    const count = indexed.length;
-    let index = 0;
-    while (index < count) {
-      yield indexed[index];
-      index = index + 1;
-    }
-  }),
-  map: map => seq(function* () {
-    for (let [_, value] of map) yield value;
-  }),
-  default: object => seq(function* () {
-    for (let key of Object.keys(object)) yield object[key];
-  })
-});
-exports.values = values;
-
-
-
-// Returns a lazy sequence of `x`, `f(x)`, `f(f(x))` etc.
-// `f` must be free of side-effects. Note that returned
-// sequence is infinite so it must be consumed partially.
-//
-// Implements clojure iterate:
-// http://clojuredocs.org/clojure_core/clojure.core/iterate
-const iterate = (f, x) => seq(function* () {
-  let state = x;
-  while (true) {
-    yield state;
-    state = f(state);
-  }
-});
-exports.iterate = iterate;
-
-// Returns a lazy sequence of the items in sequence for which `p(item)`
-// returns `true`. `p` must be free of side-effects.
-//
-// Implements clojure filter:
-// http://clojuredocs.org/clojure_core/clojure.core/filter
-const filter = (p, sequence) => seq(function* () {
-  if (sequence !== null && sequence !== void(0)) {
-    for (let item of sequence) {
-      if (p(item))
-        yield item;
-    }
-  }
-});
-exports.filter = filter;
-
-// Returns a lazy sequence consisting of the result of applying `f` to the
-// set of first items of each sequence, followed by applying f to the set
-// of second items in each sequence, until any one of the sequences is
-// exhausted. Any remaining items in other sequences are ignored. Function
-// `f` should accept number-of-sequences arguments.
-//
-// Implements clojure map:
-// http://clojuredocs.org/clojure_core/clojure.core/map
-const map = (f, ...sequences) => seq(function* () {
-  const count = sequences.length;
-  // Optimize a single sequence case
-  if (count === 1) {
-    let [sequence] = sequences;
-    if (sequence !== null && sequence !== void(0)) {
-      for (let item of sequence)
-        yield f(item);
-    }
-  }
-  else {
-    // define args array that will be recycled on each
-    // step to aggregate arguments to be passed to `f`.
-    let args = [];
-    // define inputs to contain started generators.
-    let inputs = [];
-
-    let index = 0;
-    while (index < count) {
-      inputs[index] = sequences[index][Symbol.iterator]();
-      index = index + 1;
-    }
-
-    // Run loop yielding of applying `f` to the set of
-    // items at each step until one of the `inputs` is
-    // exhausted.
-    let done = false;
-    while (!done) {
-      let index = 0;
-      let value = void(0);
-      while (index < count && !done) {
-        ({ done, value } = inputs[index].next());
-
-        // If input is not exhausted yet store value in args.
-        if (!done) {
-          args[index] = value;
-          index = index + 1;
-        }
-      }
-
-      // If none of the inputs is exhasted yet, `args` contain items
-      // from each input so we yield application of `f` over them.
-      if (!done)
-        yield f(...args);
-    }
-  }
-});
-exports.map = map;
-
-// Returns a lazy sequence of the intermediate values of the reduction (as
-// per reduce) of sequence by `f`, starting with `initial` value if provided.
-//
-// Implements clojure reductions:
-// http://clojuredocs.org/clojure_core/clojure.core/reductions
-const reductions = (...params) => {
-  const count = params.length;
-  let hasInitial = false;
-  let f, initial, source;
-  if (count === 2) {
-    [f, source] = params;
-  }
-  else if (count === 3) {
-    [f, initial, source] = params;
-    hasInitial = true;
-  }
-  else {
-    throw Error("Invoked with wrong number of arguments: " + count);
-  }
-
-  const sequence = seq(source);
-
-  return seq(function* () {
-    let started = hasInitial;
-    let result = void(0);
-
-    // If initial is present yield it.
-    if (hasInitial)
-      yield (result = initial);
-
-    // For each item of the sequence accumulate new result.
-    for (let item of sequence) {
-      // If nothing has being yield yet set result to first
-      // item and yield it.
-      if (!started) {
-        started = true;
-        yield (result = item);
-      }
-      // Otherwise accumulate new result and yield it.
-      else {
-        yield (result = f(result, item));
-      }
-    }
-
-    // If nothing has being yield yet it's empty sequence and no
-    // `initial` was provided in which case we need to yield `f()`.
-    if (!started)
-      yield f();
-  });
-};
-exports.reductions = reductions;
-
-// `f` should be a function of 2 arguments. If `initial` is not supplied,
-// returns the result of applying `f` to the first 2 items in sequence, then
-// applying `f` to that result and the 3rd item, etc. If sequence contains no
-// items, `f` must accept no arguments as well, and reduce returns the
-// result of calling f with no arguments. If sequence has only 1 item, it
-// is returned and `f` is not called. If `initial` is supplied, returns the
-// result of applying `f` to `initial` and the first item in  sequence, then
-// applying `f` to that result and the 2nd item, etc. If sequence contains no
-// items, returns `initial` and `f` is not called.
-//
-// Implements clojure reduce:
-// http://clojuredocs.org/clojure_core/clojure.core/reduce
-const reduce = (...args) => {
-  const xs = reductions(...args);
-  let x;
-  for (x of xs) void(0);
-  return x;
-};
-exports.reduce = reduce;
-
-const each = (f, sequence) => {
-  for (let x of seq(sequence)) void(f(x));
-};
-exports.each = each;
-
-
-const inc = x => x + 1;
-// Returns the number of items in the sequence. `count(null)` && `count()`
-// returns `0`. Also works on strings, arrays, Maps & Sets.
-
-// Implements clojure count:
-// http://clojuredocs.org/clojure_core/clojure.core/count
-const count = polymorphic({
-  null: _ => 0,
-  void: _ => 0,
-  indexed: indexed => indexed.length,
-  map: map => map.size,
-  set: set => set.size,
-  default: xs => reduce(inc, 0, xs)
-});
-exports.count = count;
-
-// Returns `true` if sequence has no items.
-
-// Implements clojure empty?:
-// http://clojuredocs.org/clojure_core/clojure.core/empty_q
-const isEmpty = sequence => {
-  // Treat `null` and `undefined` as empty sequences.
-  if (sequence === null || sequence === void(0))
-    return true;
-
-  // If contains any item non empty so return `false`.
-  for (let _ of sequence)
-    return false;
-
-  // If has not returned yet, there was nothing to iterate
-  // so it's empty.
-  return true;
-};
-exports.isEmpty = isEmpty;
-
-const and = (a, b) => a && b;
-
-// Returns true if `p(x)` is logical `true` for every `x` in sequence, else
-// `false`.
-//
-// Implements clojure every?:
-// http://clojuredocs.org/clojure_core/clojure.core/every_q
-const isEvery = (p, sequence) => {
-  if (sequence !== null && sequence !== void(0)) {
-    for (let item of sequence) {
-      if (!p(item))
-        return false;
-    }
-  }
-  return true;
-};
-exports.isEvery = isEvery;
-
-// Returns the first logical true value of (p x) for any x in sequence,
-// else `null`.
-//
-// Implements clojure some:
-// http://clojuredocs.org/clojure_core/clojure.core/some
-const some = (p, sequence) => {
-  if (sequence !== null && sequence !== void(0)) {
-    for (let item of sequence) {
-      if (p(item))
-        return true;
-    }
-  }
-  return null;
-};
-exports.some = some;
-
-// Returns a lazy sequence of the first `n` items in sequence, or all items if
-// there are fewer than `n`.
-//
-// Implements clojure take:
-// http://clojuredocs.org/clojure_core/clojure.core/take
-const take = (n, sequence) => n <= 0 ? empty() : seq(function* () {
-  let count = n;
-  for (let item of sequence) {
-    yield item;
-    count = count - 1;
-    if (count === 0) break;
-  }
-});
-exports.take = take;
-
-// Returns a lazy sequence of successive items from sequence while
-// `p(item)` returns `true`. `p` must be free of side-effects.
-//
-// Implements clojure take-while:
-// http://clojuredocs.org/clojure_core/clojure.core/take-while
-const takeWhile = (p, sequence) => seq(function* () {
-  for (let item of sequence) {
-    if (!p(item))
-      break;
-
-    yield item;
-  }
-});
-exports.takeWhile = takeWhile;
-
-// Returns a lazy sequence of all but the first `n` items in
-// sequence.
-//
-// Implements clojure drop:
-// http://clojuredocs.org/clojure_core/clojure.core/drop
-const drop = (n, sequence) => seq(function* () {
-  if (sequence !== null && sequence !== void(0)) {
-    let count = n;
-    for (let item of sequence) {
-      if (count > 0)
-        count = count - 1;
-      else
-        yield item;
-    }
-  }
-});
-exports.drop = drop;
-
-// Returns a lazy sequence of the items in sequence starting from the
-// first item for which `p(item)` returns falsy value.
-//
-// Implements clojure drop-while:
-// http://clojuredocs.org/clojure_core/clojure.core/drop-while
-const dropWhile = (p, sequence) => seq(function* () {
-  let keep = false;
-  for (let item of sequence) {
-    keep = keep || !p(item);
-    if (keep) yield item;
-  }
-});
-exports.dropWhile = dropWhile;
-
-// Returns a lazy sequence representing the concatenation of the
-// suplied sequences.
-//
-// Implements clojure conact:
-// http://clojuredocs.org/clojure_core/clojure.core/concat
-const concat = (...sequences) => seq(function* () {
-  for (let sequence of sequences)
-    for (let item of sequence)
-      yield item;
-});
-exports.concat = concat;
-
-// Returns the first item in the sequence.
-//
-// Implements clojure first:
-// http://clojuredocs.org/clojure_core/clojure.core/first
-const first = sequence => {
-  if (sequence !== null && sequence !== void(0)) {
-    for (let item of sequence)
-      return item;
-  }
-  return null;
-};
-exports.first = first;
-
-// Returns a possibly empty sequence of the items after the first.
-//
-// Implements clojure rest:
-// http://clojuredocs.org/clojure_core/clojure.core/rest
-const rest = sequence => drop(1, sequence);
-exports.rest = rest;
-
-// Returns the value at the index. Returns `notFound` or `undefined`
-// if index is out of bounds.
-const nth = (xs, n, notFound) => {
-  if (n >= 0) {
-    if (isArray(xs) || isArguments(xs) || isString(xs)) {
-      return n < xs.length ? xs[n] : notFound;
-    }
-    else if (xs !== null && xs !== void(0)) {
-      let count = n;
-      for (let x of xs) {
-        if (count <= 0)
-          return x;
-
-        count = count - 1;
-      }
-    }
-  }
-  return notFound;
-};
-exports.nth = nth;
-
-// Return the last item in sequence, in linear time.
-// If `sequence` is an array or string or arguments
-// returns in constant time.
-// Implements clojure last:
-// http://clojuredocs.org/clojure_core/clojure.core/last
-const last = polymorphic({
-  null: _ => null,
-  void: _ => null,
-  indexed: indexed => indexed[indexed.length - 1],
-  map: xs => reduce((_, x) => x, xs),
-  set: xs => reduce((_, x) => x, xs),
-  default: xs => reduce((_, x) => x, xs)
-});
-exports.last = last;
-
-// Return a lazy sequence of all but the last `n` (default 1) items
-// from the give `xs`.
-//
-// Implements clojure drop-last:
-// http://clojuredocs.org/clojure_core/clojure.core/drop-last
-const dropLast = flip((xs, n=1) => seq(function* () {
-  let ys = [];
-  for (let x of xs) {
-    ys.push(x);
-    if (ys.length > n)
-      yield ys.shift();
-  }
-}));
-exports.dropLast = dropLast;
-
-// Returns a lazy sequence of the elements of `xs` with duplicates
-// removed
-//
-// Implements clojure distinct
-// http://clojuredocs.org/clojure_core/clojure.core/distinct
-const distinct = sequence => seq(function* () {
-  let items = new Set();
-  for (let item of sequence) {
-    if (!items.has(item)) {
-      items.add(item);
-      yield item;
-    }
-  }
-});
-exports.distinct = distinct;
-
-// Returns a lazy sequence of the items in `xs` for which
-// `p(x)` returns false. `p` must be free of side-effects.
-//
-// Implements clojure remove
-// http://clojuredocs.org/clojure_core/clojure.core/remove
-const remove = (p, xs) => filter(complement(p), xs);
-exports.remove = remove;
-
-// Returns the result of applying concat to the result of
-// `map(f, xs)`. Thus function `f` should return a sequence.
-//
-// Implements clojure mapcat
-// http://clojuredocs.org/clojure_core/clojure.core/mapcat
-const mapcat = (f, sequence) => seq(function* () {
-  const sequences = map(f, sequence);
-  for (let sequence of sequences)
-    for (let item of sequence)
-      yield item;
-});
-exports.mapcat = mapcat;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/util/uuid.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { Cc, Ci, components: { ID: parseUUID } } = require('chrome');
-const { generateUUID } = Cc['@mozilla.org/uuid-generator;1'].
-                          getService(Ci.nsIUUIDGenerator);
-
-// Returns `uuid`. If `id` is passed then it's parsed to `uuid` and returned
-// if not then new one is generated.
-exports.uuid = function uuid(id) {
-  return id ? parseUUID(id) : generateUUID();
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/window/utils.js
+++ /dev/null
@@ -1,459 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  'stability': 'unstable'
-};
-
-const { Cc, Ci } = require('chrome');
-lazyRequireModule(this, "../util/array", "array");
-const { defer } = require('sdk/core/promise');
-const { dispatcher } = require("../util/dispatcher");
-
-const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
-                       getService(Ci.nsIWindowWatcher);
-const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
-                        getService(Ci.nsIAppShellService);
-const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
-           getService(Ci.nsIWindowMediator);
-const io = Cc['@mozilla.org/network/io-service;1'].
-           getService(Ci.nsIIOService);
-const FM = Cc["@mozilla.org/focus-manager;1"].
-              getService(Ci.nsIFocusManager);
-
-const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-
-const prefs = require("../preferences/service");
-const BROWSER = 'navigator:browser',
-      URI_BROWSER = prefs.get('browser.chromeURL', null),
-      NAME = '_blank',
-      FEATURES = 'chrome,all,dialog=no,non-private';
-
-function isWindowPrivate(win) {
-  if (!win)
-    return false;
-
-  // if the pbService is undefined, the PrivateBrowsingUtils.jsm is available,
-  // and the app is Firefox, then assume per-window private browsing is
-  // enabled.
-  try {
-    return win.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIWebNavigation)
-                  .QueryInterface(Ci.nsILoadContext)
-                  .usePrivateBrowsing;
-  }
-  catch(e) {}
-
-  // Sometimes the input is not a nsIDOMWindow.. but it is still a winodw.
-  try {
-    return !!win.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
-  }
-  catch (e) {}
-
-  return false;
-}
-exports.isWindowPrivate = isWindowPrivate;
-
-function getMostRecentBrowserWindow() {
-  return getMostRecentWindow(BROWSER);
-}
-exports.getMostRecentBrowserWindow = getMostRecentBrowserWindow;
-
-function getHiddenWindow() {
-  return appShellService.hiddenDOMWindow;
-}
-exports.getHiddenWindow = getHiddenWindow;
-
-function getMostRecentWindow(type) {
-  return WM.getMostRecentWindow(type);
-}
-exports.getMostRecentWindow = getMostRecentWindow;
-
-/**
- * Returns the ID of the window's current inner window.
- */
-function getInnerId(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).
-                getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
-};
-exports.getInnerId = getInnerId;
-
-/**
- * Returns the ID of the window's outer window.
- */
-function getOuterId(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).
-                getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
-};
-exports.getOuterId = getOuterId;
-
-/**
- * Returns window by the outer window id.
- */
-const getByOuterId = WM.getOuterWindowWithId;
-exports.getByOuterId = getByOuterId;
-
-const getByInnerId = WM.getCurrentInnerWindowWithId;
-exports.getByInnerId = getByInnerId;
-
-/**
- * Returns `nsIXULWindow` for the given `nsIDOMWindow`.
- */
-function getXULWindow(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIWebNavigation).
-    QueryInterface(Ci.nsIDocShellTreeItem).
-    treeOwner.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIXULWindow);
-};
-exports.getXULWindow = getXULWindow;
-
-function getDOMWindow(xulWindow) {
-  return xulWindow.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDOMWindow);
-}
-exports.getDOMWindow = getDOMWindow;
-
-/**
- * Returns `nsIBaseWindow` for the given `nsIDOMWindow`.
- */
-function getBaseWindow(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIWebNavigation).
-    QueryInterface(Ci.nsIDocShell).
-    QueryInterface(Ci.nsIDocShellTreeItem).
-    treeOwner.
-    QueryInterface(Ci.nsIBaseWindow);
-}
-exports.getBaseWindow = getBaseWindow;
-
-/**
- * Returns the `nsIDOMWindow` toplevel window for any child/inner window
- */
-function getToplevelWindow(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShellTreeItem)
-               .rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindow);
-}
-exports.getToplevelWindow = getToplevelWindow;
-
-function getWindowDocShell(window) {
-  return window.gBrowser.docShell;
-}
-exports.getWindowDocShell = getWindowDocShell;
-
-function getWindowLoadingContext(window) {
-  return getWindowDocShell(window).
-         QueryInterface(Ci.nsILoadContext);
-}
-exports.getWindowLoadingContext = getWindowLoadingContext;
-
-const isTopLevel = window => window && getToplevelWindow(window) === window;
-exports.isTopLevel = isTopLevel;
-
-/**
- * Takes hash of options and serializes it to a features string that
- * 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' || name == 'all'))
-      return result + ((value === true) ? ',' + name : '');
-
-    return result + ',' + name + '=' +
-           (value === true ? 'yes' : value === false ? 'no' : value);
-  }, '').substr(1);
-}
-
-/**
- * Opens a top level window and returns it's `nsIDOMWindow` representation.
- * @params {String} uri
- *    URI of the document to be loaded into window.
- * @params {nsIDOMWindow} options.parent
- *    Used as parent for the created window.
- * @params {String} options.name
- *    Optional name that is assigned to the window.
- * @params {Object} options.features
- *    Map of key, values like: `{ width: 10, height: 15, chrome: true, private: true }`.
- */
-function open(uri, options) {
-  uri = uri || URI_BROWSER;
-  options = options || {};
-
-  if (!uri)
-    throw new Error('browser.chromeURL is undefined, please provide an explicit uri');
-
-  if (['chrome', 'resource', 'data'].indexOf(io.newURI(uri).scheme) < 0)
-    throw new Error('only chrome, resource and data uris are allowed');
-
-  let newWindow = windowWatcher.
-    openWindow(options.parent || null,
-               uri,
-               options.name || null,
-               options.features ? serializeFeatures(options.features) : null,
-               options.args || null);
-
-  return newWindow;
-}
-exports.open = open;
-
-function onFocus(window) {
-  let { resolve, promise } = defer();
-
-  if (isFocused(window)) {
-    resolve(window);
-  }
-  else {
-    window.addEventListener("focus", function() {
-      resolve(window);
-    }, {capture: true, once: true});
-  }
-
-  return promise;
-}
-exports.onFocus = onFocus;
-
-var isFocused = dispatcher("window-isFocused");
-isFocused.when(x => x instanceof Ci.nsIDOMWindow, (window) => {
-  const FM = Cc["@mozilla.org/focus-manager;1"].
-                getService(Ci.nsIFocusManager);
-
-  let childTargetWindow = {};
-  FM.getFocusedElementForWindow(window, true, childTargetWindow);
-  childTargetWindow = childTargetWindow.value;
-
-  let focusedChildWindow = {};
-  if (FM.activeWindow) {
-    FM.getFocusedElementForWindow(FM.activeWindow, true, focusedChildWindow);
-    focusedChildWindow = focusedChildWindow.value;
-  }
-
-  return (focusedChildWindow === childTargetWindow);
-});
-exports.isFocused = isFocused;
-
-/**
- * Opens a top level window and returns it's `nsIDOMWindow` representation.
- * Same as `open` but with more features
- * @param {Object} options
- *
- */
-function openDialog(options) {
-  options = options || {};
-
-  let features = options.features || FEATURES;
-  let featureAry = features.toLowerCase().split(',');
-
-  if (!!options.private) {
-    // add private flag if private window is desired
-    if (!array.has(featureAry, 'private')) {
-      featureAry.push('private');
-    }
-
-    // remove the non-private flag ig a private window is desired
-    let nonPrivateIndex = featureAry.indexOf('non-private');
-    if (nonPrivateIndex >= 0) {
-      featureAry.splice(nonPrivateIndex, 1);
-    }
-
-    features = featureAry.join(',');
-  }
-
-  let browser = getMostRecentBrowserWindow();
-
-  // if there is no browser then do nothing
-  if (!browser)
-    return undefined;
-
-  let newWindow = browser.openDialog.apply(
-      browser,
-      array.flatten([
-        options.url || URI_BROWSER,
-        options.name || NAME,
-        features,
-        options.args || null
-      ])
-  );
-
-  return newWindow;
-}
-exports.openDialog = openDialog;
-
-/**
- * Returns an array of all currently opened windows.
- * Note that these windows may still be loading.
- */
-function windows(type, options) {
-  options = options || {};
-  let list = [];
-  let winEnum = WM.getEnumerator(type);
-  while (winEnum.hasMoreElements()) {
-    let window = winEnum.getNext().QueryInterface(Ci.nsIDOMWindow);
-    // Only add non-private windows when pb permission isn't set,
-    // unless an option forces the addition of them.
-    if (!window.closed && (options.includePrivate || !isWindowPrivate(window))) {
-      list.push(window);
-    }
-  }
-  return list;
-}
-exports.windows = windows;
-
-/**
- * Check if the given window is interactive.
- * i.e. if its "DOMContentLoaded" event has already been fired.
- * @params {nsIDOMWindow} window
- */
-const isInteractive = window =>
-  window.document.readyState === "interactive" ||
-  isDocumentLoaded(window) ||
-  // XUL documents stays '"uninitialized"' until it's `readyState` becomes
-  // `"complete"`.
-  isXULDocumentWindow(window) && window.document.readyState === "interactive";
-exports.isInteractive = isInteractive;
-
-/**
- * Check if the given browser window has finished the startup.
- * @params {nsIDOMWindow} window
- */
-const isStartupFinished = (window) =>
-  isBrowser(window) &&
-  window.gBrowserInit &&
-  window.gBrowserInit.delayedStartupFinished;
-
-exports.isStartupFinished = isStartupFinished;
-
-const isXULDocumentWindow = ({document}) =>
-  document.documentElement &&
-  document.documentElement.namespaceURI === XUL_NS;
-
-/**
- * Check if the given window is completely loaded.
- * i.e. if its "load" event has already been fired and all possible DOM content
- * is done loading (the whole DOM document, images content, ...)
- * @params {nsIDOMWindow} window
- */
-function isDocumentLoaded(window) {
-  return window.document.readyState == "complete";
-}
-exports.isDocumentLoaded = isDocumentLoaded;
-
-function isBrowser(window) {
-  try {
-    return window.document.documentElement.getAttribute("windowtype") === BROWSER;
-  }
-  catch (e) {}
-  return false;
-};
-exports.isBrowser = isBrowser;
-
-function getWindowTitle(window) {
-  return window && window.document ? window.document.title : null;
-}
-exports.getWindowTitle = getWindowTitle;
-
-function isXULBrowser(window) {
-  return !!(isBrowser(window) && window.XULBrowserWindow);
-}
-exports.isXULBrowser = isXULBrowser;
-
-/**
- * Returns the most recent focused window
- */
-function getFocusedWindow() {
-  let window = WM.getMostRecentWindow(BROWSER);
-
-  return window ? window.document.commandDispatcher.focusedWindow : null;
-}
-exports.getFocusedWindow = getFocusedWindow;
-
-/**
- * Returns the focused browser window if any, or the most recent one.
- * Opening new window, updates most recent window, but focus window
- * changes later; so most recent window and focused window are not always
- * the same.
- */
-function getFocusedBrowser() {
-  let window = FM.activeWindow;
-  return isBrowser(window) ? window : getMostRecentBrowserWindow()
-}
-exports.getFocusedBrowser = getFocusedBrowser;
-
-/**
- * Returns the focused element in the most recent focused window
- */
-function getFocusedElement() {
-  let window = WM.getMostRecentWindow(BROWSER);
-
-  return window ? window.document.commandDispatcher.focusedElement : null;
-}
-exports.getFocusedElement = getFocusedElement;
-
-function getFrames(window) {
-  return Array.slice(window.frames).reduce(function(frames, frame) {
-    return frames.concat(frame, getFrames(frame));
-  }, []);
-}
-exports.getFrames = getFrames;
-
-function getScreenPixelsPerCSSPixel(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).
-                getInterface(Ci.nsIDOMWindowUtils).screenPixelsPerCSSPixel;
-}
-exports.getScreenPixelsPerCSSPixel = getScreenPixelsPerCSSPixel;
-
-function getOwnerBrowserWindow(node) {
-  /**
-  Takes DOM node and returns browser window that contains it.
-  **/
-  let window = getToplevelWindow(node.ownerGlobal);
-  // If anchored window is browser then it's target browser window.
-  return isBrowser(window) ? window : null;
-}
-exports.getOwnerBrowserWindow = getOwnerBrowserWindow;
-
-function getParentWindow(window) {
-  try {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIWebNavigation)
-      .QueryInterface(Ci.nsIDocShellTreeItem).parent
-      .QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIDOMWindow);
-  }
-  catch (e) {}
-  return null;
-}
-exports.getParentWindow = getParentWindow;
-
-
-function getParentFrame(window) {
-  try {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIWebNavigation)
-      .QueryInterface(Ci.nsIDocShellTreeItem).parent
-      .QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIDOMWindow);
-  }
-  catch (e) {}
-  return null;
-}
-exports.getParentWindow = getParentWindow;
-
-// The element in which the window is embedded, or `null`
-// if the window is top-level. Similar to `window.frameElement`
-// but can cross chrome-content boundries.
-const getFrameElement = target =>
-  (target instanceof Ci.nsIDOMDocument ? target.defaultView : target).
-  QueryInterface(Ci.nsIInterfaceRequestor).
-  getInterface(Ci.nsIDOMWindowUtils).
-  containerElement;
-exports.getFrameElement = getFrameElement;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/zip/utils.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cc, Ci } = require("chrome");
-
-function getZipReader(aFile) {
-  return new Promise(resolve => {
-    let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
-                        createInstance(Ci.nsIZipReader);
-    zipReader.open(aFile);
-    resolve(zipReader);
-  });
-};
-exports.getZipReader = getZipReader;
deleted file mode 100644
--- a/addon-sdk/source/lib/test.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/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-module.exports = require("sdk/test");
deleted file mode 100644
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ /dev/null
@@ -1,1271 +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/. */
-
-;((factory) => { // Module boilerplate :(
-  if (typeof(require) === 'function') { // CommonJS
-    require("chrome").Cu.import(module.uri, exports);
-  }
-  else if (~String(this).indexOf('BackstagePass')) { // JSM
-    let module = { uri: __URI__, id: "toolkit/loader", exports: Object.create(null) }
-    factory(module);
-    Object.assign(this, module.exports);
-    this.EXPORTED_SYMBOLS = Object.getOwnPropertyNames(module.exports);
-  }
-  else {
-    throw Error("Loading environment is not supported");
-  }
-})(module => {
-
-'use strict';
-
-module.metadata = {
-  "stability": "unstable"
-};
-
-const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
-        results: Cr, manager: Cm } = Components;
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const { addObserver, notifyObservers } = Cc['@mozilla.org/observer-service;1'].
-                        getService(Ci.nsIObserverService);
-const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-const { normalize, dirname } = Cu.import("resource://gre/modules/osfile/ospath_unix.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "resProto",
-                                   "@mozilla.org/network/protocol;1?name=resource",
-                                   "nsIResProtocolHandler");
-XPCOMUtils.defineLazyServiceGetter(this, "zipCache",
-                                   "@mozilla.org/libjar/zip-reader-cache;1",
-                                   "nsIZipReaderCache");
-
-const { defineLazyGetter } = XPCOMUtils;
-
-defineLazyGetter(this, "XulApp", () => {
-  let xulappURI = module.uri.replace("toolkit/loader.js",
-                                     "sdk/system/xul-app.jsm");
-  return Cu.import(xulappURI, {});
-});
-
-// Define some shortcuts.
-const bind = Function.call.bind(Function.bind);
-const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-const prototypeOf = Object.getPrototypeOf;
-function* getOwnIdentifiers(x) {
-  yield* Object.getOwnPropertyNames(x);
-  yield* Object.getOwnPropertySymbols(x);
-}
-
-const NODE_MODULES = new Set([
-  "assert",
-  "buffer_ieee754",
-  "buffer",
-  "child_process",
-  "cluster",
-  "console",
-  "constants",
-  "crypto",
-  "_debugger",
-  "dgram",
-  "dns",
-  "domain",
-  "events",
-  "freelist",
-  "fs",
-  "http",
-  "https",
-  "_linklist",
-  "module",
-  "net",
-  "os",
-  "path",
-  "punycode",
-  "querystring",
-  "readline",
-  "repl",
-  "stream",
-  "string_decoder",
-  "sys",
-  "timers",
-  "tls",
-  "tty",
-  "url",
-  "util",
-  "vm",
-  "zlib",
-]);
-
-const COMPONENT_ERROR = '`Components` is not available in this context.\n' +
-  'Functionality provided by Components may be available in an SDK\n' +
-  'module: https://developer.mozilla.org/en-US/Add-ons/SDK \n\n' +
-  'However, if you still need to import Components, you may use the\n' +
-  '`chrome` module\'s properties for shortcuts to Component properties:\n\n' +
-  'Shortcuts: \n' +
-  '    Cc = Components' + '.classes \n' +
-  '    Ci = Components' + '.interfaces \n' +
-  '    Cu = Components' + '.utils \n' +
-  '    CC = Components' + '.Constructor \n' +
-  'Example: \n' +
-  '    let { Cc, Ci } = require(\'chrome\');\n';
-
-// Workaround for bug 674195. Freezing objects from other compartments fail,
-// so we use `Object.freeze` from the same component instead.
-function freeze(object) {
-  if (prototypeOf(object) === null) {
-      Object.freeze(object);
-  }
-  else {
-    prototypeOf(prototypeOf(object.isPrototypeOf)).
-      constructor. // `Object` from the owner compartment.
-      freeze(object);
-  }
-  return object;
-}
-
-// Returns map of given `object`-s own property descriptors.
-const descriptor = iced(function descriptor(object) {
-  let value = {};
-  for (let name of getOwnIdentifiers(object))
-    value[name] = getOwnPropertyDescriptor(object, name)
-  return value;
-});
-Loader.descriptor = descriptor;
-
-// Freeze important built-ins so they can't be used by untrusted code as a
-// message passing channel.
-freeze(Object);
-freeze(Object.prototype);
-freeze(Function);
-freeze(Function.prototype);
-freeze(Array);
-freeze(Array.prototype);
-freeze(String);
-freeze(String.prototype);
-
-// This function takes `f` function sets it's `prototype` to undefined and
-// freezes it. We need to do this kind of deep freeze with all the exposed
-// functions so that untrusted code won't be able to use them a message
-// passing channel.
-function iced(f) {
-  if (!Object.isFrozen(f)) {
-    f.prototype = undefined;
-  }
-  return freeze(f);
-}
-
-// Defines own properties of given `properties` object on the given
-// target object overriding any existing property with a conflicting name.
-// Returns `target` object. Note we only export this function because it's
-// useful during loader bootstrap when other util modules can't be used &
-// thats only case where this export should be used.
-const override = iced(function override(target, source) {
-  let properties = descriptor(target);
-
-  for (let name of getOwnIdentifiers(source || {}))
-    properties[name] = getOwnPropertyDescriptor(source, name);
-
-  return Object.defineProperties({}, properties);
-});
-Loader.override = override;
-
-function sourceURI(uri) { return String(uri).split(" -> ").pop(); }
-Loader.sourceURI = iced(sourceURI);
-
-function isntLoaderFrame(frame) { return frame.fileName !== module.uri }
-
-function parseURI(uri) { return String(uri).split(" -> ").pop(); }
-Loader.parseURI = parseURI;
-
-function parseStack(stack) {
-  let lines = String(stack).split("\n");
-  return lines.reduce(function(frames, line) {
-    if (line) {
-      let atIndex = line.indexOf("@");
-      let columnIndex = line.lastIndexOf(":");
-      let lineIndex = line.lastIndexOf(":", columnIndex - 1);
-      let fileName = parseURI(line.slice(atIndex + 1, lineIndex));
-      let lineNumber = parseInt(line.slice(lineIndex + 1, columnIndex));
-      let columnNumber = parseInt(line.slice(columnIndex + 1));
-      let name = line.slice(0, atIndex).split("(").shift();
-      frames.unshift({
-        fileName: fileName,
-        name: name,
-        lineNumber: lineNumber,
-        columnNumber: columnNumber
-      });
-    }
-    return frames;
-  }, []);
-}
-Loader.parseStack = parseStack;
-
-function serializeStack(frames) {
-  return frames.reduce(function(stack, frame) {
-    return frame.name + "@" +
-           frame.fileName + ":" +
-           frame.lineNumber + ":" +
-           frame.columnNumber + "\n" +
-           stack;
-  }, "");
-}
-Loader.serializeStack = serializeStack;
-
-class DefaultMap extends Map {
-  constructor(createItem, items = undefined) {
-    super(items);
-
-    this.createItem = createItem;
-  }
-
-  get(key) {
-    if (!this.has(key)) {
-      this.set(key, this.createItem(key));
-    }
-
-    return super.get(key);
-  }
-}
-
-const urlCache = {
-  /**
-   * Returns a list of fully-qualified URLs for entries within the zip
-   * file at the given URI which are either directories or files with a
-   * .js or .json extension.
-   *
-   * @param {nsIJARURI} uri
-   * @param {string} baseURL
-   *        The original base URL, prior to resolution.
-   *
-   * @returns {Set<string>}
-   */
-  getZipFileContents(uri, baseURL) {
-    // Make sure the path has a trailing slash, and strip off the leading
-    // slash, so that we can easily check whether it is a path prefix.
-    let basePath = addTrailingSlash(uri.JAREntry).slice(1);
-    let file = uri.JARFile.QueryInterface(Ci.nsIFileURL).file;
-
-    let enumerator = zipCache.getZip(file).findEntries("(*.js|*.json|*/)");
-
-    let results = new Set();
-    for (let entry of XPCOMUtils.IterStringEnumerator(enumerator)) {
-      if (entry.startsWith(basePath)) {
-        let path = entry.slice(basePath.length);
-
-        results.add(baseURL + path);
-      }
-    }
-
-    return results;
-  },
-
-  zipContentsCache: new DefaultMap(baseURL => {
-    let uri = NetUtil.newURI(baseURL);
-
-    if (baseURL.startsWith("resource:")) {
-      uri = NetUtil.newURI(resProto.resolveURI(uri));
-    }
-
-    if (uri instanceof Ci.nsIJARURI) {
-      return urlCache.getZipFileContents(uri, baseURL);
-    }
-
-    return null;
-  }),
-
-  filesCache: new DefaultMap(url => {
-    try {
-      let uri = NetUtil.newURI(url).QueryInterface(Ci.nsIFileURL);
-
-      return uri.file.exists();
-    } catch (e) {
-      return false;
-    }
-  }),
-
-  resolutionCache: new DefaultMap(fullId => {
-    return (resolveAsFile(fullId) ||
-            resolveAsDirectory(fullId));
-  }),
-
-  nodeModulesCache: new Map(),
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
-
-  observe() {
-    // Clear any module resolution caches when the startup cache is flushed,
-    // since it probably means we're loading new copies of extensions.
-    this.zipContentsCache.clear();
-    this.filesCache.clear();
-    this.resolutionCache.clear();
-    this.nodeModulesCache.clear();
-  },
-
-  getNodeModulePaths(rootURI, start) {
-    let url = join(rootURI, start);
-
-    if (this.nodeModulesCache.has(url))
-      return this.nodeModulesCache.get(url);
-
-    let result = Array.from(getNodeModulePaths(rootURI, start));
-    this.nodeModulesCache.set(url, result);
-    return result;
-  },
-
-  /**
-   * Returns the base URL for the given URL, if one can be determined. For
-   * a resource: URL, this is the root of the resource package. For a jar:
-   * URL, it is the root of the JAR file. Otherwise, null is returned.
-   *
-   * @param {string} url
-   * @returns {string?}
-   */
-  getBaseURL(url) {
-    // By using simple string matching for the common case of resource: URLs
-    // backed by jar: URLs, we can avoid creating any nsIURI objects for the
-    // common case where the JAR contents are already cached.
-    if (url.startsWith("resource://")) {
-      return /^resource:\/\/[^\/]+\//.exec(url)[0];
-    }
-
-    let uri = NetUtil.newURI(url);
-    if (uri instanceof Ci.nsIJARURI) {
-      return `jar:${uri.JARFile.spec}!/`;
-    }
-
-    return null;
-  },
-
-  /**
-   * Returns true if the target of the given URL exists as a local file,
-   * or as an entry in a local zip file.
-   *
-   * @param {string} url
-   * @returns {boolean}
-   */
-  exists(url) {
-    if (!/\.(?:js|json)$/.test(url)) {
-      url = addTrailingSlash(url);
-    }
-
-    let baseURL = this.getBaseURL(url);
-    let scripts = baseURL && this.zipContentsCache.get(baseURL);
-    if (scripts) {
-      return scripts.has(url);
-    }
-
-    return this.filesCache.get(url);
-  },
-}
-addObserver(urlCache, "startupcache-invalidate", true);
-
-function readURI(uri) {
-  let nsURI = NetUtil.newURI(uri);
-  if (nsURI.scheme == "resource") {
-    // Resolve to a real URI, this will catch any obvious bad paths without
-    // logging assertions in debug builds, see bug 1135219
-    uri = resProto.resolveURI(nsURI);
-  }
-
-  let stream = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, 'UTF-8'),
-    loadUsingSystemPrincipal: true}
-  ).open2();
-  let count = stream.available();
-  let data = NetUtil.readInputStreamToString(stream, count, {
-    charset: 'UTF-8'
-  });
-
-  stream.close();
-
-  return data;
-}
-
-// Combines all arguments into a resolved, normalized path
-function join(base, ...paths) {
-  // If this is an absolute URL, we need to normalize only the path portion,
-  // or we wind up stripping too many slashes and producing invalid URLs.
-  let match = /^((?:resource|file|chrome)\:\/\/[^\/]*|jar:[^!]+!)(.*)/.exec(base);
-  if (match) {
-    return match[1] + normalize([match[2], ...paths].join("/"));
-  }
-
-  return normalize([base, ...paths].join("/"));
-}
-Loader.join = join;
-
-// Function takes set of options and returns a JS sandbox. Function may be
-// passed set of options:
-//  - `name`: A string value which identifies the sandbox in about:memory. Will
-//    throw exception if omitted.
-// - `principal`: String URI or `nsIPrincipal` for the sandbox. Defaults to
-//    system principal.
-// - `prototype`: Ancestor for the sandbox that will be created. Defaults to
-//    `{}`.
-// - `wantXrays`: A Boolean value indicating whether code outside the sandbox
-//    wants X-ray vision with respect to objects inside the sandbox. Defaults
-//    to `true`.
-// - `sandbox`: A sandbox to share JS compartment with. If omitted new
-//    compartment will be created.
-// - `metadata`: A metadata object associated with the sandbox. It should
-//    be JSON-serializable.
-// For more details see:
-// https://developer.mozilla.org/en/Components.utils.Sandbox
-const Sandbox = iced(function Sandbox(options) {
-  // Normalize options and rename to match `Cu.Sandbox` expectations.
-  options = {
-    // Do not expose `Components` if you really need them (bad idea!) you
-    // still can expose via prototype.
-    wantComponents: false,
-    sandboxName: options.name,
-    principal: 'principal' in options ? options.principal : systemPrincipal,
-    wantXrays: 'wantXrays' in options ? options.wantXrays : true,
-    wantGlobalProperties: 'wantGlobalProperties' in options ?
-                          options.wantGlobalProperties : [],
-    sandboxPrototype: 'prototype' in options ? options.prototype : {},
-    invisibleToDebugger: 'invisibleToDebugger' in options ?
-                         options.invisibleToDebugger : false,
-    metadata: 'metadata' in options ? options.metadata : {},
-    waiveIntereposition: !!options.waiveIntereposition
-  };
-
-  if (options.metadata && options.metadata.addonID) {
-    options.addonId = options.metadata.addonID;
-  }
-
-  let sandbox = Cu.Sandbox(options.principal, options);
-
-  // Each sandbox at creation gets set of own properties that will be shadowing
-  // ones from it's prototype. We override delete such `sandbox` properties
-  // to avoid shadowing.
-  delete sandbox.Iterator;
-  delete sandbox.Components;
-  delete sandbox.importFunction;
-  delete sandbox.debug;
-
-  return sandbox;
-});
-Loader.Sandbox = Sandbox;
-
-// Evaluates code from the given `uri` into given `sandbox`. If
-// `options.source` is passed, then that code is evaluated instead.
-// Optionally following options may be given:
-// - `options.encoding`: Source encoding, defaults to 'UTF-8'.
-// - `options.line`: Line number to start count from for stack traces.
-//    Defaults to 1.
-// - `options.version`: Version of JS used, defaults to '1.8'.
-const evaluate = iced(function evaluate(sandbox, uri, options) {
-  let { source, line, version, encoding } = override({
-    encoding: 'UTF-8',
-    line: 1,
-    version: '1.8',
-    source: null
-  }, options);
-
-  return source ? Cu.evalInSandbox(source, sandbox, version, uri, line)
-                : loadSubScript(uri, sandbox, encoding);
-});
-Loader.evaluate = evaluate;
-
-// Populates `exports` of the given CommonJS `module` object, in the context
-// of the given `loader` by evaluating code associated with it.
-const load = iced(function load(loader, module) {
-  let { sandboxes, globals, loadModuleHook } = loader;
-  let require = Require(loader, module);
-
-  // We expose set of properties defined by `CommonJS` specification via
-  // prototype of the sandbox. Also globals are deeper in the prototype
-  // chain so that each module has access to them as well.
-  let descriptors = descriptor({
-    require: require,
-    module: module,
-    exports: module.exports,
-    get Components() {
-      // Expose `Components` property to throw error on usage with
-      // additional information
-      throw new ReferenceError(COMPONENT_ERROR);
-    }
-  });
-
-  let sandbox;
-  if ((loader.useSharedGlobalSandbox || isSystemURI(module.uri)) &&
-      loader.sharedGlobalBlocklist.indexOf(module.id) == -1) {
-    // Create a new object in this sandbox, that will be used as
-    // the scope object for this particular module
-    sandbox = new loader.sharedGlobalSandbox.Object();
-    descriptors.lazyRequire = {
-      configurable: true,
-      value: lazyRequire.bind(sandbox),
-    };
-    descriptors.lazyRequireModule = {
-      configurable: true,
-      value: lazyRequireModule.bind(sandbox),
-    };
-
-    if ("console" in globals) {
-      descriptors.console = {
-        configurable: true,
-        get() {
-          return globals.console;
-        },
-      };
-    }
-    let define = Object.getOwnPropertyDescriptor(globals, "define");
-    if (define && define.value)
-      descriptors.define = define;
-    if ("DOMParser" in globals)
-      descriptors.DOMParser = Object.getOwnPropertyDescriptor(globals, "DOMParser");
-    Object.defineProperties(sandbox, descriptors);
-  }
-  else {
-    sandbox = Sandbox({
-      name: module.uri,
-      prototype: Object.create(globals, descriptors),
-      wantXrays: false,
-      wantGlobalProperties: module.id == "sdk/indexed-db" ? ["indexedDB"] : [],
-      invisibleToDebugger: loader.invisibleToDebugger,
-      metadata: {
-        addonID: loader.id,
-        URI: module.uri
-      }
-    });
-  }
-  sandboxes[module.uri] = sandbox;
-
-  let originalExports = module.exports;
-  try {
-    evaluate(sandbox, module.uri);
-  }
-  catch (error) {
-    let { message, fileName, lineNumber } = error;
-    let stack = error.stack || Error().stack;
-    let frames = parseStack(stack).filter(isntLoaderFrame);
-    let toString = String(error);
-    let file = sourceURI(fileName);
-
-    // Note that `String(error)` where error is from subscript loader does
-    // not puts `:` after `"Error"` unlike regular errors thrown by JS code.
-    // If there is a JS stack then this error has already been handled by an
-    // inner module load.
-    if (/^Error opening input stream/.test(String(error))) {
-      let caller = frames.slice(0).pop();
-      fileName = caller.fileName;
-      lineNumber = caller.lineNumber;
-      message = "Module `" + module.id + "` is not found at " + module.uri;
-      toString = message;
-    }
-    // Workaround for a Bug 910653. Errors thrown by subscript loader
-    // do not include `stack` field and above created error won't have
-    // fileName or lineNumber of the module being loaded, so we ensure
-    // it does.
-    else if (frames[frames.length - 1].fileName !== file) {
-      frames.push({ fileName: file, lineNumber: lineNumber, name: "" });
-    }
-
-    let prototype = typeof(error) === "object" ? error.constructor.prototype :
-                    Error.prototype;
-
-    throw Object.create(prototype, {
-      message: { value: message, writable: true, configurable: true },
-      fileName: { value: fileName, writable: true, configurable: true },
-      lineNumber: { value: lineNumber, writable: true, configurable: true },
-      stack: { value: serializeStack(frames), writable: true, configurable: true },
-      toString: { value: () => toString, writable: true, configurable: true },
-    });
-  }
-
-  if (loadModuleHook) {
-    module = loadModuleHook(module, require);
-  }
-
-  if (loader.checkCompatibility) {
-    let err = XulApp.incompatibility(module);
-    if (err) {
-      throw err;
-    }
-  }
-
-  // Only freeze the exports object if we created it ourselves. Modules
-  // which completely replace the exports object and still want it
-  // frozen need to freeze it themselves.
-  if (module.exports === originalExports)
-    Object.freeze(module.exports);
-
-  return module;
-});
-Loader.load = load;
-
-// Utility function to normalize module `uri`s so they have `.js` extension.
-function normalizeExt(uri) {
-  return isJSURI(uri) ? uri :
-         isJSONURI(uri) ? uri :
-         isJSMURI(uri) ? uri :
-         uri + '.js';
-}
-
-// Utility function to join paths. In common case `base` is a
-// `requirer.uri` but in some cases it may be `baseURI`. In order to
-// avoid complexity we require `baseURI` with a trailing `/`.
-const resolve = iced(function resolve(id, base) {
-  if (!isRelative(id))
-    return id;
-
-  let baseDir = dirname(base);
-
-  let resolved;
-  if (baseDir.includes(":"))
-    resolved = join(baseDir, id);
-  else
-    resolved = normalize(`${baseDir}/${id}`);
-
-  // Joining and normalizing removes the './' from relative files.
-  // We need to ensure the resolution still has the root
-  if (base.startsWith('./'))
-    resolved = './' + resolved;
-
-  return resolved;
-});
-Loader.resolve = resolve;
-
-// Attempts to load `path` and then `path.js`
-// Returns `path` with valid file, or `undefined` otherwise
-function resolveAsFile(path) {
-  // Append '.js' to path name unless it's another support filetype
-  path = normalizeExt(path);
-  if (urlCache.exists(path)) {
-    return path;
-  }
-
-  return null;
-}
-
-// Attempts to load `path/package.json`'s `main` entry,
-// followed by `path/index.js`, or `undefined` otherwise
-function resolveAsDirectory(path) {
-  try {
-    // If `path/package.json` exists, parse the `main` entry
-    // and attempt to load that
-    let manifestPath = addTrailingSlash(path) + 'package.json';
-
-    let main = (urlCache.exists(manifestPath) &&
-                getManifestMain(JSON.parse(readURI(manifestPath))));
-    if (main) {
-      let found = resolveAsFile(join(path, main));
-      if (found) {
-        return found
-      }
-    }
-  } catch (e) {}
-
-  return resolveAsFile(addTrailingSlash(path) + 'index.js');
-}
-
-function resolveRelative(rootURI, modulesDir, id) {
-  let fullId = join(rootURI, modulesDir, id);
-
-  let resolvedPath = urlCache.resolutionCache.get(fullId);
-  if (resolvedPath) {
-    return './' + resolvedPath.slice(rootURI.length);
-  }
-
-  return null;
-}
-
-// From `resolve` module
-// https://github.com/substack/node-resolve/blob/master/lib/node-modules-paths.js
-function* getNodeModulePaths(rootURI, start) {
-  let moduleDir = 'node_modules';
-
-  let parts = start.split('/');
-  while (parts.length) {
-    let leaf = parts.pop();
-    let path = [...parts, leaf, moduleDir].join("/");
-    if (leaf !== moduleDir && urlCache.exists(join(rootURI, path))) {
-      yield path;
-    }
-  }
-
-  if (urlCache.exists(join(rootURI, moduleDir))) {
-    yield moduleDir;
-  }
-}
-
-// Node-style module lookup
-// Takes an id and path and attempts to load a file using node's resolving
-// algorithm.
-// `id` should already be resolved relatively at this point.
-// http://nodejs.org/api/modules.html#modules_all_together
-const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
-  // Resolve again
-  id = Loader.resolve(id, requirer);
-
-  // If this is already an absolute URI then there is no resolution to do
-  if (isAbsoluteURI(id)) {
-    return null;
-  }
-
-  // we assume that extensions are correct, i.e., a directory doesnt't have '.js'
-  // and a js file isn't named 'file.json.js'
-  let resolvedPath;
-
-  if ((resolvedPath = resolveRelative(rootURI, "", id))) {
-    return resolvedPath;
-  }
-
-  // If the requirer is an absolute URI then the node module resolution below
-  // won't work correctly as we prefix everything with rootURI
-  if (isAbsoluteURI(requirer)) {
-    return null;
-  }
-
-  // If manifest has dependencies, attempt to look up node modules
-  // in the `dependencies` list
-  for (let modulesDir of urlCache.getNodeModulePaths(rootURI, dirname(requirer))) {
-    if ((resolvedPath = resolveRelative(rootURI, modulesDir, id))) {
-      return resolvedPath;
-    }
-  }
-
-  // We would not find lookup for things like `sdk/tabs`, as that's part of
-  // the alias mapping. If during `generateMap`, the runtime lookup resolves
-  // with `resolveURI` -- if during runtime, then `resolve` will throw.
-  return null;
-});
-
-Loader.nodeResolve = nodeResolve;
-
-function addTrailingSlash(path) {
-  return path.replace(/\/*$/, "/");
-}
-
-function compileMapping(paths) {
-  // Make mapping array that is sorted from longest path to shortest path.
-  let mapping = Object.keys(paths)
-                      .sort((a, b) => b.length - a.length)
-                      .map(path => [path, paths[path]]);
-
-  const PATTERN = /([.\\?+*(){}[\]^$])/g;
-  const escapeMeta = str => str.replace(PATTERN, '\\$1')
-
-  let patterns = [];
-  paths = {};
-
-  for (let [path, uri] of mapping) {
-    // Strip off any trailing slashes to make comparisons simpler
-    if (path.endsWith("/")) {
-      path = path.slice(0, -1);
-      uri = uri.replace(/\/+$/, "");
-    }
-
-    paths[path] = uri;
-
-    // We only want to match path segments explicitly. Examples:
-    // * "foo/bar" matches for "foo/bar"
-    // * "foo/bar" matches for "foo/bar/baz"
-    // * "foo/bar" does not match for "foo/bar-1"
-    // * "foo/bar/" does not match for "foo/bar"
-    // * "foo/bar/" matches for "foo/bar/baz"
-    //
-    // Check for an empty path, an exact match, or a substring match
-    // with the next character being a forward slash.
-    if (path == "")
-      patterns.push("");
-    else
-      patterns.push(`${escapeMeta(path)}(?=$|/)`);
-  }
-
-  let pattern = new RegExp(`^(${patterns.join('|')})`);
-
-  // This will replace the longest matching path mapping at the start of
-  // the ID string with its mapped value.
-  return id => {
-    return id.replace(pattern, (m0, m1) => paths[m1]);
-  };
-}
-
-const resolveURI = iced(function resolveURI(id, mapping) {
-  // Do not resolve if already a resource URI
-  if (isAbsoluteURI(id))
-    return normalizeExt(id);
-
-  return normalizeExt(mapping(id))
-});
-Loader.resolveURI = resolveURI;
-
-/**
- * Defines lazy getters on the given object, which lazily require the
- * given module the first time they are accessed, and then resolve that
- * module's exported properties.
- *
- * @param {object} obj
- *        The target object on which to define the lazy getters.
- * @param {string} moduleId
- *        The ID of the module to require, as passed to require().
- * @param {Array<string | object>} args
- *        Any number of properties to import from the module. A string
- *        will cause the property to be defined which resolves to the
- *        same property in the module's exports. An object will define a
- *        lazy getter for every value in the object which corresponds to
- *        the given key in the module's exports, as in an ordinary
- *        destructuring assignment.
- */
-function lazyRequire(obj, moduleId, ...args) {
-  let module;
-  let getModule = () => {
-    if (!module)
-      module = this.require(moduleId);
-    return module;
-  };
-
-  for (let props of args) {
-    if (typeof props !== "object")
-      props = {[props]: props};
-
-    for (let [fromName, toName] of Object.entries(props))
-      defineLazyGetter(obj, toName, () => getModule()[fromName]);
-  }
-}
-
-/**
- * Defines a lazy getter on the given object which causes a module to be
- * lazily imported the first time it is accessed.
- *
- * @param {object} obj
- *        The target object on which to define the lazy getter.
- * @param {string} moduleId
- *        The ID of the module to require, as passed to require().
- * @param {string} [prop = moduleId]
- *        The name of the lazy getter property to define.
- */
-function lazyRequireModule(obj, moduleId, prop = moduleId) {
-  defineLazyGetter(obj, prop, () => this.require(moduleId));
-}
-
-
-// Creates version of `require` that will be exposed to the given `module`
-// in the context of the given `loader`. Each module gets own limited copy
-// of `require` that is allowed to load only a modules that are associated
-// with it during link time.
-const Require = iced(function Require(loader, requirer) {
-  let {
-    modules, mapping, mappingCache, resolve: loaderResolve, load,
-    manifest, rootURI, isNative, requireHook
-  } = loader;
-
-  if (isSystemURI(requirer.uri)) {
-    // Built-in modules don't require the expensive module resolution
-    // algorithm used by SDK add-ons, so give them the more efficient standard
-    // resolve instead.
-    isNative = false;
-    loaderResolve = Loader.resolve;
-  }
-
-  function require(id) {
-    if (!id) // Throw if `id` is not passed.
-      throw Error('You must provide a module name when calling require() from '
-                  + requirer.id, requirer.uri);
-
-    if (requireHook) {
-      return requireHook(id, _require);
-    }
-
-    return _require(id);
-  }
-
-  function _require(id) {
-    let { uri, requirement } = getRequirements(id);
-
-    let module = null;
-    // If module is already cached by loader then just use it.
-    if (uri in modules) {
-      module = modules[uri];
-    }
-    else if (isJSMURI(uri)) {
-      module = modules[uri] = Module(requirement, uri);
-      module.exports = Cu.import(uri, {});
-      freeze(module);
-    }
-    else if (isJSONURI(uri)) {
-      let data;
-
-      // First attempt to load and parse json uri
-      // ex: `test.json`
-      // If that doesn't exist, check for `test.json.js`
-      // for node parity
-      try {
-        data = JSON.parse(readURI(uri));
-        module = modules[uri] = Module(requirement, uri);
-        module.exports = data;
-        freeze(module);
-      }
-      catch (err) {
-        // If error thrown from JSON parsing, throw that, do not
-        // attempt to find .json.js file
-        if (err && /JSON\.parse/.test(err.message))
-          throw err;
-        uri = uri + '.js';
-      }
-    }
-
-    // If not yet cached, load and cache it.
-    // We also freeze module to prevent it from further changes
-    // at runtime.
-    if (!(uri in modules)) {
-      // Many of the loader's functionalities are dependent
-      // on modules[uri] being set before loading, so we set it and
-      // remove it if we have any errors.
-      module = modules[uri] = Module(requirement, uri);
-      try {
-        Object.freeze(load(loader, module));
-      }
-      catch (e) {
-        // Clear out modules cache so we can throw on a second invalid require
-        delete modules[uri];
-        // Also clear out the Sandbox that was created
-        delete loader.sandboxes[uri];
-        throw e;
-      }
-    }
-
-    return module.exports;
-  }
-
-  // Resolution function taking a module name/path and
-  // returning a resourceURI and a `requirement` used by the loader.
-  // Used by both `require` and `require.resolve`.
-  function getRequirements(id) {
-    if (!id) // Throw if `id` is not passed.
-      throw Error('you must provide a module name when calling require() from '
-                  + requirer.id, requirer.uri);
-
-    let requirement, uri;
-
-    // TODO should get native Firefox modules before doing node-style lookups
-    // to save on loading time
-    if (isNative) {
-      let { overrides } = manifest.jetpack;
-      for (let key in overrides) {
-        // ignore any overrides using relative keys
-        if (/^[.\/]/.test(key)) {
-          continue;
-        }
-
-        // If the override is for x -> y,
-        // then using require("x/lib/z") to get reqire("y/lib/z")
-        // should also work
-        if (id == key || id.startsWith(key + "/")) {
-          id = overrides[key] + id.substr(key.length);
-          id = id.replace(/^[.\/]+/, "");
-        }
-      }
-
-      // For native modules, we want to check if it's a module specified
-      // in 'modules', like `chrome`, or `@loader` -- if it exists,
-      // just set the uri to skip resolution
-      if (!requirement && modules[id])
-        uri = requirement = id;
-
-      if (!requirement && !NODE_MODULES.has(id)) {
-        // If `isNative` defined, this is using the new, native-style
-        // loader, not cuddlefish, so lets resolve using node's algorithm
-        // and get back a path that needs to be resolved via paths mapping
-        // in `resolveURI`
-        requirement = loaderResolve(id, requirer.id, {
-          manifest: manifest,
-          rootURI: rootURI
-        });
-      }
-
-      // If not found in the map, not a node module, and wasn't able to be
-      // looked up, it's something
-      // found in the paths most likely, like `sdk/tabs`, which should
-      // be resolved relatively if needed using traditional resolve
-      if (!requirement) {
-        requirement = isRelative(id) ? Loader.resolve(id, requirer.id) : id;
-      }
-    }
-    else if (modules[id]) {
-      uri = requirement = id;
-    }
-    else if (requirer) {
-      // Resolve `id` to its requirer if it's relative.
-      requirement = loaderResolve(id, requirer.id);
-    }
-    else {
-      requirement = id;
-    }
-
-    // Resolves `uri` of module using loaders resolve function.
-    if (!uri) {
-      if (mappingCache.has(requirement)) {
-        uri = mappingCache.get(requirement);
-      } else {
-        uri = resolveURI(requirement, mapping);
-        mappingCache.set(requirement, uri);
-      }
-    }
-
-    // Throw if `uri` can not be resolved.
-    if (!uri) {
-      throw Error('Module: Can not resolve "' + id + '" module required by ' +
-                  requirer.id + ' located at ' + requirer.uri, requirer.uri);
-    }
-
-    return { uri: uri, requirement: requirement };
-  }
-
-  // Expose the `resolve` function for this `Require` instance
-  require.resolve = _require.resolve = function resolve(id) {
-    let { uri } = getRequirements(id);
-    return uri;
-  }
-
-  // This is like webpack's require.context.  It returns a new require
-  // function that prepends the prefix to any requests.
-  require.context = prefix => {
-    return id => {
-      return require(prefix + id);
-    };
-  };
-
-  // Make `require.main === module` evaluate to true in main module scope.
-  require.main = loader.main === requirer ? requirer : undefined;
-  return iced(require);
-});
-Loader.Require = Require;
-
-const main = iced(function main(loader, id) {
-  // If no main entry provided, and native loader is used,
-  // read the entry in the manifest
-  if (!id && loader.isNative)
-    id = getManifestMain(loader.manifest);
-  let uri = resolveURI(id, loader.mapping);
-  let module = loader.main = loader.modules[uri] = Module(id, uri);
-  return loader.load(loader, module).exports;
-});
-Loader.main = main;
-
-// Makes module object that is made available to CommonJS modules when they
-// are evaluated, along with `exports` and `require`.
-const Module = iced(function Module(id, uri) {
-  return Object.create(null, {
-    id: { enumerable: true, value: id },
-    exports: { enumerable: true, writable: true, value: Object.create(null),
-               configurable: true },
-    uri: { value: uri }
-  });
-});
-Loader.Module = Module;
-
-// Takes `loader`, and unload `reason` string and notifies all observers that
-// they should cleanup after them-self.
-const unload = iced(function unload(loader, reason) {
-  // subject is a unique object created per loader instance.
-  // This allows any code to cleanup on loader unload regardless of how
-  // it was loaded. To handle unload for specific loader subject may be
-  // asserted against loader.destructor or require('@loader/unload')
-  // Note: We don not destroy loader's module cache or sandboxes map as
-  // some modules may do cleanup in subsequent turns of event loop. Destroying
-  // cache may cause module identity problems in such cases.
-  let subject = { wrappedJSObject: loader.destructor };
-  notifyObservers(subject, 'sdk:loader:destroy', reason);
-});
-Loader.unload = unload;
-
-// Function makes new loader that can be used to load CommonJS modules
-// described by a given `options.manifest`. Loader takes following options:
-// - `globals`: Optional map of globals, that all module scopes will inherit
-//   from. Map is also exposed under `globals` property of the returned loader
-//   so it can be extended further later. Defaults to `{}`.
-// - `modules` Optional map of built-in module exports mapped by module id.
-//   These modules will incorporated into module cache. Each module will be
-//   frozen.
-// - `resolve` Optional module `id` resolution function. If given it will be
-//   used to resolve module URIs, by calling it with require term, requirer
-//   module object (that has `uri` property) and `baseURI` of the loader.
-//   If `resolve` does not returns `uri` string exception will be thrown by
-//   an associated `require` call.
-function Loader(options) {
-  function normalizeRootURI(uri) {
-    return addTrailingSlash(join(uri));
-  }
-
-  if (options.sharedGlobalBlacklist && !options.sharedGlobalBlocklist) {
-    options.sharedGlobalBlocklist = options.sharedGlobalBlacklist;
-  }
-  let {
-    modules, globals, resolve, paths, rootURI, manifest, isNative,
-    metadata, sharedGlobal, sharedGlobalBlocklist, checkCompatibility, waiveIntereposition
-  } = override({
-    paths: {},
-    modules: {},
-    globals: {
-      get console() {
-        // Import Console.jsm from here to prevent loading it until someone uses it
-        let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm");
-        let console = new ConsoleAPI({
-          consoleID: options.id ? "addon/" + options.id : ""
-        });
-        Object.defineProperty(this, "console", { value: console });
-        return this.console;
-      }
-    },
-    checkCompatibility: false,
-    resolve: options.isNative ?
-      // Make the returned resolve function have the same signature
-      (id, requirer) => Loader.nodeResolve(id, requirer, { rootURI: normalizeRootURI(rootURI) }) :
-      Loader.resolve,
-    sharedGlobalBlocklist: ["sdk/indexed-db"],
-    waiveIntereposition: false
-  }, options);
-
-  // Create overrides defaults, none at the moment
-  if (typeof manifest != "object" || !manifest) {
-    manifest = {};
-  }
-  if (typeof manifest.jetpack != "object" || !manifest.jetpack) {
-    manifest.jetpack = {
-      overrides: {}
-    };
-  }
-  if (typeof manifest.jetpack.overrides != "object" || !manifest.jetpack.overrides) {
-    manifest.jetpack.overrides = {};
-  }
-
-  // We create an identity object that will be dispatched on an unload
-  // event as subject. This way unload listeners will be able to assert
-  // which loader is unloaded. Please note that we intentionally don't
-  // use `loader` as subject to prevent a loader access leakage through
-  // observer notifications.
-  let destructor = freeze(Object.create(null));
-
-  let mapping = compileMapping(paths);
-
-  // Define pseudo modules.
-  modules = override({
-    '@loader/unload': destructor,
-    '@loader/options': options,
-    'chrome': { Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
-                CC: bind(CC, Components), components: Components,
-                // `ChromeWorker` has to be inject in loader global scope.
-                // It is done by bootstrap.js:loadSandbox for the SDK.
-                ChromeWorker: ChromeWorker
-    }
-  }, modules);
-
-  const builtinModuleExports = modules;
-  modules = {};
-  for (let id of Object.keys(builtinModuleExports)) {
-    // We resolve `uri` from `id` since modules are cached by `uri`.
-    let uri = resolveURI(id, mapping);
-    // In native loader, the mapping will not contain values for
-    // pseudomodules -- store them as their ID rather than the URI
-    if (isNative && !uri)
-      uri = id;
-    let module = Module(id, uri);
-
-    // Lazily expose built-in modules in order to
-    // allow them to be loaded lazily.
-    Object.defineProperty(module, "exports", {
-      enumerable: true,
-      get: function() {
-        return builtinModuleExports[id];
-      }
-    });
-
-    modules[uri] = freeze(module);
-  }
-
-  // Create the unique sandbox we will be using for all modules,
-  // so that we prevent creating a new comportment per module.
-  // The side effect is that all modules will share the same
-  // global objects.
-  let sharedGlobalSandbox = Sandbox({
-    name: options.sandboxName || "Addon-SDK",
-    wantXrays: false,
-    wantGlobalProperties: [],
-    invisibleToDebugger: options.invisibleToDebugger || false,
-    metadata: {
-      addonID: options.noSandboxAddonId ? undefined : options.id,
-      URI: options.sandboxName || "Addon-SDK"
-    },
-    prototype: options.sandboxPrototype || globals,
-  });
-
-  if (options.sandboxPrototype) {
-    // If we were given a sandboxPrototype, we have to define the globals on
-    // the sandbox directly. Note that this will not work for callers who
-    // depend on being able to add globals after the loader was created.
-    for (let name of getOwnIdentifiers(globals))
-      Object.defineProperty(sharedGlobalSandbox, name,
-                            getOwnPropertyDescriptor(globals, name));
-  }
-
-  // Loader object is just a representation of a environment
-  // state. We freeze it and mark make it's properties non-enumerable
-  // as they are pure implementation detail that no one should rely upon.
-  let returnObj = {
-    destructor: { enumerable: false, value: destructor },
-    globals: { enumerable: false, value: globals },
-    mapping: { enumerable: false, value: mapping },
-    mappingCache: { enumerable: false, value: new Map() },
-    // Map of module objects indexed by module URIs.
-    modules: { enumerable: false, value: modules },
-    metadata: { enumerable: false, value: metadata },
-    useSharedGlobalSandbox: { enumerable: false, value: !!sharedGlobal },
-    sharedGlobalSandbox: { enumerable: false, value: sharedGlobalSandbox },
-    sharedGlobalBlocklist: { enumerable: false, value: sharedGlobalBlocklist },
-    sharedGlobalBlacklist: { enumerable: false, value: sharedGlobalBlocklist },
-    // Map of module sandboxes indexed by module URIs.
-    sandboxes: { enumerable: false, value: {} },
-    resolve: { enumerable: false, value: resolve },
-    // ID of the addon, if provided.
-    id: { enumerable: false, value: options.id },
-    // Whether the modules loaded should be ignored by the debugger
-    invisibleToDebugger: { enumerable: false,
-                           value: options.invisibleToDebugger || false },
-    load: { enumerable: false, value: options.load || load },
-    checkCompatibility: { enumerable: false, value: checkCompatibility },
-    requireHook: { enumerable: false, value: options.requireHook },
-    loadModuleHook: { enumerable: false, value: options.loadModuleHook },
-    // Main (entry point) module, it can be set only once, since loader
-    // instance can have only one main module.
-    main: new function() {
-      let main;
-      return {
-        enumerable: false,
-        get: function() { return main; },
-        // Only set main if it has not being set yet!
-        set: function(module) { main = main || module; }
-      }
-    }
-  };
-
-  if (isNative) {
-    returnObj.isNative = { enumerable: false, value: true };
-    returnObj.manifest = { enumerable: false, value: manifest };
-    returnObj.rootURI = { enumerable: false, value: normalizeRootURI(rootURI) };
-  }
-
-  return freeze(Object.create(null, returnObj));
-};
-Loader.Loader = Loader;
-
-var isSystemURI = uri => /^resource:\/\/(gre|devtools|testing-common)\//.test(uri);
-
-var isJSONURI = uri => uri.endsWith('.json');
-var isJSMURI = uri => uri.endsWith('.jsm');
-var isJSURI = uri => uri.endsWith('.js');
-var isAbsoluteURI = uri => /^(resource|chrome|file|jar):/.test(uri);
-var isRelative = id => id.startsWith(".");
-
-// Default `main` entry to './index.js' and ensure is relative,
-// since node allows 'lib/index.js' without relative `./`
-function getManifestMain(manifest) {
-  let main = manifest.main || './index.js';
-  return isRelative(main) ? main : './' + main;
-}
-
-module.exports = iced(Loader);
-});
deleted file mode 100644
--- a/addon-sdk/source/lib/toolkit/require.js
+++ /dev/null
@@ -1,91 +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 make = (exports, rootURI, components) => {
-  const { Loader: { Loader, Require, Module, main } } =
-        components.utils.import(rootURI + "toolkit/loader.js", {});
-
-  const loader = Loader({
-    id: "toolkit/require",
-    rootURI: rootURI,
-    isNative: true,
-    paths: {
-     "": rootURI,
-     "devtools/": "resource://devtools/"
-    }
-  });
-
-  // Implement require.unload(uri) that can be used to unload
-  // already loaded module which is convinient during development phase.
-  const unload = uri => {
-    delete loader.sandboxes[uri];
-    delete loader.modules[uri];
-  };
-
-  const builtins = new Set(Object.keys(loader.modules));
-
-  // Below we define `require` & `require.resolve` that resolve passed
-  // module id relative to the caller URI. This is not perfect but good
-  // enough for common case & there is always an option to pass absolute
-  // id when that
-  // but presumably well enough to cover
-
-  const require = (id, options={}) => {
-    const { reload, all } = options;
-    const requirerURI = components.stack.caller.filename;
-    const requirer = Module(requirerURI, requirerURI);
-    const require = Require(loader, requirer);
-    if (reload) {
-      // To load JS code into modules, loader uses `mozIJSSubScriptLoader`
-      // which uses startup cache to avoid reading source from the same URI
-      // more than once. Unless we invalidate statup cache changes to a module
-      // won't be reflected even after reload. Therefor we must dispatch an
-      // nsIObserverService notification that causes cache invalidation.
-      // Note: This is not ideal since it destroys whole cache, but since there
-      // is no way to invalidate individual entries, we assume performance hit
-      // during development is acceptable.
-      components.classes["@mozilla.org/observer-service;1"].
-        getService(components.interfaces.nsIObserverService).
-        notifyObservers({}, "startupcache-invalidate");
-
-      if (all) {
-        for (let uri of Object.keys(loader.sandboxes)) {
-          unload(uri);
-        }
-      }
-      else {
-        unload(require.resolve(id));
-      }
-    }
-    return require(id);
-  };
-
-  require.resolve = id => {
-    const requirerURI = components.stack.caller.filename;
-    const requirer = Module(requirerURI, requirerURI);
-    return Require(loader, requirer).resolve(id);
-  };
-
-  exports.require = require;
-}
-
-// If loaded in the context of commonjs module, reload as JSM into an
-// exports object.
-if (typeof(require) === "function" && typeof(module) === "object") {
-  require("chrome").Cu.import(module.uri, module.exports);
-}
-// If loaded in the context of JSM make a loader & require and define
-// new symbols as exported ones.
-else if (typeof(__URI__) === "string" && this["Components"]) {
-  const builtin = Object.keys(this);
-  const uri = __URI__.replace("toolkit/require.js", "");
-  make(this, uri, this["Components"]);
-
-  this.EXPORTED_SYMBOLS = Object.
-                            keys(this).
-                            filter($ => builtin.indexOf($) < 0);
-}
-else {
-  throw Error("Loading require.js in this environment isn't supported")
-}
deleted file mode 100644
--- a/addon-sdk/source/mapping.json
+++ /dev/null
@@ -1,71 +0,0 @@
-{
-  "api-utils": "sdk/deprecated/api-utils",
-  "base64": "sdk/base64",
-  "content": "sdk/content/content",
-  "deprecate": "sdk/util/deprecate",
-  "event/core": "sdk/event/core",
-  "events": "sdk/deprecated/events",
-  "functional": "sdk/core/functional",
-  "l10n/core": "sdk/l10n/json/core",
-  "l10n/html": "sdk/l10n/html",
-  "l10n/loader": "sdk/l10n/loader",
-  "l10n/locale": "sdk/l10n/locale",
-  "l10n/prefs": "sdk/l10n/prefs",
-  "list": "sdk/util/list",
-  "loader": "sdk/loader/loader",
-  "namespace": "sdk/core/namespace",
-  "preferences-service": "sdk/preferences/service",
-  "promise": "sdk/core/promise",
-  "system": "sdk/system",
-  "system/events": "sdk/system/events-shimmed",
-  "tabs/tab": "sdk/tabs/tab",
-  "tabs/utils": "sdk/tabs/utils",
-  "timer": "sdk/timers",
-  "traits": "sdk/deprecated/traits",
-  "unload": "sdk/system/unload",
-  "window-utils": "sdk/deprecated/window-utils",
-  "window/utils": "sdk/window/utils",
-  "windows/dom": "sdk/windows/dom",
-  "windows/loader": "sdk/windows/loader",
-  "xul-app": "sdk/system/xul-app",
-  "url": "sdk/url",
-  "traceback": "sdk/console/traceback",
-  "xhr": "sdk/net/xhr",
-  "match-pattern": "sdk/util/match-pattern",
-  "file": "sdk/io/file",
-  "runtime": "sdk/system/runtime",
-  "xpcom": "sdk/platform/xpcom",
-  "querystring": "sdk/querystring",
-  "text-streams": "sdk/io/text-streams",
-  "app-strings": "sdk/deprecated/app-strings",
-  "environment": "sdk/system/environment",
-  "keyboard/utils": "sdk/keyboard/utils",
-  "dom/events": "sdk/dom/events-shimmed",
-  "utils/data": "sdk/io/data",
-  "test/assert": "sdk/test/assert",
-  "hidden-frame": "sdk/frame/hidden-frame",
-  "collection": "sdk/util/collection",
-  "array": "sdk/util/array",
-  "clipboard": "sdk/clipboard",
-  "context-menu": "sdk/context-menu",
-  "hotkeys": "sdk/hotkeys",
-  "indexed-db": "sdk/indexed-db",
-  "l10n": "sdk/l10n",
-  "notifications": "sdk/notifications",
-  "page-mod": "sdk/page-mod",
-  "page-worker": "sdk/page-worker",
-  "panel": "sdk/panel",
-  "passwords": "sdk/passwords",
-  "private-browsing": "sdk/private-browsing",
-  "request": "sdk/request",
-  "selection": "sdk/selection",
-  "self": "sdk/self",
-  "simple-prefs": "sdk/simple-prefs",
-  "simple-storage": "sdk/simple-storage",
-  "tabs": "sdk/tabs",
-  "timers": "sdk/timers",
-  "windows": "sdk/windows",
-  "harness": "sdk/test/harness",
-  "run-tests": "sdk/test/runner",
-  "test": "sdk/test"
-}
deleted file mode 100644
--- a/addon-sdk/source/modules/system/Startup.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var EXPORTED_SYMBOLS = ["Startup"];
-
-var { utils: Cu, interfaces: Ci, classes: Cc } = Components;
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-const { defer } = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
-
-const { XulApp } = Cu.import("resource://gre/modules/commonjs/sdk/system/xul-app.jsm", {});
-
-const appStartupSrv = Cc["@mozilla.org/toolkit/app-startup;1"]
-                       .getService(Ci.nsIAppStartup);
-
-const NAME2TOPIC = {
-  'Firefox': 'sessionstore-windows-restored',
-  'Fennec': 'sessionstore-windows-restored',
-  'SeaMonkey': 'sessionstore-windows-restored',
-  'Thunderbird': 'mail-startup-done',
-  'Instantbird': 'xul-window-visible'
-};
-
-var Startup = {
-  initialized: !appStartupSrv.startingUp
-};
-var exports = Startup;
-
-var gOnceInitializedDeferred = defer();
-exports.onceInitialized = gOnceInitializedDeferred.promise;
-
-// Set 'final-ui-startup' as default topic for unknown applications
-var appStartup = 'final-ui-startup';
-
-if (Startup.initialized) {
-  gOnceInitializedDeferred.resolve()
-}
-else {
-  // Gets the topic that fit best as application startup event, in according with
-  // the current application (e.g. Firefox, Fennec, Thunderbird...)
-  for (let name of Object.keys(NAME2TOPIC)) {
-    if (XulApp.is(name)) {
-      appStartup = NAME2TOPIC[name];
-      break;
-    }
-  }
-
-  let listener = function (subject, topic) {
-    Services.obs.removeObserver(this, topic);
-    Startup.initialized = true;
-    Services.tm.dispatchToMainThread(() => gOnceInitializedDeferred.resolve());
-  }
-
-  Services.obs.addObserver(listener, appStartup);
-}
deleted file mode 100644
--- a/addon-sdk/source/modules/system/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXTRA_JS_MODULES.sdk.system += [
-    'Startup.js',
-]
deleted file mode 100644
--- a/addon-sdk/source/package.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "name": "addon-sdk",
-  "description": "Add-on development made easy.",
-  "keywords": [
-    "javascript", "engine", "addon", "extension",
-    "xulrunner", "firefox", "browser"
-  ],
-  "license": "MPL-2.0",
-  "unpack": true,
-  "scripts": {
-    "test": "gulp test"
-  },
-  "homepage": "https://github.com/mozilla/addon-sdk",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/mozilla/addon-sdk.git"
-  },
-  "version": "0.1.18",
-  "main": "./lib/index.js",
-  "loader": "lib/sdk/loader/cuddlefish.js",
-  "devDependencies": {
-    "async": "0.9.0",
-    "chai": "2.1.1",
-    "fs-extra": "0.18.2",
-    "fx-runner": "0.0.7",
-    "glob": "4.4.2",
-    "gulp": "3.8.11",
-    "ini-parser": "0.0.2",
-    "jpm": "0.0.29",
-    "lodash": "3.3.1",
-    "mocha": "2.1.0",
-    "patch-editor": "0.0.1",
-    "promise": "6.1.0",
-    "rimraf": "2.3.1",
-    "teacher": "0.0.1",
-    "unzip": "0.1.11",
-    "xmldom": "0.1.19"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/__init__.py
+++ /dev/null
@@ -1,959 +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/.
-
-import sys
-import os
-import optparse
-import time
-
-from copy import copy
-import simplejson as json
-from cuddlefish import packaging
-from cuddlefish._version import get_versions
-
-MOZRUNNER_BIN_NOT_FOUND = 'Mozrunner could not locate your binary'
-MOZRUNNER_BIN_NOT_FOUND_HELP = """
-I can't find the application binary in any of its default locations
-on your system. Please specify one using the -b/--binary option.
-"""
-
-UPDATE_RDF_FILENAME = "%s.update.rdf"
-XPI_FILENAME = "%s.xpi"
-
-usage = """
-%prog [options] command [command-specific options]
-
-Supported Commands:
-  init       - create a sample addon in an empty directory
-  test       - run tests
-  run        - run program
-  xpi        - generate an xpi
-
-Internal Commands:
-  testcfx    - test the cfx tool
-  testex     - test all example code
-  testpkgs   - test all installed packages
-  testall    - test whole environment
-
-Experimental and internal commands and options are not supported and may be
-changed or removed in the future.
-"""
-
-global_options = [
-    (("-v", "--verbose",), dict(dest="verbose",
-                                help="enable lots of output",
-                                action="store_true",
-                                default=False)),
-    ]
-
-parser_groups = (
-    ("Supported Command-Specific Options", [
-        (("", "--update-url",), dict(dest="update_url",
-                                     help="update URL in install.rdf",
-                                     metavar=None,
-                                     default=None,
-                                     cmds=['xpi'])),
-        (("", "--update-link",), dict(dest="update_link",
-                                      help="generate update.rdf",
-                                      metavar=None,
-                                      default=None,
-                                      cmds=['xpi'])),
-        (("-p", "--profiledir",), dict(dest="profiledir",
-                                       help=("profile directory to pass to "
-                                             "app"),
-                                       metavar=None,
-                                       default=None,
-                                       cmds=['test', 'run', 'testex',
-                                             'testpkgs', 'testall'])),
-        (("-b", "--binary",), dict(dest="binary",
-                                   help="path to app binary",
-                                   metavar=None,
-                                   default=None,
-                                   cmds=['test', 'run', 'testex', 'testpkgs',
-                                         'testall'])),
-        (("", "--binary-args",), dict(dest="cmdargs",
-                                 help=("additional arguments passed to the "
-                                       "binary"),
-                                 metavar=None,
-                                 default=None,
-                                 cmds=['run', 'test'])),
-        (("", "--dependencies",), dict(dest="dep_tests",
-                                       help="include tests for all deps",
-                                       action="store_true",
-                                       default=False,
-                                       cmds=['test', 'testex', 'testpkgs',
-                                             'testall'])),
-        (("", "--times",), dict(dest="iterations",
-                                type="int",
-                                help="number of times to run tests",
-                                default=1,
-                                cmds=['test', 'testex', 'testpkgs',
-                                      'testall'])),
-        (("-f", "--filter",), dict(dest="filter",
-                                   help=("only run tests whose filenames "
-                                         "match FILENAME and optionally "
-                                         "match TESTNAME, both regexps"),
-                                   metavar="FILENAME[:TESTNAME]",
-                                   default='',
-                                   cmds=['test', 'testex', 'testaddons', 'testpkgs',
-                                         'testall'])),
-        (("-g", "--use-config",), dict(dest="config",
-                                       help="use named config from local.json",
-                                       metavar=None,
-                                       default="default",
-                                       cmds=['test', 'run', 'xpi', 'testex',
-                                             'testpkgs', 'testall'])),
-        (("", "--templatedir",), dict(dest="templatedir",
-                                      help="XULRunner app/ext. template",
-                                      metavar=None,
-                                      default=None,
-                                      cmds=['run', 'xpi'])),
-        (("", "--package-path",), dict(dest="packagepath", action="append",
-                                       help="extra directories for package search",
-                                       metavar=None,
-                                       default=[],
-                                       cmds=['run', 'xpi', 'test'])),
-        (("", "--extra-packages",), dict(dest="extra_packages",
-                                         help=("extra packages to include, "
-                                               "comma-separated. Default is "
-                                               "'addon-sdk'."),
-                                         metavar=None,
-                                         default="addon-sdk",
-                                         cmds=['run', 'xpi', 'test', 'testex',
-                                               'testpkgs', 'testall',
-                                               'testcfx'])),
-        (("", "--pkgdir",), dict(dest="pkgdir",
-                                 help=("package dir containing "
-                                       "package.json; default is "
-                                       "current directory"),
-                                 metavar=None,
-                                 default=None,
-                                 cmds=['run', 'xpi', 'test'])),
-        (("", "--static-args",), dict(dest="static_args",
-                                      help="extra harness options as JSON",
-                                      type="json",
-                                      metavar=None,
-                                      default="{}",
-                                      cmds=['run', 'xpi'])),
-        (("", "--parseable",), dict(dest="parseable",
-                                    help="display test output in a parseable format",
-                                    action="store_true",
-                                    default=False,
-                                    cmds=['run', 'test', 'testex', 'testpkgs',
-                                          'testaddons', 'testall'])),
-        ]
-     ),
-
-    ("Experimental Command-Specific Options", [
-        (("-a", "--app",), dict(dest="app",
-                                help=("app to run: firefox (default), fennec, "
-                                      "fennec-on-device, xulrunner or "
-                                      "thunderbird"),
-                                metavar=None,
-                                type="choice",
-                                choices=["firefox",
-                                         "fennec-on-device", "thunderbird",
-                                         "xulrunner"],
-                                default="firefox",
-                                cmds=['test', 'run', 'testex', 'testpkgs',
-                                      'testall'])),
-        (("-o", "--overload-modules",), dict(dest="overload_modules",
-                                     help=("Overload JS modules integrated into"
-                                           " Firefox with the one from your SDK"
-                                           " repository"),
-                                     action="store_true",
-                                     default=False,
-                                     cmds=['run', 'test', 'testex', 'testpkgs',
-                                           'testall'])),
-        (("", "--strip-sdk",), dict(dest="bundle_sdk",
-                                    help=("Do not ship SDK modules in the xpi"),
-                                    action="store_false",
-                                    default=False,
-                                    cmds=['run', 'test', 'testex', 'testpkgs',
-                                          'testall', 'xpi'])),
-        (("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk",
-                                    help=("When --strip-sdk isn't passed, "
-                                          "force using sdk modules shipped in "
-                                          "the xpi instead of firefox ones"),
-                                    action="store_true",
-                                    default=False,
-                                    cmds=['run', 'test', 'testex', 'testpkgs',
-                                          'testall', 'xpi'])),
-        (("", "--no-run",), dict(dest="no_run",
-                                     help=("Instead of launching the "
-                                           "application, just show the command "
-                                           "for doing so.  Use this to launch "
-                                           "the application in a debugger like "
-                                           "gdb."),
-                                     action="store_true",
-                                     default=False,
-                                     cmds=['run', 'test'])),
-        (("", "--no-quit",), dict(dest="no_quit",
-                                     help=("Prevent from killing Firefox when"
-                                           "running tests"),
-                                     action="store_true",
-                                     default=False,
-                                     cmds=['run', 'test'])),
-        (("", "--no-strip-xpi",), dict(dest="no_strip_xpi",
-                                    help="retain unused modules in XPI",
-                                    action="store_true",
-                                    default=False,
-                                    cmds=['xpi'])),
-        (("", "--force-mobile",), dict(dest="enable_mobile",
-                                    help="Force compatibility with Firefox Mobile",
-                                    action="store_true",
-                                    default=False,
-                                    cmds=['run', 'test', 'xpi', 'testall'])),
-        (("", "--mobile-app",), dict(dest="mobile_app_name",
-                                    help=("Name of your Android application to "
-                                          "use. Possible values: 'firefox', "
-                                          "'firefox_beta', 'fennec_aurora', "
-                                          "'fennec' (for nightly)."),
-                                    metavar=None,
-                                    default=None,
-                                    cmds=['run', 'test', 'testall'])),
-        (("", "--harness-option",), dict(dest="extra_harness_option_args",
-                                         help=("Extra properties added to "
-                                               "harness-options.json"),
-                                         action="append",
-                                         metavar="KEY=VALUE",
-                                         default=[],
-                                         cmds=['xpi'])),
-        (("", "--stop-on-error",), dict(dest="stopOnError",
-                                  help="Stop running tests after the first failure",
-                                  action="store_true",
-                                  metavar=None,
-                                  default=False,
-                                  cmds=['test', 'testex', 'testpkgs'])),
-        (("", "--check-memory",), dict(dest="check_memory",
-                                       help="attempts to detect leaked compartments after a test run",
-                                       action="store_true",
-                                       default=False,
-                                       cmds=['test', 'testpkgs', 'testaddons',
-                                             'testall'])),
-        (("", "--output-file",), dict(dest="output_file",
-                                      help="Where to put the finished .xpi",
-                                      default=None,
-                                      cmds=['xpi'])),
-        (("", "--abort-on-missing-module",), dict(dest="abort_on_missing",
-                                      help="Abort if required module is missing",
-                                      action="store_true",
-                                      default=False,
-                                      cmds=['test', 'run', 'xpi', 'testpkgs'])),
-        (("", "--no-connections",), dict(dest="no_connections",
-                                      help="disable/enable remote connections (on for cfx run only by default)",
-                                      type="choice",
-                                      choices=["on", "off", "default"],
-                                      default="default",
-                                      cmds=['test', 'run', 'testpkgs',
-                                            'testall', 'testaddons', 'testex'])),
-        ]
-     ),
-
-    ("Internal Command-Specific Options", [
-        (("", "--addons",), dict(dest="addons",
-                                 help=("paths of addons to install, "
-                                       "comma-separated"),
-                                 metavar=None,
-                                 default=None,
-                                 cmds=['test', 'run', 'testex', 'testpkgs',
-                                       'testall'])),
-        (("", "--test-runner-pkg",), dict(dest="test_runner_pkg",
-                                          help=("name of package "
-                                                "containing test runner "
-                                                "program (default is "
-                                                "test-harness)"),
-                                          default="addon-sdk",
-                                          cmds=['test', 'testex', 'testpkgs',
-                                                'testall'])),
-        # --keydir was removed in 1.0b5, but we keep it around in the options
-        # parser to make life easier for frontends like FlightDeck which
-        # might still pass it. It can go away once the frontends are updated.
-        (("", "--keydir",), dict(dest="keydir",
-                                 help=("obsolete, ignored"),
-                                 metavar=None,
-                                 default=None,
-                                 cmds=['test', 'run', 'xpi', 'testex',
-                                       'testpkgs', 'testall'])),
-        (("", "--e10s",), dict(dest="enable_e10s",
-                               help="enable remote windows",
-                               action="store_true",
-                               default=False,
-                               cmds=['test', 'run', 'testex', 'testpkgs',
-                                     'testaddons', 'testcfx', 'testall'])),
-        (("", "--logfile",), dict(dest="logfile",
-                                  help="log console output to file",
-                                  metavar=None,
-                                  default=None,
-                                  cmds=['run', 'test', 'testex', 'testpkgs'])),
-        # TODO: This should default to true once our memory debugging
-        # issues are resolved; see bug 592774.
-        (("", "--profile-memory",), dict(dest="profileMemory",
-                                         help=("profile memory usage "
-                                               "(default is false)"),
-                                         type="int",
-                                         action="store",
-                                         default=0,
-                                         cmds=['test', 'testex', 'testpkgs',
-                                               'testall'])),
-        ]
-     ),
-    )
-
-def find_parent_package(cur_dir):
-    tail = True
-    while tail:
-        if os.path.exists(os.path.join(cur_dir, 'package.json')):
-            return cur_dir
-        cur_dir, tail = os.path.split(cur_dir)
-    return None
-
-def check_json(option, opt, value):
-    # We return the parsed JSON here; see bug 610816 for background on why.
-    try:
-        return json.loads(value)
-    except ValueError:
-        raise optparse.OptionValueError("Option %s must be JSON." % opt)
-
-class CfxOption(optparse.Option):
-    TYPES = optparse.Option.TYPES + ('json',)
-    TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER)
-    TYPE_CHECKER['json'] = check_json
-
-def parse_args(arguments, global_options, usage, version, parser_groups,
-               defaults=None):
-    parser = optparse.OptionParser(usage=usage.strip(), option_class=CfxOption,
-                                   version=version)
-
-    def name_cmp(a, b):
-        # a[0]    = name sequence
-        # a[0][0] = short name (possibly empty string)
-        # a[0][1] = long name
-        names = []
-        for seq in (a, b):
-            names.append(seq[0][0][1:] if seq[0][0] else seq[0][1][2:])
-        return cmp(*names)
-
-    global_options.sort(name_cmp)
-    for names, opts in global_options:
-        parser.add_option(*names, **opts)
-
-    for group_name, options in parser_groups:
-        group = optparse.OptionGroup(parser, group_name)
-        options.sort(name_cmp)
-        for names, opts in options:
-            if 'cmds' in opts:
-                cmds = opts['cmds']
-                del opts['cmds']
-                cmds.sort()
-                if not 'help' in opts:
-                    opts['help'] = ""
-                opts['help'] += " (%s)" % ", ".join(cmds)
-            group.add_option(*names, **opts)
-        parser.add_option_group(group)
-
-    if defaults:
-        parser.set_defaults(**defaults)
-
-    (options, args) = parser.parse_args(args=arguments)
-
-    if not args:
-        parser.print_help()
-        parser.exit()
-
-    return (options, args)
-
-# all tests emit progress messages to stderr, not stdout. (the mozrunner
-# console output goes to stderr and is hard to change, and
-# unittest.TextTestRunner prefers stderr, so we send everything else there
-# too, to keep all the messages in order)
-
-def test_all(env_root, defaults):
-    fail = False
-
-    starttime = time.time()
-
-    if not defaults['filter']:
-        print >>sys.stderr, "Testing cfx..."
-        sys.stderr.flush()
-        result = test_cfx(env_root, defaults['verbose'])
-        if result.failures or result.errors:
-            fail = True
-
-    if not fail or not defaults.get("stopOnError"):
-        print >>sys.stderr, "Testing all examples..."
-        sys.stderr.flush()
-
-        try:
-            test_all_examples(env_root, defaults)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-
-    if not fail or not defaults.get("stopOnError"):
-        print >>sys.stderr, "Testing all unit-test addons..."
-        sys.stderr.flush()
-
-        try:
-            test_all_testaddons(env_root, defaults)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-
-    if not fail or not defaults.get("stopOnError"):
-        print >>sys.stderr, "Testing all packages..."
-        sys.stderr.flush()
-        try:
-            test_all_packages(env_root, defaults)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-
-    print >>sys.stderr, "Total time for all tests: %f seconds" % (time.time() - starttime)
-
-    if fail:
-        print >>sys.stderr, "Some tests were unsuccessful."
-        sys.exit(1)
-    print >>sys.stderr, "All tests were successful. Ship it!"
-    sys.exit(0)
-
-def test_cfx(env_root, verbose):
-    import cuddlefish.tests
-
-    # tests write to stderr. flush everything before and after to avoid
-    # confusion later.
-    sys.stdout.flush(); sys.stderr.flush()
-    olddir = os.getcwd()
-    os.chdir(env_root)
-    retval = cuddlefish.tests.run(verbose)
-    os.chdir(olddir)
-    sys.stdout.flush(); sys.stderr.flush()
-    return retval
-
-def test_all_testaddons(env_root, defaults):
-    addons_dir = os.path.join(env_root, "test", "addons")
-    addons = [dirname for dirname in os.listdir(addons_dir)
-                if os.path.isdir(os.path.join(addons_dir, dirname))]
-    addons.sort()
-    fail = False
-    for dirname in addons:
-        # apply the filter
-        if (not defaults['filter'].split(":")[0] in dirname):
-            continue
-
-        print >>sys.stderr, "Testing %s..." % dirname
-        sys.stderr.flush()
-        try:
-            run(arguments=["testrun",
-                           "--pkgdir",
-                           os.path.join(addons_dir, dirname)],
-                defaults=defaults,
-                env_root=env_root)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-        if fail and defaults.get("stopOnError"):
-            break
-
-    if fail:
-        print >>sys.stderr, "Some test addons tests were unsuccessful."
-        sys.exit(-1)
-
-def test_all_examples(env_root, defaults):
-    examples_dir = os.path.join(env_root, "examples")
-    examples = [dirname for dirname in os.listdir(examples_dir)
-                if os.path.isdir(os.path.join(examples_dir, dirname))]
-    examples.sort()
-    fail = False
-    for dirname in examples:
-        if (not defaults['filter'].split(":")[0] in dirname):
-            continue
-
-        print >>sys.stderr, "Testing %s..." % dirname
-        sys.stderr.flush()
-        try:
-            run(arguments=["test",
-                           "--pkgdir",
-                           os.path.join(examples_dir, dirname)],
-                defaults=defaults,
-                env_root=env_root)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-        if fail and defaults.get("stopOnError"):
-            break
-
-    if fail:
-        print >>sys.stderr, "Some examples tests were unsuccessful."
-        sys.exit(-1)
-
-def test_all_packages(env_root, defaults):
-    packages_dir = os.path.join(env_root, "packages")
-    if os.path.isdir(packages_dir):
-      packages = [dirname for dirname in os.listdir(packages_dir)
-                  if os.path.isdir(os.path.join(packages_dir, dirname))]
-    else:
-      packages = []
-    packages.append(env_root)
-    packages.sort()
-    print >>sys.stderr, "Testing all available packages: %s." % (", ".join(packages))
-    sys.stderr.flush()
-    fail = False
-    for dirname in packages:
-        print >>sys.stderr, "Testing %s..." % dirname
-        sys.stderr.flush()
-        try:
-            run(arguments=["test",
-                           "--pkgdir",
-                           os.path.join(packages_dir, dirname)],
-                defaults=defaults,
-                env_root=env_root)
-        except SystemExit, e:
-            fail = (e.code != 0) or fail
-        if fail and defaults.get('stopOnError'):
-            break
-    if fail:
-        print >>sys.stderr, "Some package tests were unsuccessful."
-        sys.exit(-1)
-
-def get_config_args(name, env_root):
-    local_json = os.path.join(env_root, "local.json")
-    if not (os.path.exists(local_json) and
-            os.path.isfile(local_json)):
-        if name == "default":
-            return []
-        else:
-            print >>sys.stderr, "File does not exist: %s" % local_json
-            sys.exit(1)
-    local_json = packaging.load_json_file(local_json)
-    if 'configs' not in local_json:
-        print >>sys.stderr, "'configs' key not found in local.json."
-        sys.exit(1)
-    if name not in local_json.configs:
-        if name == "default":
-            return []
-        else:
-            print >>sys.stderr, "No config found for '%s'." % name
-            sys.exit(1)
-    config = local_json.configs[name]
-    if type(config) != list:
-        print >>sys.stderr, "Config for '%s' must be a list of strings." % name
-        sys.exit(1)
-    return config
-
-def initializer(env_root, args, out=sys.stdout, err=sys.stderr):
-    from templates import PACKAGE_JSON, TEST_MAIN_JS
-    from preflight import create_jid
-    path = os.getcwd()
-    addon = os.path.basename(path)
-    # if more than two arguments
-    if len(args) > 2:
-        print >>err, 'Too many arguments.'
-        return {"result":1}
-    if len(args) == 2:
-        path = os.path.join(path,args[1])
-        try:
-            os.mkdir(path)
-            print >>out, '*', args[1], 'package directory created'
-        except OSError:
-            print >>out, '*', args[1], 'already exists, testing if directory is empty'
-    # avoid clobbering existing files, but we tolerate things like .git
-    existing = [fn for fn in os.listdir(path) if not fn.startswith(".")]
-    if existing:
-        print >>err, 'This command must be run in an empty directory.'
-        return {"result":1}
-    for d in ['lib','data','test']:
-        os.mkdir(os.path.join(path,d))
-        print >>out, '*', d, 'directory created'
-    jid = create_jid()
-    print >>out, '* generated jID automatically:', jid
-    open(os.path.join(path,'package.json'),'w').write(PACKAGE_JSON % {'name':addon.lower(),
-                                                   'title':addon,
-                                                   'id':jid })
-    print >>out, '* package.json written'
-    open(os.path.join(path,'test','test-main.js'),'w').write(TEST_MAIN_JS)
-    print >>out, '* test/test-main.js written'
-    open(os.path.join(path,'lib','main.js'),'w').write('')
-    print >>out, '* lib/main.js written'
-    if len(args) == 1:
-        print >>out, '\nYour sample add-on is now ready.'
-        print >>out, 'Do "cfx test" to test it and "cfx run" to try it.  Have fun!'
-    else:
-        print >>out, '\nYour sample add-on is now ready in the \'' + args[1] +  '\' directory.'
-        print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it.  Have fun!'
-    return {"result":0, "jid":jid}
-
-def buildJID(target_cfg):
-    if "id" in target_cfg:
-        jid = target_cfg["id"]
-    else:
-        import uuid
-        jid = str(uuid.uuid4())
-    if not ("@" in jid or jid.startswith("{")):
-        jid = jid + "@jetpack"
-    return jid
-
-def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
-        defaults=None, env_root=os.environ.get('CUDDLEFISH_ROOT'),
-        stdout=sys.stdout):
-    versions = get_versions()
-    sdk_version = versions["version"]
-    display_version = "Add-on SDK %s (%s)" % (sdk_version, versions["full"])
-    parser_kwargs = dict(arguments=arguments,
-                         global_options=global_options,
-                         parser_groups=parser_groups,
-                         usage=usage,
-                         version=display_version,
-                         defaults=defaults)
-
-    (options, args) = parse_args(**parser_kwargs)
-
-    config_args = get_config_args(options.config, env_root);
-
-    # reparse configs with arguments from local.json
-    if config_args:
-        parser_kwargs['arguments'] += config_args
-        (options, args) = parse_args(**parser_kwargs)
-
-    command = args[0]
-
-    if command == "init":
-        initializer(env_root, args)
-        return
-    if command == "testpkgs":
-        test_all_packages(env_root, defaults=options.__dict__)
-        return
-    elif command == "testaddons":
-        test_all_testaddons(env_root, defaults=options.__dict__)
-        return
-    elif command == "testex":
-        test_all_examples(env_root, defaults=options.__dict__)
-        return
-    elif command == "testall":
-        test_all(env_root, defaults=options.__dict__)
-        return
-    elif command == "testcfx":
-        if options.filter:
-            print >>sys.stderr, "The filter option is not valid with the testcfx command"
-            return
-        test_cfx(env_root, options.verbose)
-        return
-    elif command not in ["xpi", "test", "run", "testrun"]:
-        print >>sys.stderr, "Unknown command: %s" % command
-        print >>sys.stderr, "Try using '--help' for assistance."
-        sys.exit(1)
-
-    target_cfg_json = None
-    if not target_cfg:
-        if not options.pkgdir:
-            options.pkgdir = find_parent_package(os.getcwd())
-            if not options.pkgdir:
-                print >>sys.stderr, ("cannot find 'package.json' in the"
-                                     " current directory or any parent.")
-                sys.exit(1)
-        else:
-            options.pkgdir = os.path.abspath(options.pkgdir)
-        if not os.path.exists(os.path.join(options.pkgdir, 'package.json')):
-            print >>sys.stderr, ("cannot find 'package.json' in"
-                                 " %s." % options.pkgdir)
-            sys.exit(1)
-
-        target_cfg_json = os.path.join(options.pkgdir, 'package.json')
-        target_cfg = packaging.get_config_in_dir(options.pkgdir)
-
-    # At this point, we're either building an XPI or running Jetpack code in
-    # a Mozilla application (which includes running tests).
-
-    use_main = False
-    inherited_options = ['verbose', 'enable_e10s', 'parseable', 'check_memory',
-                         'no_quit', 'abort_on_missing']
-    enforce_timeouts = False
-
-    if command == "xpi":
-        use_main = True
-    elif command == "test":
-        if 'tests' not in target_cfg:
-            target_cfg['tests'] = []
-        inherited_options.extend(['iterations', 'filter', 'profileMemory',
-                                  'stopOnError'])
-        enforce_timeouts = True
-    elif command == "run":
-        use_main = True
-    elif command == "testrun":
-        use_main = True
-        enforce_timeouts = True
-    else:
-        assert 0, "shouldn't get here"
-
-    if use_main and 'main' not in target_cfg:
-        # If the user supplies a template dir, then the main
-        # program may be contained in the template.
-        if not options.templatedir:
-            print >>sys.stderr, "package.json does not have a 'main' entry."
-            sys.exit(1)
-
-    if not pkg_cfg:
-        pkg_cfg = packaging.build_config(env_root, target_cfg, options.packagepath)
-
-    target = target_cfg.name
-
-    # TODO: Consider keeping a cache of dynamic UUIDs, based
-    # on absolute filesystem pathname, in the root directory
-    # or something.
-    if command in ('xpi', 'run', 'testrun'):
-        from cuddlefish.preflight import preflight_config
-        if target_cfg_json:
-            config_was_ok, modified = preflight_config(target_cfg,
-                                                       target_cfg_json)
-            if not config_was_ok:
-                if modified:
-                    # we need to re-read package.json . The safest approach
-                    # is to re-run the "cfx xpi"/"cfx run" command.
-                    print >>sys.stderr, ("package.json modified: please re-run"
-                                         " 'cfx %s'" % command)
-                else:
-                    print >>sys.stderr, ("package.json needs modification:"
-                                         " please update it and then re-run"
-                                         " 'cfx %s'" % command)
-                sys.exit(1)
-        # if we make it this far, we have a JID
-    else:
-        assert command == "test"
-
-    jid = buildJID(target_cfg)
-
-    targets = [target]
-    if command == "test":
-        targets.append(options.test_runner_pkg)
-
-    extra_packages = []
-    if options.extra_packages:
-        extra_packages = options.extra_packages.split(",")
-    if extra_packages:
-        targets.extend(extra_packages)
-        target_cfg.extra_dependencies = extra_packages
-
-    deps = packaging.get_deps_for_targets(pkg_cfg, targets)
-
-    from cuddlefish.manifest import build_manifest, ModuleNotFoundError, \
-                                    BadChromeMarkerError
-    # Figure out what loader files should be scanned. This is normally
-    # computed inside packaging.generate_build_for_target(), by the first
-    # dependent package that defines a "loader" property in its package.json.
-    # This property is interpreted as a filename relative to the top of that
-    # file, and stored as a path in build.loader . generate_build_for_target()
-    # cannot be called yet (it needs the list of used_deps that
-    # build_manifest() computes, but build_manifest() needs the list of
-    # loader files that it computes). We could duplicate or factor out this
-    # build.loader logic, but that would be messy, so instead we hard-code
-    # the choice of loader for manifest-generation purposes. In practice,
-    # this means that alternative loaders probably won't work with
-    # --strip-xpi.
-    assert packaging.DEFAULT_LOADER == "addon-sdk"
-    assert pkg_cfg.packages["addon-sdk"].loader == "lib/sdk/loader/cuddlefish.js"
-    cuddlefish_js_path = os.path.join(pkg_cfg.packages["addon-sdk"].root_dir,
-                                      "lib", "sdk", "loader", "cuddlefish.js")
-    loader_modules = [("addon-sdk", "lib", "sdk/loader/cuddlefish", cuddlefish_js_path)]
-    scan_tests = command == "test"
-
-    try:
-        manifest = build_manifest(target_cfg, pkg_cfg, deps, scan_tests,
-                                  None, loader_modules,
-                                  abort_on_missing=options.abort_on_missing)
-    except ModuleNotFoundError, e:
-        print str(e)
-        sys.exit(1)
-    except BadChromeMarkerError, e:
-        # An error had already been displayed on stderr in manifest code
-        sys.exit(1)
-    used_deps = manifest.get_used_packages()
-    if command == "test":
-        # The test runner doesn't appear to link against any actual packages,
-        # because it loads everything at runtime (invisible to the linker).
-        # If we believe that, we won't set up URI mappings for anything, and
-        # tests won't be able to run.
-        used_deps = deps
-    for xp in extra_packages:
-        if xp not in used_deps:
-            used_deps.append(xp)
-
-    build = packaging.generate_build_for_target(
-        pkg_cfg, target, used_deps,
-        include_dep_tests=options.dep_tests,
-        is_running_tests=(command == "test")
-        )
-
-    harness_options = {
-        'jetpackID': jid,
-        'staticArgs': options.static_args,
-        'name': target,
-        }
-
-    harness_options.update(build)
-
-    # When cfx is run from sdk root directory, we will strip sdk modules and
-    # override them with local modules.
-    # So that integration tools will continue to work and use local modules
-    if os.getcwd() == env_root:
-        options.bundle_sdk = True
-        options.force_use_bundled_sdk = False
-        options.overload_modules = True
-
-    if options.pkgdir == env_root:
-        options.bundle_sdk = True
-        options.overload_modules = True
-
-    extra_environment = {}
-    if command == "test":
-        # This should be contained in the test runner package.
-        harness_options['main'] = 'sdk/test/runner'
-        harness_options['mainPath'] = 'sdk/test/runner'
-    else:
-        harness_options['main'] = target_cfg.get('main')
-        harness_options['mainPath'] = manifest.top_path
-    extra_environment["CFX_COMMAND"] = command
-
-    for option in inherited_options:
-        harness_options[option] = getattr(options, option)
-
-    harness_options['metadata'] = packaging.get_metadata(pkg_cfg, used_deps)
-
-    harness_options['sdkVersion'] = sdk_version
-
-    packaging.call_plugins(pkg_cfg, used_deps)
-
-    retval = 0
-
-    if options.templatedir:
-        app_extension_dir = os.path.abspath(options.templatedir)
-    elif os.path.exists(os.path.join(options.pkgdir, "app-extension")):
-      app_extension_dir = os.path.join(options.pkgdir, "app-extension")
-    else:
-        mydir = os.path.dirname(os.path.abspath(__file__))
-        app_extension_dir = os.path.join(mydir, "../../app-extension")
-
-    # Do not add entries for SDK modules
-    harness_options['manifest'] = manifest.get_harness_options_manifest(False)
-
-    # Gives an hint to tell if sdk modules are bundled or not
-    harness_options['is-sdk-bundled'] = options.bundle_sdk or options.no_strip_xpi
-
-    if options.force_use_bundled_sdk:
-        if not harness_options['is-sdk-bundled']:
-            print >>sys.stderr, ("--force-use-bundled-sdk "
-                                 "can't be used if sdk isn't bundled.")
-            sys.exit(1)
-        if options.overload_modules:
-            print >>sys.stderr, ("--force-use-bundled-sdk and --overload-modules "
-                                 "can't be used at the same time.")
-            sys.exit(1)
-        # Pass a flag in order to force using sdk modules shipped in the xpi
-        harness_options['force-use-bundled-sdk'] = True
-
-    from cuddlefish.rdf import gen_manifest, RDFUpdate
-
-    manifest_rdf = gen_manifest(template_root_dir=app_extension_dir,
-                                target_cfg=target_cfg,
-                                jid=jid,
-                                update_url=options.update_url,
-                                bootstrap=True,
-                                enable_mobile=options.enable_mobile)
-
-    if command == "xpi" and options.update_link:
-        if not options.update_link.startswith("https"):
-            raise optparse.OptionValueError("--update-link must start with 'https': %s" % options.update_link)
-        rdf_name = UPDATE_RDF_FILENAME % target_cfg.name
-        print >>stdout, "Exporting update description to %s." % rdf_name
-        update = RDFUpdate()
-        update.add(manifest_rdf, options.update_link)
-        open(rdf_name, "w").write(str(update))
-
-    # ask the manifest what files were used, so we can construct an XPI
-    # without the rest. This will include the loader (and everything it
-    # uses) because of the "loader_modules" starting points we passed to
-    # build_manifest earlier
-    used_files = None
-    if command == "xpi":
-        used_files = set(manifest.get_used_files(options.bundle_sdk))
-
-    if options.no_strip_xpi:
-        used_files = None # disables the filter, includes all files
-
-    if command == 'xpi':
-        from cuddlefish.xpi import build_xpi
-        # Generate extra options
-        extra_harness_options = {}
-        for kv in options.extra_harness_option_args:
-            key,value = kv.split("=", 1)
-            extra_harness_options[key] = value
-        # Generate xpi filepath
-        if options.output_file:
-          xpi_path = options.output_file
-        else:
-          xpi_path = XPI_FILENAME % target_cfg.name
-
-        print >>stdout, "Exporting extension to %s." % xpi_path
-        build_xpi(template_root_dir=app_extension_dir,
-                  manifest=manifest_rdf,
-                  xpi_path=xpi_path,
-                  harness_options=harness_options,
-                  limit_to=used_files,
-                  extra_harness_options=extra_harness_options,
-                  bundle_sdk=True,
-                  pkgdir=options.pkgdir)
-    else:
-        from cuddlefish.runner import run_app
-
-        if options.no_connections == "default":
-            if command == "run":
-              no_connections = False
-            else:
-              no_connections = True
-        elif options.no_connections == "on":
-            no_connections = True
-        else:
-            no_connections = False
-
-        if options.profiledir:
-            options.profiledir = os.path.expanduser(options.profiledir)
-            options.profiledir = os.path.abspath(options.profiledir)
-
-        if options.addons is not None:
-            options.addons = options.addons.split(",")
-
-        enable_e10s = options.enable_e10s or target_cfg.get('e10s', False)
-
-        try:
-            retval = run_app(harness_root_dir=app_extension_dir,
-                             manifest_rdf=manifest_rdf,
-                             harness_options=harness_options,
-                             app_type=options.app,
-                             binary=options.binary,
-                             profiledir=options.profiledir,
-                             verbose=options.verbose,
-                             parseable=options.parseable,
-                             enforce_timeouts=enforce_timeouts,
-                             logfile=options.logfile,
-                             addons=options.addons,
-                             args=options.cmdargs,
-                             extra_environment=extra_environment,
-                             norun=options.no_run,
-                             noquit=options.no_quit,
-                             used_files=used_files,
-                             enable_mobile=options.enable_mobile,
-                             mobile_app_name=options.mobile_app_name,
-                             env_root=env_root,
-                             is_running_tests=(command == "test"),
-                             overload_modules=options.overload_modules,
-                             bundle_sdk=options.bundle_sdk,
-                             pkgdir=options.pkgdir,
-                             enable_e10s=enable_e10s,
-                             no_connections=no_connections)
-        except ValueError, e:
-            print ""
-            print "A given cfx option has an inappropriate value:"
-            print >>sys.stderr, "  " + "  \n  ".join(str(e).split("\n"))
-            retval = -1
-        except Exception, e:
-            if str(e).startswith(MOZRUNNER_BIN_NOT_FOUND):
-                print >>sys.stderr, MOZRUNNER_BIN_NOT_FOUND_HELP.strip()
-                retval = -1
-            else:
-                raise
-    sys.exit(retval)
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/_version.py
+++ /dev/null
@@ -1,174 +0,0 @@
-
-# This file helps to compute a version number in source trees obtained from
-# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (build by setup.py sdist) and build
-# directories (produced by setup.py build) will contain a much shorter file
-# that just contains the computed version number.
-
-# This file is released into the public domain. Generated by versioneer-0.6
-# (https://github.com/warner/python-versioneer)
-
-# these strings will be replaced by git during git-archive
-git_refnames = "$Format:%d$"
-git_full = "$Format:%H$"
-
-
-import subprocess
-
-def run_command(args, cwd=None, verbose=False):
-    try:
-        # remember shell=False, so use git.cmd on windows, not just git
-        p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
-    except EnvironmentError, e:
-        if verbose:
-            print "unable to run %s" % args[0]
-            print e
-        return None
-    stdout = p.communicate()[0].strip()
-    if p.returncode != 0:
-        if verbose:
-            print "unable to run %s (error)" % args[0]
-        return None
-    return stdout
-
-
-import sys
-import re
-import os.path
-
-def get_expanded_variables(versionfile_source):
-    """
-    the code embedded in _version.py can just fetch the value of these
-    variables. When used from setup.py, we don't want to import
-    _version.py, so we do it with a regexp instead. This function is not
-    used from _version.py.
-    """
-    variables = {}
-    try:
-        for line in open(versionfile_source,"r").readlines():
-            if line.strip().startswith("git_refnames ="):
-                mo = re.search(r'=\s*"(.*)"', line)
-                if mo:
-                    variables["refnames"] = mo.group(1)
-            if line.strip().startswith("git_full ="):
-                mo = re.search(r'=\s*"(.*)"', line)
-                if mo:
-                    variables["full"] = mo.group(1)
-    except EnvironmentError:
-        pass
-    return variables
-
-def versions_from_expanded_variables(variables, tag_prefix):
-    refnames = variables["refnames"].strip()
-    if refnames.startswith("$Format"):
-        return {} # unexpanded, so not in an unpacked git-archive tarball
-    refs = set([r.strip() for r in refnames.strip("()").split(",")])
-    for ref in list(refs):
-        if not re.search(r'\d', ref):
-            refs.discard(ref)
-            # Assume all version tags have a digit. git's %d expansion
-            # behaves like git log --decorate=short and strips out the
-            # refs/heads/ and refs/tags/ prefixes that would let us
-            # distinguish between branches and tags. By ignoring refnames
-            # without digits, we filter out many common branch names like
-            # "release" and "stabilization", as well as "HEAD" and "master".
-    for ref in sorted(refs):
-        # sorting will prefer e.g. "2.0" over "2.0rc1"
-        if ref.startswith(tag_prefix):
-            r = ref[len(tag_prefix):]
-            return { "version": r,
-                     "full": variables["full"].strip() }
-    # no suitable tags, so we use the full revision id
-    return { "version": variables["full"].strip(),
-             "full": variables["full"].strip() }
-
-def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
-    """
-    this runs 'git' from the root of the source tree. That either means
-    someone ran a setup.py command (and this code is in versioneer.py, thus
-    the containing directory is the root of the source tree), or someone
-    ran a project-specific entry point (and this code is in _version.py,
-    thus the containing directory is somewhere deeper in the source tree).
-    This only gets called if the git-archive 'subst' variables were *not*
-    expanded, and _version.py hasn't already been rewritten with a short
-    version string, meaning we're inside a checked out source tree.
-    """
-    try:
-        here = os.path.abspath(__file__)
-    except NameError:
-        # some py2exe/bbfreeze/non-CPython implementations don't do __file__
-        return {} # not always correct
-
-    # versionfile_source is the relative path from the top of the source tree
-    # (where the .git directory might live) to this file. Invert this to find
-    # the root from __file__.
-    root = here
-    for i in range(len(versionfile_source.split("/"))):
-        root = os.path.dirname(root)
-    if not os.path.exists(os.path.join(root, ".git")):
-        return {}
-
-    GIT = "git"
-    if sys.platform == "win32":
-        GIT = "git.cmd"
-    stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
-                         cwd=root)
-    if stdout is None:
-        return {}
-    if not stdout.startswith(tag_prefix):
-        if verbose:
-            print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)
-        return {}
-    tag = stdout[len(tag_prefix):]
-    stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
-    if stdout is None:
-        return {}
-    full = stdout.strip()
-    if tag.endswith("-dirty"):
-        full += "-dirty"
-    return {"version": tag, "full": full}
-
-
-def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):
-    try:
-        here = os.path.abspath(__file__)
-        # versionfile_source is the relative path from the top of the source
-        # tree (where the .git directory might live) to _version.py, when
-        # this is used by the runtime. Invert this to find the root from
-        # __file__.
-        root = here
-        for i in range(len(versionfile_source.split("/"))):
-            root = os.path.dirname(root)
-    except NameError:
-        # try a couple different things to handle py2exe, bbfreeze, and
-        # non-CPython implementations which don't do __file__. This code
-        # either lives in versioneer.py (used by setup.py) or _version.py
-        # (used by the runtime). In the versioneer.py case, sys.argv[0] will
-        # be setup.py, in the root of the source tree. In the _version.py
-        # case, we have no idea what sys.argv[0] is (some
-        # application-specific runner).
-        root = os.path.dirname(os.path.abspath(sys.argv[0]))
-    # Source tarballs conventionally unpack into a directory that includes
-    # both the project name and a version string.
-    dirname = os.path.basename(root)
-    if not dirname.startswith(parentdir_prefix):
-        if verbose:
-            print "dirname '%s' doesn't start with prefix '%s'" %                   (dirname, parentdir_prefix)
-        return None
-    return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-tag_prefix = ""
-parentdir_prefix = "addon-sdk-"
-versionfile_source = "python-lib/cuddlefish/_version.py"
-
-def get_versions():
-    variables = { "refnames": git_refnames, "full": git_full }
-    ver = versions_from_expanded_variables(variables, tag_prefix)
-    if not ver:
-        ver = versions_from_vcs(tag_prefix, versionfile_source)
-    if not ver:
-        ver = versions_from_parentdir(parentdir_prefix, versionfile_source)
-    if not ver:
-        ver = {"version": "unknown", "full": ""}
-    return ver
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/bunch.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Taken from Paver's paver.options module.
-
-class Bunch(dict):
-    """A dictionary that provides attribute-style access."""
-
-    def __repr__(self):
-        keys = self.keys()
-        keys.sort()
-        args = ', '.join(['%s=%r' % (key, self[key]) for key in keys])
-        return '%s(%s)' % (self.__class__.__name__, args)
-    
-    def __getitem__(self, key):
-        item = dict.__getitem__(self, key)
-        if callable(item):
-            return item()
-        return item
-
-    def __getattr__(self, name):
-        try:
-            return self[name]
-        except KeyError:
-            raise AttributeError(name)
-
-    __setattr__ = dict.__setitem__
-
-    def __delattr__(self, name):
-        try:
-            del self[name]
-        except KeyError:
-            raise AttributeError(name)
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/manifest.py
+++ /dev/null
@@ -1,807 +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/.
-
-
-import os, sys, re, hashlib
-import simplejson as json
-SEP = os.path.sep
-from cuddlefish.util import filter_filenames, filter_dirnames
-
-# Load new layout mapping hashtable
-path = os.path.join(os.environ.get('CUDDLEFISH_ROOT'), "mapping.json")
-data = open(path, 'r').read()
-NEW_LAYOUT_MAPPING = json.loads(data)
-
-def js_zipname(packagename, modulename):
-    return "%s-lib/%s.js" % (packagename, modulename)
-def docs_zipname(packagename, modulename):
-    return "%s-docs/%s.md" % (packagename, modulename)
-def datamap_zipname(packagename):
-    return "%s-data.json" % packagename
-def datafile_zipname(packagename, datapath):
-    return "%s-data/%s" % (packagename, datapath)
-
-def to_json(o):
-    return json.dumps(o, indent=1).encode("utf-8")+"\n"
-
-class ModuleNotFoundError(Exception):
-    def __init__(self, requirement_type, requirement_name,
-                 used_by, line_number, looked_in):
-        Exception.__init__(self)
-        self.requirement_type = requirement_type # "require" or "define"
-        self.requirement_name = requirement_name # string, what they require()d
-        self.used_by = used_by # string, full path to module which did require()
-        self.line_number = line_number # int, 1-indexed line number of first require()
-        self.looked_in = looked_in # list of full paths to potential .js files
-    def __str__(self):
-        what = "%s(%s)" % (self.requirement_type, self.requirement_name)
-        where = self.used_by
-        if self.line_number is not None:
-            where = "%s:%d" % (self.used_by, self.line_number)
-        searched = "Looked for it in:\n  %s\n" % "\n  ".join(self.looked_in)
-        return ("ModuleNotFoundError: unable to satisfy: %s from\n"
-                "  %s:\n" % (what, where)) + searched
-
-class BadModuleIdentifier(Exception):
-    pass
-class BadSection(Exception):
-    pass
-class UnreachablePrefixError(Exception):
-    pass
-
-class ManifestEntry:
-    def __init__(self):
-        self.docs_filename = None
-        self.docs_hash = None
-        self.requirements = {}
-        self.datamap = None
-
-    def get_path(self):
-        name = self.moduleName
-
-        if name.endswith(".js"):
-            name = name[:-3]
-        items = []
-        # Only add package name for addons, so that system module paths match
-        # the path from the commonjs root directory and also match the loader
-        # mappings.
-        if self.packageName != "addon-sdk":
-            items.append(self.packageName)
-        # And for the same reason, do not append `lib/`.
-        if self.sectionName == "tests":
-            items.append(self.sectionName)
-        items.append(name)
-
-        return "/".join(items)
-
-    def get_entry_for_manifest(self):
-        entry = { "packageName": self.packageName,
-                  "sectionName": self.sectionName,
-                  "moduleName": self.moduleName,
-                  "jsSHA256": self.js_hash,
-                  "docsSHA256": self.docs_hash,
-                  "requirements": {},
-                  }
-        for req in self.requirements:
-            if isinstance(self.requirements[req], ManifestEntry):
-                them = self.requirements[req] # this is another ManifestEntry
-                entry["requirements"][req] = them.get_path()
-            else:
-                # something magic. The manifest entry indicates that they're
-                # allowed to require() it
-                entry["requirements"][req] = self.requirements[req]
-            assert isinstance(entry["requirements"][req], unicode) or \
-                   isinstance(entry["requirements"][req], str)
-        return entry
-
-    def add_js(self, js_filename):
-        self.js_filename = js_filename
-        self.js_hash = hash_file(js_filename)
-    def add_docs(self, docs_filename):
-        self.docs_filename = docs_filename
-        self.docs_hash = hash_file(docs_filename)
-    def add_requirement(self, reqname, reqdata):
-        self.requirements[reqname] = reqdata
-    def add_data(self, datamap):
-        self.datamap = datamap
-
-    def get_js_zipname(self):
-        return js_zipname(self.packagename, self.modulename)
-    def get_docs_zipname(self):
-        if self.docs_hash:
-            return docs_zipname(self.packagename, self.modulename)
-        return None
-    # self.js_filename
-    # self.docs_filename
-
-
-def hash_file(fn):
-    return hashlib.sha256(open(fn,"rb").read()).hexdigest()
-
-def get_datafiles(datadir):
-    """
-    yields pathnames relative to DATADIR, ignoring some files
-    """
-    for dirpath, dirnames, filenames in os.walk(datadir):
-        filenames = list(filter_filenames(filenames))
-        # this tells os.walk to prune the search
-        dirnames[:] = filter_dirnames(dirnames)
-        for filename in filenames:
-            fullname = os.path.join(dirpath, filename)
-            assert fullname.startswith(datadir+SEP), "%s%s not in %s" % (datadir, SEP, fullname)
-            yield fullname[len(datadir+SEP):]
-
-
-class DataMap:
-    # one per package
-    def __init__(self, pkg):
-        self.pkg = pkg
-        self.name = pkg.name
-        self.files_to_copy = []
-        datamap = {}
-        datadir = os.path.join(pkg.root_dir, "data")
-        for dataname in get_datafiles(datadir):
-            absname = os.path.join(datadir, dataname)
-            zipname = datafile_zipname(pkg.name, dataname)
-            datamap[dataname] = hash_file(absname)
-            self.files_to_copy.append( (zipname, absname) )
-        self.data_manifest = to_json(datamap)
-        self.data_manifest_hash = hashlib.sha256(self.data_manifest).hexdigest()
-        self.data_manifest_zipname = datamap_zipname(pkg.name)
-        self.data_uri_prefix = "%s/data/" % (self.name)
-
-class BadChromeMarkerError(Exception):
-    pass
-
-class ModuleInfo:
-    def __init__(self, package, section, name, js, docs):
-        self.package = package
-        self.section = section
-        self.name = name
-        self.js = js
-        self.docs = docs
-
-    def __hash__(self):
-        return hash( (self.package.name, self.section, self.name,
-                      self.js, self.docs) )
-    def __eq__(self, them):
-        if them.__class__ is not self.__class__:
-            return False
-        if ((them.package.name, them.section, them.name, them.js, them.docs) !=
-            (self.package.name, self.section, self.name, self.js, self.docs) ):
-            return False
-        return True
-
-    def __repr__(self):
-        return "ModuleInfo [%s %s %s] (%s, %s)" % (self.package.name,
-                                                   self.section,
-                                                   self.name,
-                                                   self.js, self.docs)
-
-class ManifestBuilder:
-    def __init__(self, target_cfg, pkg_cfg, deps, extra_modules,
-                 stderr=sys.stderr, abort_on_missing=False):
-        self.manifest = {} # maps (package,section,module) to ManifestEntry
-        self.target_cfg = target_cfg # the entry point
-        self.pkg_cfg = pkg_cfg # all known packages
-        self.deps = deps # list of package names to search
-        self.used_packagenames = set()
-        self.stderr = stderr
-        self.extra_modules = extra_modules
-        self.modules = {} # maps ModuleInfo to URI in self.manifest
-        self.datamaps = {} # maps package name to DataMap instance
-        self.files = [] # maps manifest index to (absfn,absfn) js/docs pair
-        self.test_modules = [] # for runtime
-        self.abort_on_missing = abort_on_missing # cfx eol
-
-    def build(self, scan_tests, test_filter_re):
-        """
-        process the top module, which recurses to process everything it reaches
-        """
-        if "main" in self.target_cfg:
-            top_mi = self.find_top(self.target_cfg)
-            top_me = self.process_module(top_mi)
-            self.top_path = top_me.get_path()
-            self.datamaps[self.target_cfg.name] = DataMap(self.target_cfg)
-        if scan_tests:
-            mi = self._find_module_in_package("addon-sdk", "lib", "sdk/test/runner", [])
-            self.process_module(mi)
-            # also scan all test files in all packages that we use. By making
-            # a copy of self.used_packagenames first, we refrain from
-            # processing tests in packages that our own tests depend upon. If
-            # we're running tests for package A, and either modules in A or
-            # tests in A depend upon modules from package B, we *don't* want
-            # to run tests for package B.
-            test_modules = []
-            dirnames = self.target_cfg["tests"]
-            if isinstance(dirnames, basestring):
-                dirnames = [dirnames]
-            dirnames = [os.path.join(self.target_cfg.root_dir, d)
-                        for d in dirnames]
-            for d in dirnames:
-                for filename in os.listdir(d):
-                    if filename.startswith("test-") and filename.endswith(".js"):
-                        testname = filename[:-3] # require(testname)
-                        if test_filter_re:
-                            if not re.search(test_filter_re, testname):
-                                continue
-                        tmi = ModuleInfo(self.target_cfg, "tests", testname,
-                                         os.path.join(d, filename), None)
-                        # scan the test's dependencies
-                        tme = self.process_module(tmi)
-                        test_modules.append( (testname, tme) )
-            # also add it as an artificial dependency of unit-test-finder, so
-            # the runtime dynamic load can work.
-            test_finder = self.get_manifest_entry("addon-sdk", "lib",
-                                                  "sdk/deprecated/unit-test-finder")
-            for (testname,tme) in test_modules:
-                test_finder.add_requirement(testname, tme)
-                # finally, tell the runtime about it, so they won't have to
-                # search for all tests. self.test_modules will be passed
-                # through the harness-options.json file in the
-                # .allTestModules property.
-                # Pass the absolute module path.
-                self.test_modules.append(tme.get_path())
-
-        # include files used by the loader
-        for em in self.extra_modules:
-            (pkgname, section, modname, js) = em
-            mi = ModuleInfo(self.pkg_cfg.packages[pkgname], section, modname,
-                            js, None)
-            self.process_module(mi)
-
-
-    def get_module_entries(self):
-        return frozenset(self.manifest.values())
-    def get_data_entries(self):
-        return frozenset(self.datamaps.values())
-
-    def get_used_packages(self):
-        used = set()
-        for index in self.manifest:
-            (package, section, module) = index
-            used.add(package)
-        return sorted(used)
-
-    def get_used_files(self, bundle_sdk_modules):
-        """
-        returns all .js files that we reference, plus data/ files. You will
-        need to add the loader, off-manifest files that it needs, and
-        generated metadata.
-        """
-        for datamap in self.datamaps.values():
-            for (zipname, absname) in datamap.files_to_copy:
-                yield absname
-
-        for me in self.get_module_entries():
-            # Only ship SDK files if we are told to do so
-            if me.packageName != "addon-sdk" or bundle_sdk_modules:
-                yield me.js_filename
-
-    def get_harness_options_manifest(self, bundle_sdk_modules):
-        manifest = {}
-        for me in self.get_module_entries():
-            path = me.get_path()
-            # Do not add manifest entries for system modules.
-            # Doesn't prevent from shipping modules.
-            # Shipping modules is decided in `get_used_files`.
-            if me.packageName != "addon-sdk" or bundle_sdk_modules:
-                manifest[path] = me.get_entry_for_manifest()
-        return manifest
-
-    def get_manifest_entry(self, package, section, module):
-        index = (package, section, module)
-        if index not in self.manifest:
-            m = self.manifest[index] = ManifestEntry()
-            m.packageName = package
-            m.sectionName = section
-            m.moduleName = module
-            self.used_packagenames.add(package)
-        return self.manifest[index]
-
-    def uri_name_from_path(self, pkg, fn):
-        # given a filename like .../pkg1/lib/bar/foo.js, and a package
-        # specification (with a .root_dir like ".../pkg1" and a .lib list of
-        # paths where .lib[0] is like "lib"), return the appropriate NAME
-        # that can be put into a URI like resource://JID-pkg1-lib/NAME . This
-        # will throw an exception if the file is outside of the lib/
-        # directory, since that means we can't construct a URI that points to
-        # it.
-        #
-        # This should be a lot easier, and shouldn't fail when the file is in
-        # the root of the package. Both should become possible when the XPI
-        # is rearranged and our URI scheme is simplified.
-        fn = os.path.abspath(fn)
-        pkglib = pkg.lib[0]
-        libdir = os.path.abspath(os.path.join(pkg.root_dir, pkglib))
-        # AARGH, section and name! we need to reverse-engineer a
-        # ModuleInfo instance that will produce a URI (in the form
-        # PREFIX/PKGNAME-SECTION/JS) that will map to the existing file.
-        # Until we fix URI generation to get rid of "sections", this is
-        # limited to files in the same .directories.lib as the rest of
-        # the package uses. So if the package's main files are in lib/,
-        # but the main.js is in the package root, there is no URI we can
-        # construct that will point to it, and we must fail.
-        #
-        # This will become much easier (and the failure case removed)
-        # when we get rid of sections and change the URIs to look like
-        # (PREFIX/PKGNAME/PATH-TO-JS).
-
-        # AARGH 2, allowing .lib to be a list is really getting in the
-        # way. That needs to go away eventually too.
-        if not fn.startswith(libdir):
-            raise UnreachablePrefixError("Sorry, but the 'main' file (%s) in package %s is outside that package's 'lib' directory (%s), so I cannot construct a URI to reach it."
-                                         % (fn, pkg.name, pkglib))
-        name = fn[len(libdir):].lstrip(SEP)[:-len(".js")]
-        return name
-
-
-    def parse_main(self, root_dir, main, check_lib_dir=None):
-        # 'main' can be like one of the following:
-        #   a: ./lib/main.js  b: ./lib/main  c: lib/main
-        # we require it to be a path to the file, though, and ignore the
-        # .directories stuff. So just "main" is insufficient if you really
-        # want something in a "lib/" subdirectory.
-        if main.endswith(".js"):
-            main = main[:-len(".js")]
-        if main.startswith("./"):
-            main = main[len("./"):]
-        # package.json must always use "/", but on windows we'll replace that
-        # with "\" before using it as an actual filename
-        main = os.sep.join(main.split("/"))
-        paths = [os.path.join(root_dir, main+".js")]
-        if check_lib_dir is not None:
-            paths.append(os.path.join(root_dir, check_lib_dir, main+".js"))
-        return paths
-
-    def find_top_js(self, target_cfg):
-        for libdir in target_cfg.lib:
-            for n in self.parse_main(target_cfg.root_dir, target_cfg.main,
-                                     libdir):
-                if os.path.exists(n):
-                    return n
-        raise KeyError("unable to find main module '%s.js' in top-level package" % target_cfg.main)
-
-    def find_top(self, target_cfg):
-        top_js = self.find_top_js(target_cfg)
-        n = os.path.join(target_cfg.root_dir, "README.md")
-        if os.path.exists(n):
-            top_docs = n
-        else:
-            top_docs = None
-        name = self.uri_name_from_path(target_cfg, top_js)
-        return ModuleInfo(target_cfg, "lib", name, top_js, top_docs)
-
-    def process_module(self, mi):
-        pkg = mi.package
-        #print "ENTERING", pkg.name, mi.name
-        # mi.name must be fully-qualified
-        assert (not mi.name.startswith("./") and
-                not mi.name.startswith("../"))
-        # create and claim the manifest row first
-        me = self.get_manifest_entry(pkg.name, mi.section, mi.name)
-
-        me.add_js(mi.js)
-        if mi.docs:
-            me.add_docs(mi.docs)
-
-        js_lines = open(mi.js,"r").readlines()
-        requires, problems, locations = scan_module(mi.js,js_lines,self.stderr)
-        if problems:
-            # the relevant instructions have already been written to stderr
-            raise BadChromeMarkerError()
-
-        # We update our requirements on the way out of the depth-first
-        # traversal of the module graph
-
-        for reqname in sorted(requires.keys()):
-            # If requirement is chrome or a pseudo-module (starts with @) make
-            # path a requirement name.
-            if reqname == "chrome" or reqname.startswith("@"):
-                me.add_requirement(reqname, reqname)
-            else:
-                # when two modules require() the same name, do they get a
-                # shared instance? This is a deep question. For now say yes.
-
-                # find_req_for() returns an entry to put in our
-                # 'requirements' dict, and will recursively process
-                # everything transitively required from here. It will also
-                # populate the self.modules[] cache. Note that we must
-                # tolerate cycles in the reference graph.
-                looked_in = [] # populated by subroutines
-                them_me = self.find_req_for(mi, reqname, looked_in, locations)
-                if them_me is None:
-                    if mi.section == "tests":
-                        # tolerate missing modules in tests, because
-                        # test-securable-module.js, and the modules/red.js
-                        # that it imports, both do that intentionally
-                        continue
-                    if reqname.endswith(".jsm"):
-                        # ignore JSM modules
-                        continue
-                    if not self.abort_on_missing:
-                        # print a warning, but tolerate missing modules
-                        # unless cfx --abort-on-missing-module flag was set
-                        print >>self.stderr, "Warning: missing module: %s" % reqname
-                        me.add_requirement(reqname, reqname)
-                        continue
-                    lineno = locations.get(reqname) # None means define()
-                    if lineno is None:
-                        reqtype = "define"
-                    else:
-                        reqtype = "require"
-                    err = ModuleNotFoundError(reqtype, reqname,
-                                              mi.js, lineno, looked_in)
-                    raise err
-                else:
-                    me.add_requirement(reqname, them_me)
-
-        return me
-        #print "LEAVING", pkg.name, mi.name
-
-    def find_req_for(self, from_module, reqname, looked_in, locations):
-        # handle a single require(reqname) statement from from_module .
-        # Return a uri that exists in self.manifest
-        # Populate looked_in with places we looked.
-        def BAD(msg):
-            return BadModuleIdentifier(msg + " in require(%s) from %s" %
-                                       (reqname, from_module))
-
-        if not reqname:
-            raise BAD("no actual modulename")
-
-        # Allow things in tests/*.js to require both test code and real code.
-        # But things in lib/*.js can only require real code.
-        if from_module.section == "tests":
-            lookfor_sections = ["tests", "lib"]
-        elif from_module.section == "lib":
-            lookfor_sections = ["lib"]
-        else:
-            raise BadSection(from_module.section)
-        modulename = from_module.name
-
-        #print " %s require(%s))" % (from_module, reqname)
-
-        if reqname.startswith("./") or reqname.startswith("../"):
-            # 1: they want something relative to themselves, always from
-            # their own package
-            them = modulename.split("/")[:-1]
-            bits = reqname.split("/")
-            while bits[0] in (".", ".."):
-                if not bits:
-                    raise BAD("no actual modulename")
-                if bits[0] == "..":
-                    if not them:
-                        raise BAD("too many ..")
-                    them.pop()
-                bits.pop(0)
-            bits = them+bits
-            lookfor_pkg = from_module.package.name
-            lookfor_mod = "/".join(bits)
-            return self._get_module_from_package(lookfor_pkg,
-                                                 lookfor_sections, lookfor_mod,
-                                                 looked_in)
-
-        # non-relative import. Might be a short name (requiring a search
-        # through "library" packages), or a fully-qualified one.
-
-        if "/" in reqname:
-            # 2: PKG/MOD: find PKG, look inside for MOD
-            bits = reqname.split("/")
-            lookfor_pkg = bits[0]
-            lookfor_mod = "/".join(bits[1:])
-            mi = self._get_module_from_package(lookfor_pkg,
-                                               lookfor_sections, lookfor_mod,
-                                               looked_in)
-            if mi: # caution, 0==None
-                return mi
-        else:
-            # 3: try finding PKG, if found, use its main.js entry point
-            lookfor_pkg = reqname
-            mi = self._get_entrypoint_from_package(lookfor_pkg, looked_in)
-            if mi:
-                return mi
-
-        # 4: search packages for MOD or MODPARENT/MODCHILD. We always search
-        # their own package first, then the list of packages defined by their
-        # .dependencies list
-        from_pkg = from_module.package.name
-        mi = self._search_packages_for_module(from_pkg,
-                                              lookfor_sections, reqname,
-                                              looked_in)
-        if mi:
-            return mi
-
-        # Only after we look for module in the addon itself, search for a module
-        # in new layout.
-        # First normalize require argument in order to easily find a mapping
-        normalized = reqname
-        if normalized.endswith(".js"):
-            normalized = normalized[:-len(".js")]
-        if normalized.startswith("addon-kit/"):
-            normalized = normalized[len("addon-kit/"):]
-        if normalized.startswith("api-utils/"):
-            normalized = normalized[len("api-utils/"):]
-        if normalized in NEW_LAYOUT_MAPPING:
-            # get the new absolute path for this module
-            original_reqname = reqname
-            reqname = NEW_LAYOUT_MAPPING[normalized]
-            from_pkg = from_module.package.name
-
-            # If the addon didn't explicitely told us to ignore deprecated
-            # require path, warn the developer:
-            # (target_cfg is the package.json file)
-            if not "ignore-deprecated-path" in self.target_cfg:
-                lineno = locations.get(original_reqname)
-                print >>self.stderr, "Warning: Use of deprecated require path:"
-                print >>self.stderr, "  In %s:%d:" % (from_module.js, lineno)
-                print >>self.stderr, "    require('%s')." % original_reqname
-                print >>self.stderr, "  New path should be:"
-                print >>self.stderr, "    require('%s')" % reqname
-
-            return self._search_packages_for_module(from_pkg,
-                                                    lookfor_sections, reqname,
-                                                    looked_in)
-        else:
-            # We weren't able to find this module, really.
-            return None
-
-    def _handle_module(self, mi):
-        if not mi:
-            return None
-
-        # we tolerate cycles in the reference graph, which means we need to
-        # populate the self.modules cache before recursing into
-        # process_module() . We must also check the cache first, so recursion
-        # can terminate.
-        if mi in self.modules:
-            return self.modules[mi]
-
-        # this creates the entry
-        new_entry = self.get_manifest_entry(mi.package.name, mi.section, mi.name)
-        # and populates the cache
-        self.modules[mi] = new_entry
-        self.process_module(mi)
-        return new_entry
-
-    def _get_module_from_package(self, pkgname, sections, modname, looked_in):
-        if pkgname not in self.pkg_cfg.packages:
-            return None
-        mi = self._find_module_in_package(pkgname, sections, modname,
-                                          looked_in)
-        return self._handle_module(mi)
-
-    def _get_entrypoint_from_package(self, pkgname, looked_in):
-        if pkgname not in self.pkg_cfg.packages:
-            return None
-        pkg = self.pkg_cfg.packages[pkgname]
-        main = pkg.get("main", None)
-        if not main:
-            return None
-        for js in self.parse_main(pkg.root_dir, main):
-            looked_in.append(js)
-            if os.path.exists(js):
-                section = "lib"
-                name = self.uri_name_from_path(pkg, js)
-                docs = None
-                mi = ModuleInfo(pkg, section, name, js, docs)
-                return self._handle_module(mi)
-        return None
-
-    def _search_packages_for_module(self, from_pkg, sections, reqname,
-                                    looked_in):
-        searchpath = [] # list of package names
-        searchpath.append(from_pkg) # search self first
-        us = self.pkg_cfg.packages[from_pkg]
-        if 'dependencies' in us:
-            # only look in dependencies
-            searchpath.extend(us['dependencies'])
-        else:
-            # they didn't declare any dependencies (or they declared an empty
-            # list, but we'll treat that as not declaring one, because it's
-            # easier), so look in all deps, sorted alphabetically, so
-            # addon-kit comes first. Note that self.deps includes all
-            # packages found by traversing the ".dependencies" lists in each
-            # package.json, starting from the main addon package, plus
-            # everything added by --extra-packages
-            searchpath.extend(sorted(self.deps))
-        for pkgname in searchpath:
-            mi = self._find_module_in_package(pkgname, sections, reqname,
-                                              looked_in)
-            if mi:
-                return self._handle_module(mi)
-        return None
-
-    def _find_module_in_package(self, pkgname, sections, name, looked_in):
-        # require("a/b/c") should look at ...\a\b\c.js on windows
-        filename = os.sep.join(name.split("/"))
-        # normalize filename, make sure that we do not add .js if it already has
-        # it.
-        if not filename.endswith(".js") and not filename.endswith(".json"):
-          filename += ".js"
-
-        if filename.endswith(".js"):
-          basename = filename[:-3]
-        if filename.endswith(".json"):
-          basename = filename[:-5]
-
-        pkg = self.pkg_cfg.packages[pkgname]
-        if isinstance(sections, basestring):
-            sections = [sections]
-        for section in sections:
-            for sdir in pkg.get(section, []):
-                js = os.path.join(pkg.root_dir, sdir, filename)
-                looked_in.append(js)
-                if os.path.exists(js):
-                    docs = None
-                    maybe_docs = os.path.join(pkg.root_dir, "docs",
-                                              basename+".md")
-                    if section == "lib" and os.path.exists(maybe_docs):
-                        docs = maybe_docs
-                    return ModuleInfo(pkg, section, name, js, docs)
-        return None
-
-def build_manifest(target_cfg, pkg_cfg, deps, scan_tests,
-                   test_filter_re=None, extra_modules=[], abort_on_missing=False):
-    """
-    Perform recursive dependency analysis starting from entry_point,
-    building up a manifest of modules that need to be included in the XPI.
-    Each entry will map require() names to the URL of the module that will
-    be used to satisfy that dependency. The manifest will be used by the
-    runtime's require() code.
-
-    This returns a ManifestBuilder object, with two public methods. The
-    first, get_module_entries(), returns a set of ManifestEntry objects, each
-    of which can be asked for the following:
-
-     * its contribution to the harness-options.json '.manifest'
-     * the local disk name
-     * the name in the XPI at which it should be placed
-
-    The second is get_data_entries(), which returns a set of DataEntry
-    objects, each of which has:
-
-     * local disk name
-     * name in the XPI
-
-    note: we don't build the XPI here, but our manifest is passed to the
-    code which does, so it knows what to copy into the XPI.
-    """
-
-    mxt = ManifestBuilder(target_cfg, pkg_cfg, deps, extra_modules,
-                          abort_on_missing=abort_on_missing)
-    mxt.build(scan_tests, test_filter_re)
-    return mxt
-
-
-
-COMMENT_PREFIXES = ["//", "/*", "*", "dump("]
-
-REQUIRE_RE = r"(?<![\'\"])require\s*\(\s*[\'\"]([^\'\"]+?)[\'\"]\s*\)"
-
-# detect the define idiom of the form:
-#   define("module name", ["dep1", "dep2", "dep3"], function() {})
-# by capturing the contents of the list in a group.
-DEF_RE = re.compile(r"(require|define)\s*\(\s*([\'\"][^\'\"]+[\'\"]\s*,)?\s*\[([^\]]+)\]")
-
-# Out of the async dependencies, do not allow quotes in them.
-DEF_RE_ALLOWED = re.compile(r"^[\'\"][^\'\"]+[\'\"]$")
-
-def scan_requirements_with_grep(fn, lines):
-    requires = {}
-    first_location = {}
-    for (lineno0, line) in enumerate(lines):
-        for clause in line.split(";"):
-            clause = clause.strip()
-            iscomment = False
-            for commentprefix in COMMENT_PREFIXES:
-                if clause.startswith(commentprefix):
-                    iscomment = True
-            if iscomment:
-                continue
-            mo = re.finditer(REQUIRE_RE, clause)
-            if mo:
-                for mod in mo:
-                    modname = mod.group(1)
-                    requires[modname] = {}
-                    if modname not in first_location:
-                        first_location[modname] = lineno0 + 1
-
-    # define() can happen across multiple lines, so join everyone up.
-    wholeshebang = "\n".join(lines)
-    for match in DEF_RE.finditer(wholeshebang):
-        # this should net us a list of string literals separated by commas
-        for strbit in match.group(3).split(","):
-            strbit = strbit.strip()
-            # There could be a trailing comma netting us just whitespace, so
-            # filter that out. Make sure that only string values with
-            # quotes around them are allowed, and no quotes are inside
-            # the quoted value.
-            if strbit and DEF_RE_ALLOWED.match(strbit):
-                modname = strbit[1:-1]
-                if modname not in ["exports"]:
-                    requires[modname] = {}
-                    # joining all the lines means we lose line numbers, so we
-                    # can't fill first_location[]
-
-    return requires, first_location
-
-CHROME_ALIASES = [
-    (re.compile(r"Components\.classes"), "Cc"),
-    (re.compile(r"Components\.interfaces"), "Ci"),
-    (re.compile(r"Components\.utils"), "Cu"),
-    (re.compile(r"Components\.results"), "Cr"),
-    (re.compile(r"Components\.manager"), "Cm"),
-    ]
-OTHER_CHROME = re.compile(r"Components\.[a-zA-Z]")
-
-def scan_for_bad_chrome(fn, lines, stderr):
-    problems = False
-    old_chrome = set() # i.e. "Cc" when we see "Components.classes"
-    old_chrome_lines = [] # list of (lineno, line.strip()) tuples
-    for lineno,line in enumerate(lines):
-        # note: this scanner is not obligated to spot all possible forms of
-        # chrome access. The scanner is detecting voluntary requests for
-        # chrome. Runtime tools will enforce allowance or denial of access.
-        line = line.strip()
-        iscomment = False
-        for commentprefix in COMMENT_PREFIXES:
-            if line.startswith(commentprefix):
-                iscomment = True
-                break
-        if iscomment:
-            continue
-        old_chrome_in_this_line = set()
-        for (regexp,alias) in CHROME_ALIASES:
-            if regexp.search(line):
-                old_chrome_in_this_line.add(alias)
-        if not old_chrome_in_this_line:
-            if OTHER_CHROME.search(line):
-                old_chrome_in_this_line.add("components")
-        old_chrome.update(old_chrome_in_this_line)
-        if old_chrome_in_this_line:
-            old_chrome_lines.append( (lineno+1, line) )
-
-    if old_chrome:
-        print >>stderr, """
-The following lines from file %(fn)s:
-%(lines)s
-use 'Components' to access chrome authority. To do so, you need to add a
-line somewhat like the following:
-
-  const {%(needs)s} = require("chrome");
-
-Then you can use any shortcuts to its properties that you import from the
-'chrome' module ('Cc', 'Ci', 'Cm', 'Cr', and 'Cu' for the 'classes',
-'interfaces', 'manager', 'results', and 'utils' properties, respectively. And
-`components` for `Components` object itself).
-""" % { "fn": fn, "needs": ",".join(sorted(old_chrome)),
-        "lines": "\n".join([" %3d: %s" % (lineno,line)
-                            for (lineno, line) in old_chrome_lines]),
-        }
-        problems = True
-    return problems
-
-def scan_module(fn, lines, stderr=sys.stderr):
-    filename = os.path.basename(fn)
-    requires, locations = scan_requirements_with_grep(fn, lines)
-    if filename == "cuddlefish.js":
-        # this is the loader: don't scan for chrome
-        problems = False
-    else:
-        problems = scan_for_bad_chrome(fn, lines, stderr)
-    return requires, problems, locations
-
-
-
-if __name__ == '__main__':
-    for fn in sys.argv[1:]:
-        requires, problems, locations = scan_module(fn, open(fn).readlines())
-        print
-        print "---", fn
-        if problems:
-            print "PROBLEMS"
-            sys.exit(1)
-        print "requires: %s" % (",".join(sorted(requires.keys())))
-        print "locations: %s" % locations
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-
-var { log } = console;
-
-function startup(data, reason) {
-  // This code allow to make all stdIO work
-  try {
-    Cu.import("resource://gre/modules/ctypes.jsm");
-    let libdvm = ctypes.open("libdvm.so");
-    let dvmStdioConverterStartup;
-    // Starting with Android ICS, dalvik uses C++.
-    // So that the symbol isn't a simple C one
-    try {
-      dvmStdioConverterStartup = libdvm.declare("_Z24dvmStdioConverterStartupv", ctypes.default_abi, ctypes.bool);
-    }
-    catch(e) {
-      // Otherwise, before ICS, it was a pure C library
-      dvmStdioConverterStartup = libdvm.declare("dvmStdioConverterStartup", ctypes.default_abi, ctypes.void_t);
-    }
-    dvmStdioConverterStartup();
-    log("MU: console redirected to adb logcat.");
-  } catch(e) {
-    Cu.reportError("MU: unable to execute jsctype hack: "+e);
-  }
-
-  try {
-    let QuitObserver = {
-      observe: function (aSubject, aTopic, aData) {
-        Services.obs.removeObserver(QuitObserver, "quit-application");
-        dump("MU: APPLICATION-QUIT\n");
-      }
-    };
-    Services.obs.addObserver(QuitObserver, "quit-application");
-    log("MU: ready to watch firefox exit.");
-  } catch(e) {
-    log("MU: unable to register quit-application observer: " + e);
-  }
-}
-
-function install() {}
-function shutdown() {}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/install.rdf
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.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/. -->
-
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>mobile-utils@mozilla.com</em:id>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-
-    <!-- Fennec-XUL -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{a23983c0-fd0e-11dc-95ff-0800200c9a66}</em:id>
-        <em:minVersion>1</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Fennec-NativeUI -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
-        <em:minVersion>1</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Mobile Addon-SDK utility addon</em:name>
-    <em:description>Allow better integration with cfx tool.</em:description>
-    <em:creator>Mozilla Corporation</em:creator>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/packaging.py
+++ /dev/null
@@ -1,463 +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/.
-
-import os
-import sys
-import re
-import copy
-
-import simplejson as json
-from cuddlefish.bunch import Bunch
-
-MANIFEST_NAME = 'package.json'
-DEFAULT_LOADER = 'addon-sdk'
-
-# Is different from root_dir when running tests
-env_root = os.environ.get('CUDDLEFISH_ROOT')
-
-DEFAULT_PROGRAM_MODULE = 'main'
-
-DEFAULT_ICON = 'icon.png'
-DEFAULT_ICON64 = 'icon64.png'
-
-METADATA_PROPS = ['name', 'description', 'keywords', 'author', 'version',
-                  'developers', 'translators', 'contributors', 'license', 'homepage',
-                  'icon', 'icon64', 'main', 'directories', 'permissions', 'preferences']
-
-RESOURCE_HOSTNAME_RE = re.compile(r'^[a-z0-9_\-]+$')
-
-class Error(Exception):
-    pass
-
-class MalformedPackageError(Error):
-    pass
-
-class MalformedJsonFileError(Error):
-    pass
-
-class DuplicatePackageError(Error):
-    pass
-
-class PackageNotFoundError(Error):
-    def __init__(self, missing_package, reason):
-        self.missing_package = missing_package
-        self.reason = reason
-    def __str__(self):
-        return "%s (%s)" % (self.missing_package, self.reason)
-
-class BadChromeMarkerError(Error):
-    pass
-
-def validate_resource_hostname(name):
-    """
-    Validates the given hostname for a resource: URI.
-
-    For more information, see:
-
-      https://bugzilla.mozilla.org/show_bug.cgi?id=566812#c13
-
-    Examples:
-
-      >>> validate_resource_hostname('blarg')
-
-      >>> validate_resource_hostname('bl arg')
-      Traceback (most recent call last):
-      ...
-      ValueError: Error: the name of your package contains an invalid character.
-      Package names can contain only lower-case letters, numbers, underscores, and dashes.
-      Current package name: bl arg
-
-      >>> validate_resource_hostname('BLARG')
-      Traceback (most recent call last):
-      ...
-      ValueError: Error: the name of your package contains upper-case letters.
-      Package names can contain only lower-case letters, numbers, underscores, and dashes.
-      Current package name: BLARG
-
-      >>> validate_resource_hostname('foo@bar')
-      Traceback (most recent call last):
-      ...
-      ValueError: Error: the name of your package contains an invalid character.
-      Package names can contain only lower-case letters, numbers, underscores, and dashes.
-      Current package name: foo@bar
-    """
-
-    # See https://bugzilla.mozilla.org/show_bug.cgi?id=568131 for details.
-    if not name.lower() == name:
-        raise ValueError("""Error: the name of your package contains upper-case letters.
-Package names can contain only lower-case letters, numbers, underscores, and dashes.
-Current package name: %s""" % name)
-
-    if not RESOURCE_HOSTNAME_RE.match(name):
-        raise ValueError("""Error: the name of your package contains an invalid character.
-Package names can contain only lower-case letters, numbers, underscores, and dashes.
-Current package name: %s""" % name)
-
-def find_packages_with_module(pkg_cfg, name):
-    # TODO: Make this support more than just top-level modules.
-    filename = "%s.js" % name
-    packages = []
-    for cfg in pkg_cfg.packages.itervalues():
-        if 'lib' in cfg:
-            matches = [dirname for dirname in resolve_dirs(cfg, cfg.lib)
-                       if os.path.exists(os.path.join(dirname, filename))]
-            if matches:
-                packages.append(cfg.name)
-    return packages
-
-def resolve_dirs(pkg_cfg, dirnames):
-    for dirname in dirnames:
-        yield resolve_dir(pkg_cfg, dirname)
-
-def resolve_dir(pkg_cfg, dirname):
-    return os.path.join(pkg_cfg.root_dir, dirname)
-
-def validate_permissions(perms):
-    if (perms.get('cross-domain-content') and
-        not isinstance(perms.get('cross-domain-content'), list)):
-        raise ValueError("Error: `cross-domain-content` permissions in \
- package.json file must be an array of strings:\n  %s" % perms)
-
-def get_metadata(pkg_cfg, deps):
-    metadata = Bunch()
-    for pkg_name in deps:
-        cfg = pkg_cfg.packages[pkg_name]
-        metadata[pkg_name] = Bunch()
-        for prop in METADATA_PROPS:
-            if cfg.get(prop):
-                if prop == 'permissions':
-                    validate_permissions(cfg[prop])
-                metadata[pkg_name][prop] = cfg[prop]
-    return metadata
-
-def set_section_dir(base_json, name, base_path, dirnames, allow_root=False):
-    resolved = compute_section_dir(base_json, base_path, dirnames, allow_root)
-    if resolved:
-        base_json[name] = os.path.abspath(resolved)
-
-def compute_section_dir(base_json, base_path, dirnames, allow_root):
-    # PACKAGE_JSON.lib is highest priority
-    # then PACKAGE_JSON.directories.lib
-    # then lib/ (if it exists)
-    # then . (but only if allow_root=True)
-    for dirname in dirnames:
-        if base_json.get(dirname):
-            return os.path.join(base_path, base_json[dirname])
-    if "directories" in base_json:
-        for dirname in dirnames:
-            if dirname in base_json.directories:
-                return os.path.join(base_path, base_json.directories[dirname])
-    for dirname in dirnames:
-        if os.path.isdir(os.path.join(base_path, dirname)):
-            return os.path.join(base_path, dirname)
-    if allow_root:
-        return os.path.abspath(base_path)
-    return None
-
-def normalize_string_or_array(base_json, key):
-    if base_json.get(key):
-        if isinstance(base_json[key], basestring):
-            base_json[key] = [base_json[key]]
-
-def load_json_file(path):
-    data = open(path, 'r').read()
-    try:
-        return Bunch(json.loads(data))
-    except ValueError, e:
-        raise MalformedJsonFileError('%s when reading "%s"' % (str(e),
-                                                               path))
-
-def get_config_in_dir(path):
-    package_json = os.path.join(path, MANIFEST_NAME)
-    if not (os.path.exists(package_json) and
-            os.path.isfile(package_json)):
-        raise MalformedPackageError('%s not found in "%s"' % (MANIFEST_NAME,
-                                                              path))
-    base_json = load_json_file(package_json)
-
-    if 'name' not in base_json:
-        base_json.name = os.path.basename(path)
-
-    # later processing steps will expect to see the following keys in the
-    # base_json that we return:
-    #
-    #  name: name of the package
-    #  lib: list of directories with .js files
-    #  test: list of directories with test-*.js files
-    #  doc: list of directories with documentation .md files
-    #  data: list of directories with bundled arbitrary data files
-    #  packages: ?
-
-    if (not base_json.get('tests') and
-        os.path.isdir(os.path.join(path, 'test'))):
-        base_json['tests'] = 'test'
-
-    set_section_dir(base_json, 'lib', path, ['lib'], True)
-    set_section_dir(base_json, 'tests', path, ['test', 'tests'], False)
-    set_section_dir(base_json, 'doc', path, ['doc', 'docs'])
-    set_section_dir(base_json, 'data', path, ['data'])
-    set_section_dir(base_json, 'packages', path, ['packages'])
-    set_section_dir(base_json, 'locale', path, ['locale'])
-
-    if (not base_json.get('icon') and
-        os.path.isfile(os.path.join(path, DEFAULT_ICON))):
-        base_json['icon'] = DEFAULT_ICON
-
-    if (not base_json.get('icon64') and
-        os.path.isfile(os.path.join(path, DEFAULT_ICON64))):
-        base_json['icon64'] = DEFAULT_ICON64
-
-    for key in ['lib', 'tests', 'dependencies', 'packages']:
-        # TODO: lib/tests can be an array?? consider interaction with
-        # compute_section_dir above
-        normalize_string_or_array(base_json, key)
-
-    if 'main' not in base_json and 'lib' in base_json:
-        for dirname in base_json['lib']:
-            program = os.path.join(path, dirname,
-                                   '%s.js' % DEFAULT_PROGRAM_MODULE)
-            if os.path.exists(program):
-                base_json['main'] = DEFAULT_PROGRAM_MODULE
-                break
-
-    base_json.root_dir = path
-
-    if "dependencies" in base_json:
-      deps = base_json["dependencies"]
-      deps = [x for x in deps if x not in ["addon-kit", "api-utils"]]
-      deps.append("addon-sdk")
-      base_json["dependencies"] = deps
-
-    return base_json
-
-def _is_same_file(a, b):
-    if hasattr(os.path, 'samefile'):
-        return os.path.samefile(a, b)
-    return a == b
-
-def build_config(root_dir, target_cfg, packagepath=[]):
-    dirs_to_scan = [env_root] # root is addon-sdk dir, diff from root_dir in tests
-
-    def add_packages_from_config(pkgconfig):
-        if 'packages' in pkgconfig:
-            for package_dir in resolve_dirs(pkgconfig, pkgconfig.packages):
-                dirs_to_scan.append(package_dir)
-
-    add_packages_from_config(target_cfg)
-
-    packages_dir = os.path.join(root_dir, 'packages')
-    if os.path.exists(packages_dir) and os.path.isdir(packages_dir):
-        dirs_to_scan.append(packages_dir)
-    dirs_to_scan.extend(packagepath)
-
-    packages = Bunch({target_cfg.name: target_cfg})
-
-    while dirs_to_scan:
-        packages_dir = dirs_to_scan.pop()
-        if os.path.exists(os.path.join(packages_dir, "package.json")):
-            package_paths = [packages_dir]
-        else:
-            package_paths = [os.path.join(packages_dir, dirname)
-                             for dirname in os.listdir(packages_dir)
-                             if not dirname.startswith('.')]
-            package_paths = [dirname for dirname in package_paths
-                             if os.path.isdir(dirname)]
-
-        for path in package_paths:
-            pkgconfig = get_config_in_dir(path)
-            if pkgconfig.name in packages:
-                otherpkg = packages[pkgconfig.name]
-                if not _is_same_file(otherpkg.root_dir, path):
-                    raise DuplicatePackageError(path, otherpkg.root_dir)
-            else:
-                packages[pkgconfig.name] = pkgconfig
-                add_packages_from_config(pkgconfig)
-
-    return Bunch(packages=packages)
-
-def get_deps_for_targets(pkg_cfg, targets):
-    visited = []
-    deps_left = [[dep, None] for dep in list(targets)]
-
-    while deps_left:
-        [dep, required_by] = deps_left.pop()
-        if dep not in visited:
-            visited.append(dep)
-            if dep not in pkg_cfg.packages:
-                required_reason = ("required by '%s'" % (required_by)) \
-                                    if required_by is not None \
-                                    else "specified as target"
-                raise PackageNotFoundError(dep, required_reason)
-            dep_cfg = pkg_cfg.packages[dep]
-            deps_left.extend([[i, dep] for i in dep_cfg.get('dependencies', [])])
-            deps_left.extend([[i, dep] for i in dep_cfg.get('extra_dependencies', [])])
-
-    return visited
-
-def generate_build_for_target(pkg_cfg, target, deps,
-                              include_tests=True,
-                              include_dep_tests=False,
-                              is_running_tests=False,
-                              default_loader=DEFAULT_LOADER):
-
-    build = Bunch(# Contains section directories for all packages:
-                  packages=Bunch(),
-                  locale=Bunch()
-                  )
-
-    def add_section_to_build(cfg, section, is_code=False,
-                             is_data=False):
-        if section in cfg:
-            dirnames = cfg[section]
-            if isinstance(dirnames, basestring):
-                # This is just for internal consistency within this
-                # function, it has nothing to do w/ a non-canonical
-                # configuration dict.
-                dirnames = [dirnames]
-            for dirname in resolve_dirs(cfg, dirnames):
-                # ensure that package name is valid
-                try:
-                    validate_resource_hostname(cfg.name)
-                except ValueError, err:
-                    print err
-                    sys.exit(1)
-                # ensure that this package has an entry
-                if not cfg.name in build.packages:
-                    build.packages[cfg.name] = Bunch()
-                # detect duplicated sections
-                if section in build.packages[cfg.name]:
-                    raise KeyError("package's section already defined",
-                                   cfg.name, section)
-                # Register this section (lib, data, tests)
-                build.packages[cfg.name][section] = dirname
-
-    def add_locale_to_build(cfg):
-        # Bug 730776: Ignore locales for addon-kit, that are only for unit tests
-        if not is_running_tests and cfg.name == "addon-sdk":
-            return
-
-        path = resolve_dir(cfg, cfg['locale'])
-        files = os.listdir(path)
-        for filename in files:
-            fullpath = os.path.join(path, filename)
-            if os.path.isfile(fullpath) and filename.endswith('.properties'):
-                language = filename[:-len('.properties')]
-
-                from property_parser import parse_file, MalformedLocaleFileError
-                try:
-                    content = parse_file(fullpath)
-                except MalformedLocaleFileError, msg:
-                    print msg[0]
-                    sys.exit(1)
-
-                # Merge current locales into global locale hashtable.
-                # Locale files only contains one big JSON object
-                # that act as an hastable of:
-                # "keys to translate" => "translated keys"
-                if language in build.locale:
-                    merge = (build.locale[language].items() +
-                             content.items())
-                    build.locale[language] = Bunch(merge)
-                else:
-                    build.locale[language] = content
-
-    def add_dep_to_build(dep):
-        dep_cfg = pkg_cfg.packages[dep]
-        add_section_to_build(dep_cfg, "lib", is_code=True)
-        add_section_to_build(dep_cfg, "data", is_data=True)
-        if include_tests and include_dep_tests:
-            add_section_to_build(dep_cfg, "tests", is_code=True)
-        if 'locale' in dep_cfg:
-            add_locale_to_build(dep_cfg)
-        if ("loader" in dep_cfg) and ("loader" not in build):
-            build.loader = "%s/%s" % (dep,
-                                                 dep_cfg.loader)
-
-    target_cfg = pkg_cfg.packages[target]
-
-    if include_tests and not include_dep_tests:
-        add_section_to_build(target_cfg, "tests", is_code=True)
-
-    for dep in deps:
-        add_dep_to_build(dep)
-
-    if 'loader' not in build:
-        add_dep_to_build(DEFAULT_LOADER)
-
-    if 'icon' in target_cfg:
-        build['icon'] = os.path.join(target_cfg.root_dir, target_cfg.icon)
-        del target_cfg['icon']
-
-    if 'icon64' in target_cfg:
-        build['icon64'] = os.path.join(target_cfg.root_dir, target_cfg.icon64)
-        del target_cfg['icon64']
-
-    if 'id' in target_cfg:
-        # NOTE: logic duplicated from buildJID()
-        jid = target_cfg['id']
-        if not ('@' in jid or jid.startswith('{')):
-            jid += '@jetpack'
-        build['preferencesBranch'] = jid
-
-    if 'preferences-branch' in target_cfg:
-        build['preferencesBranch'] = target_cfg['preferences-branch']
-
-    return build
-
-def _get_files_in_dir(path):
-    data = {}
-    files = os.listdir(path)
-    for filename in files:
-        fullpath = os.path.join(path, filename)
-        if os.path.isdir(fullpath):
-            data[filename] = _get_files_in_dir(fullpath)
-        else:
-            try:
-                info = os.stat(fullpath)
-                data[filename] = ("file", dict(size=info.st_size))
-            except OSError:
-                pass
-    return ("directory", data)
-
-def build_pkg_index(pkg_cfg):
-    pkg_cfg = copy.deepcopy(pkg_cfg)
-    for pkg in pkg_cfg.packages:
-        root_dir = pkg_cfg.packages[pkg].root_dir
-        files = _get_files_in_dir(root_dir)
-        pkg_cfg.packages[pkg].files = files
-        try:
-            readme = open(root_dir + '/README.md').read()
-            pkg_cfg.packages[pkg].readme = readme
-        except IOError:
-            pass
-        del pkg_cfg.packages[pkg].root_dir
-    return pkg_cfg.packages
-
-def build_pkg_cfg(root):
-    pkg_cfg = build_config(root, Bunch(name='dummy'))
-    del pkg_cfg.packages['dummy']
-    return pkg_cfg
-
-def call_plugins(pkg_cfg, deps):
-    for dep in deps:
-        dep_cfg = pkg_cfg.packages[dep]
-        dirnames = dep_cfg.get('python-lib', [])
-        for dirname in resolve_dirs(dep_cfg, dirnames):
-            sys.path.append(dirname)
-        module_names = dep_cfg.get('python-plugins', [])
-        for module_name in module_names:
-            module = __import__(module_name)
-            module.init(root_dir=dep_cfg.root_dir)
-
-def call_cmdline_tool(env_root, pkg_name):
-    pkg_cfg = build_config(env_root, Bunch(name='dummy'))
-    if pkg_name not in pkg_cfg.packages:
-        print "This tool requires the '%s' package." % pkg_name
-        sys.exit(1)
-    cfg = pkg_cfg.packages[pkg_name]
-    for dirname in resolve_dirs(cfg, cfg['python-lib']):
-        sys.path.append(dirname)
-    module_name = cfg.get('python-cmdline-tool')
-    module = __import__(module_name)
-    module.run()
deleted file mode 100755
--- a/addon-sdk/source/python-lib/cuddlefish/preflight.py
+++ /dev/null
@@ -1,77 +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/.
-
-import os, sys
-import base64
-import simplejson as json
-
-def create_jid():
-    """Return 'jid1-XYZ', where 'XYZ' is a randomly-generated string. (in the
-    previous jid0- series, the string securely identified a specific public
-    key). To get a suitable add-on ID, append '@jetpack' to this string.
-    """
-    # per https://developer.mozilla.org/en/Install_Manifests#id all XPI id
-    # values must either be in the form of a 128-bit GUID (crazy braces
-    # and all) or in the form of an email address (crazy @ and all).
-    # Firefox will refuse to install an add-on with an id that doesn't
-    # match one of these forms. The actual regexp is at:
-    # http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#130
-    # So the JID needs an @-suffix, and the only legal punctuation is
-    # "-._". So we start with a base64 encoding, and replace the
-    # punctuation (+/) with letters (AB), losing a few bits of integrity.
-
-    # even better: windows has a maximum path length limitation of 256
-    # characters:
-    #  http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
-    # (unless all paths are prefixed with "\\?\", I kid you not). The
-    # typical install will put add-on code in a directory like:
-    # C:\Documents and Settings\<username>\Application Data\Mozilla\Firefox\Profiles\232353483.default\extensions\$JID\...
-    # (which is 108 chars long without the $JID).
-    # Then the unpacked XPI contains packaged resources like:
-    #  resources/$JID-api-utils-lib/main.js   (35 chars plus the $JID)
-    #
-    # We create a random 80 bit string, base64 encode that (with
-    # AB instead of +/ to be path-safe), then bundle it into
-    # "jid1-XYZ@jetpack". This gives us 27 characters. The resulting
-    # main.js will have a path length of 211 characters, leaving us 45
-    # characters of margin.
-    #
-    # 80 bits is enough to generate one billion JIDs and still maintain lower
-    # than a one-in-a-million chance of accidental collision. (1e9 JIDs is 30
-    # bits, square for the "birthday-paradox" to get 60 bits, add 20 bits for
-    # the one-in-a-million margin to get 80 bits)
-
-    # if length were no issue, we'd prefer to use this:
-    h = os.urandom(80/8)
-    s = base64.b64encode(h, "AB").strip("=")
-    jid = "jid1-" + s
-    return jid
-
-def preflight_config(target_cfg, filename, stderr=sys.stderr):
-    modified = False
-    config = json.load(open(filename, 'r'))
-
-    if "id" not in config:
-        print >>stderr, ("No 'id' in package.json: creating a new ID for you.")
-        jid = create_jid()
-        config["id"] = jid
-        modified = True
-
-    if modified:
-        i = 0
-        backup = filename + ".backup"
-        while os.path.exists(backup):
-            if i > 1000:
-                raise ValueError("I'm having problems finding a good name"
-                                 " for the backup file. Please move %s out"
-                                 " of the way and try again."
-                                 % (filename + ".backup"))
-            backup = filename + ".backup-%d" % i
-            i += 1
-        os.rename(filename, backup)
-        new_json = json.dumps(config, indent=4)
-        open(filename, 'w').write(new_json+"\n")
-        return False, True
-
-    return True, False
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ /dev/null
@@ -1,243 +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/.
-
-DEFAULT_COMMON_PREFS = {
-    # allow debug output via dump to be printed to the system console
-    # (setting it here just in case, even though PlainTextConsole also
-    # sets this preference)
-    'browser.dom.window.dump.enabled': True,
-    # warn about possibly incorrect code
-    'javascript.options.showInConsole': True,
-
-    # Allow remote connections to the debugger
-    'devtools.debugger.remote-enabled' : True,
-
-    'extensions.sdk.console.logLevel': 'info',
-
-    'extensions.checkCompatibility.nightly' : False,
-
-    # Disable extension updates and notifications.
-    'extensions.update.enabled' : False,
-    'lightweightThemes.update.enabled' : False,
-    'extensions.update.notifyUser' : False,
-
-    # From:
-    # https://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l372
-    # Only load extensions from the application and user profile.
-    # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
-    'extensions.enabledScopes' : 5,
-    # Disable metadata caching for installed add-ons by default
-    'extensions.getAddons.cache.enabled' : False,
-    # Disable intalling any distribution add-ons
-    'extensions.installDistroAddons' : False,
-    # Allow installing extensions dropped into the profile folder
-    'extensions.autoDisableScopes' : 10,
-
-    # shut up some warnings on `about:` page
-    'app.releaseNotesURL': 'http://localhost/app-dummy/',
-    'app.vendorURL': 'http://localhost/app-dummy/',
-}
-
-DEFAULT_NO_CONNECTIONS_PREFS = {
-    'toolkit.telemetry.enabled': False,
-    'toolkit.telemetry.server': 'https://localhost/telemetry-dummy/',
-    'app.update.auto' : False,
-    'app.update.url': 'http://localhost/app-dummy/update',
-    # Make sure GMPInstallManager won't hit the network.
-    'media.gmp-gmpopenh264.autoupdate' : False,
-    'media.gmp-manager.cert.checkAttributes' : False,
-    'media.gmp-manager.cert.requireBuiltIn' : False,
-    'media.gmp-manager.url' : 'http://localhost/media-dummy/gmpmanager',
-    'media.gmp-manager.url.override': 'http://localhost/dummy-gmp-manager.xml',
-    'media.gmp-manager.updateEnabled': False,
-    'browser.aboutHomeSnippets.updateUrl': 'https://localhost/snippet-dummy',
-    'browser.newtab.url' : 'about:blank',
-    'browser.search.update': False,
-    'browser.search.suggest.enabled' : False,
-
-    # Disable all Safe Browsing lists
-    'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads',
-    'browser.safebrowsing.malware.enabled' : False,
-    'browser.safebrowsing.phishing.enabled' : False,
-    'browser.safebrowsing.blockedURIs.enabled' : False,
-    'browser.safebrowsing.passwords.enabled' : False,
-    'browser.safebrowsing.provider.google.updateURL': 'http://localhost/safebrowsing-dummy/update',
-    'browser.safebrowsing.provider.google.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
-    'browser.safebrowsing.provider.google4.updateURL': 'http://localhost/safebrowsing4-dummy/update',
-    'browser.safebrowsing.provider.google4.gethashURL': 'http://localhost/safebrowsing4-dummy/gethash',
-    'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
-    'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update',
-    'plugins.flashBlock.enabled': False,
-    'privacy.trackingprotection.annotate_channels': False,
-    'privacy.trackingprotection.enabled': False,
-    'privacy.trackingprotection.pbmode.enabled': False,
-
-    # Disable app update
-    'app.update.enabled' : False,
-    'app.update.staging.enabled': False,
-
-    # Disable about:newtab content fetch
-    'browser.newtabpage.directory.source': 'data:application/json,{"jetpack":1}',
-
-    # Point update checks to a nonexistent local URL for fast failures.
-    'extensions.update.url' : 'http://localhost/extensions-dummy/updateURL',
-    'extensions.update.background.url': 'http://localhost/extensions-dummy/updateBackgroundURL',
-    'extensions.blocklist.url' : 'http://localhost/extensions-dummy/blocklistURL',
-    # Make sure opening about:addons won't hit the network.
-    'extensions.webservice.discoverURL' : 'http://localhost/extensions-dummy/discoveryURL',
-    'extensions.getAddons.maxResults': 0,
-
-    # Disable webapp updates.  Yes, it is supposed to be an integer.
-    'browser.webapps.checkForUpdates': 0,
-
-    # Location services
-    'geo.wifi.uri': 'http://localhost/location-dummy/locationURL',
-    'browser.search.geoip.url': 'http://localhost/location-dummy/locationURL',
-
-    # Tell the search service we are running in the US.  This also has the
-    # desired side-effect of preventing our geoip lookup.
-    'browser.search.isUS' : True,
-    'browser.search.countryCode' : 'US',
-
-    'geo.wifi.uri' : 'http://localhost/extensions-dummy/geowifiURL',
-    'geo.wifi.scan' : False,
-
-    # We don't want to hit the real Firefox Accounts server for tests.  We don't
-    # actually need a functioning FxA server, so just set it to something that
-    # resolves and accepts requests, even if they all fail.
-    'identity.fxaccounts.auth.uri': 'http://localhost/fxa-dummy/'
-}
-
-DEFAULT_FENNEC_PREFS = {
-  'browser.console.showInPanel': True,
-  'browser.firstrun.show.uidiscovery': False
-}
-
-# When launching a temporary new Firefox profile, use these preferences.
-DEFAULT_FIREFOX_PREFS = {
-    'browser.startup.homepage' : 'about:blank',
-    'startup.homepage_welcome_url' : 'about:blank',
-    'devtools.browsertoolbox.panel': 'jsdebugger',
-    'devtools.chrome.enabled' : True,
-
-    # Point the url-classifier to a nonexistent local URL for fast failures.
-    'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads',
-    'browser.safebrowsing.provider.google.gethashURL' : 'http://localhost/safebrowsing-dummy/gethash',
-    'browser.safebrowsing.provider.google.updateURL' : 'http://localhost/safebrowsing-dummy/update',
-    'browser.safebrowsing.provider.google4.gethashURL' : 'http://localhost/safebrowsing4-dummy/gethash',
-    'browser.safebrowsing.provider.google4.updateURL' : 'http://localhost/safebrowsing4-dummy/update',
-    'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
-    'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update',
-}
-
-# When launching a temporary new Thunderbird profile, use these preferences.
-# Note that these were taken from:
-# http://dxr.mozilla.org/comm-central/source/mail/test/mozmill/runtest.py
-DEFAULT_THUNDERBIRD_PREFS = {
-    # say no to slow script warnings
-    'dom.max_chrome_script_run_time': 200,
-    'dom.max_script_run_time': 0,
-    # do not ask about being the default mail client
-    'mail.shell.checkDefaultClient': False,
-    # disable non-gloda indexing daemons
-    'mail.winsearch.enable': False,
-    'mail.winsearch.firstRunDone': True,
-    'mail.spotlight.enable': False,
-    'mail.spotlight.firstRunDone': True,
-    # disable address books for undisclosed reasons
-    'ldap_2.servers.osx.position': 0,
-    'ldap_2.servers.oe.position': 0,
-    # disable the first use junk dialog
-    'mailnews.ui.junk.firstuse': False,
-    # other unknown voodoo
-    # -- dummied up local accounts to stop the account wizard
-    'mail.account.account1.server' :  "server1",
-    'mail.account.account2.identities' :  "id1",
-    'mail.account.account2.server' :  "server2",
-    'mail.accountmanager.accounts' :  "account1,account2",
-    'mail.accountmanager.defaultaccount' :  "account2",
-    'mail.accountmanager.localfoldersserver' :  "server1",
-    'mail.identity.id1.fullName' :  "Tinderbox",
-    'mail.identity.id1.smtpServer' :  "smtp1",
-    'mail.identity.id1.useremail' :  "tinderbox@invalid.com",
-    'mail.identity.id1.valid' :  True,
-    'mail.root.none-rel' :  "[ProfD]Mail",
-    'mail.root.pop3-rel' :  "[ProfD]Mail",
-    'mail.server.server1.directory-rel' :  "[ProfD]Mail/Local Folders",
-    'mail.server.server1.hostname' :  "Local Folders",
-    'mail.server.server1.name' :  "Local Folders",
-    'mail.server.server1.type' :  "none",
-    'mail.server.server1.userName' :  "nobody",
-    'mail.server.server2.check_new_mail' :  False,
-    'mail.server.server2.directory-rel' :  "[ProfD]Mail/tinderbox",
-    'mail.server.server2.download_on_biff' :  True,
-    'mail.server.server2.hostname' :  "tinderbox",
-    'mail.server.server2.login_at_startup' :  False,
-    'mail.server.server2.name' :  "tinderbox@invalid.com",
-    'mail.server.server2.type' :  "pop3",
-    'mail.server.server2.userName' :  "tinderbox",
-    'mail.smtp.defaultserver' :  "smtp1",
-    'mail.smtpserver.smtp1.hostname' :  "tinderbox",
-    'mail.smtpserver.smtp1.username' :  "tinderbox",
-    'mail.smtpservers' :  "smtp1",
-    'mail.startup.enabledMailCheckOnce' :  True,
-    'mailnews.start_page_override.mstone' :  "ignore",
-}
-
-DEFAULT_TEST_PREFS = {
-    'browser.console.showInPanel': True,
-    'browser.startup.page': 0,
-    'browser.firstrun.show.localepicker': False,
-    'browser.firstrun.show.uidiscovery': False,
-    'browser.ui.layout.tablet': 0,
-    'dom.disable_open_during_load': False,
-    'dom.experimental_forms': True,
-    'dom.forms.number': True,
-    'dom.forms.color': True,
-    'dom.max_script_run_time': 0,
-    'hangmonitor.timeout': 0,
-    'dom.max_chrome_script_run_time': 0,
-    'dom.popup_maximum': -1,
-    'dom.send_after_paint_to_content': True,
-    'dom.successive_dialog_time_limit': 0,
-    'browser.shell.checkDefaultBrowser': False,
-    'shell.checkDefaultClient': False,
-    'browser.warnOnQuit': False,
-    'accessibility.typeaheadfind.autostart': False,
-    'browser.EULA.override': True,
-    'gfx.color_management.force_srgb': True,
-    'network.manage-offline-status': False,
-    # Disable speculative connections so they aren't reported as leaking when they're hanging around.
-    'network.http.speculative-parallel-limit': 0,
-    'test.mousescroll': True,
-    # Need to client auth test be w/o any dialogs
-    'security.default_personal_cert': 'Select Automatically',
-    'network.http.prompt-temp-redirect': False,
-    'security.warn_viewing_mixed': False,
-    'extensions.defaultProviders.enabled': True,
-    'datareporting.policy.dataSubmissionPolicyBypassNotification': True,
-    'layout.css.report_errors': True,
-    'layout.css.grid.enabled': True,
-    'layout.spammy_warnings.enabled': False,
-    # Always use network provider for geolocation tests
-    # so we bypass the OSX dialog raised by the corelocation provider
-    'geo.provider.testing': True,
-    # Background thumbnails in particular cause grief, and disabling thumbnails
-    # in general can't hurt - we re-enable them when tests need them.
-    'browser.pagethumbnails.capturing_disabled': True,
-    # Indicate that the download panel has been shown once so that whichever
-    # download test runs first doesn't show the popup inconsistently.
-    'browser.download.panel.shown': True,
-    # Assume the about:newtab page's intro panels have been shown to not depend on
-    # which test runs first and happens to open about:newtab
-    'browser.newtabpage.introShown': True,
-    # Disable useragent updates.
-    'general.useragent.updates.enabled': False,
-    'media.eme.enabled': True,
-    # Don't forcibly kill content processes after a timeout
-    'dom.ipc.tabs.shutdownTimeoutSecs': 0,
-    'general.useragent.locale': "en-US",
-    'intl.locale.matchOS': "en-US",
-    'dom.indexedDB.experimental': True
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/property_parser.py
+++ /dev/null
@@ -1,111 +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/.
-
-import re
-import codecs
-
-class MalformedLocaleFileError(Exception):
-    pass
-
-def parse_file(path):
-    return parse(read_file(path), path)
-
-def read_file(path):
-    try:
-        return codecs.open( path, "r", "utf-8" ).readlines()
-    except UnicodeDecodeError, e:
-        raise MalformedLocaleFileError(
-          'Following locale file is not a valid ' +
-          'UTF-8 file: %s\n%s"' % (path, str(e)))
-
-COMMENT = re.compile(r'\s*#')
-EMPTY = re.compile(r'^\s+$')
-KEYVALUE = re.compile(r"\s*([^=:]+)(=|:)\s*(.*)")
-
-def parse(lines, path=None):
-    lines = iter(lines)
-    lineNo = 1
-    pairs = dict()
-    for line in lines:
-        if COMMENT.match(line) or EMPTY.match(line) or len(line) == 0:
-            continue
-        m = KEYVALUE.match(line)
-        if not m:
-            raise MalformedLocaleFileError(
-                  'Following locale file is not a valid .properties file: %s\n'
-                  'Line %d is incorrect:\n%s' % (path, lineNo, line))
-
-        # All spaces are strip. Spaces at the beginning are stripped
-        # by the regular expression. We have to strip spaces at the end.
-        key = m.group(1).rstrip()
-        val = m.group(3).rstrip()
-        val = val.encode('raw-unicode-escape').decode('raw-unicode-escape')
-
-        # `key` can be empty when key is only made of spaces
-        if not key:
-            raise MalformedLocaleFileError(
-                  'Following locale file is not a valid .properties file: %s\n'
-                  'Key is invalid on line %d is incorrect:\n%s' %
-                  (path, lineNo, line))
-
-        # Multiline value: keep reading lines, while lines end with backslash
-        # and strip spaces at the beginning of lines except the last line
-        # that doesn't end up with backslash, we strip all spaces for this one.
-        if val.endswith("\\"):
-            val = val[:-1]
-            try:
-                # remove spaces before/after and especially the \n at EOL
-                line = lines.next().strip()
-                while line.endswith("\\"):
-                    val += line[:-1].lstrip()
-                    line = lines.next()
-                    lineNo += 1
-                val += line.strip()
-            except StopIteration:
-                raise MalformedLocaleFileError(
-                  'Following locale file is not a valid .properties file: %s\n'
-                  'Unexpected EOF in multiline sequence at line %d:\n%s' %
-                  (path, lineNo, line))
-        # Save this new pair
-        pairs[key] = val
-        lineNo += 1
-
-    normalize_plural(path, pairs)
-    return pairs
-
-# Plural forms in properties files are defined like this:
-#   key = other form
-#   key[one] = one form
-#   key[...] = ...
-# Parse them and merge each key into one object containing all forms:
-#   key: {
-#     other: "other form",
-#     one: "one form",
-#     ...: ...
-#   }
-PLURAL_FORM = re.compile(r'^(.*)\[(zero|one|two|few|many|other)\]$')
-def normalize_plural(path, pairs):
-    for key in list(pairs.keys()):
-        m = PLURAL_FORM.match(key)
-        if not m:
-            continue
-        main_key = m.group(1)
-        plural_form = m.group(2)
-        # Allows not specifying a generic key (i.e a key without [form])
-        if not main_key in pairs:
-            pairs[main_key] = {}
-            # Ensure that we always have the [other] form
-            if not main_key + "[other]" in pairs:
-                raise MalformedLocaleFileError(
-                      'Following locale file is not a valid UTF-8 file: %s\n'
-                      'This plural form doesn\'t have a matching `%s[other]` form:\n'
-                      '%s\n'
-                      'You have to defined following key:\n%s'
-                      % (path, main_key, key, main_key))
-        # convert generic form into an object if it is still a string
-        if isinstance(pairs[main_key], unicode):
-            pairs[main_key] = {"other": pairs[main_key]}
-        # then, add this new plural form
-        pairs[main_key][plural_form] = pairs[key]
-        del pairs[key]
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/rdf.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import os
-import xml.dom.minidom
-import StringIO
-
-RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-EM_NS = "http://www.mozilla.org/2004/em-rdf#"
-
-class RDF(object):
-    def __str__(self):
-        # real files have an .encoding attribute and use it when you
-        # write() unicode into them: they read()/write() unicode and
-        # put encoded bytes in the backend file. StringIO objects
-        # read()/write() unicode and put unicode in the backing store,
-        # so we must encode the output of getvalue() to get a
-        # bytestring. (cStringIO objects are weirder: they effectively
-        # have .encoding hardwired to "ascii" and put only bytes in
-        # the backing store, so we can't use them here).
-        #
-        # The encoding= argument to dom.writexml() merely sets the XML header's
-        # encoding= attribute. It still writes unencoded unicode to the output file,
-        # so we have to encode it for real afterwards.
-        #
-        # Also see: https://bugzilla.mozilla.org/show_bug.cgi?id=567660
-
-        buf = StringIO.StringIO()
-        self.dom.writexml(buf, encoding="utf-8")
-        return buf.getvalue().encode('utf-8')
-
-class RDFUpdate(RDF):
-    def __init__(self):
-        impl = xml.dom.minidom.getDOMImplementation()
-        self.dom = impl.createDocument(RDF_NS, "RDF", None)
-        self.dom.documentElement.setAttribute("xmlns", RDF_NS)
-        self.dom.documentElement.setAttribute("xmlns:em", EM_NS)
-
-    def _make_node(self, name, value, parent):
-        elem = self.dom.createElement(name)
-        elem.appendChild(self.dom.createTextNode(value))
-        parent.appendChild(elem)
-        return elem
-
-    def add(self, manifest, update_link):
-        desc = self.dom.createElement("Description")
-        desc.setAttribute(
-            "about",
-            "urn:mozilla:extension:%s" % manifest.get("em:id")
-            )
-        self.dom.documentElement.appendChild(desc)
-
-        updates = self.dom.createElement("em:updates")
-        desc.appendChild(updates)
-
-        seq = self.dom.createElement("Seq")
-        updates.appendChild(seq)
-
-        li = self.dom.createElement("li")
-        seq.appendChild(li)
-
-        li_desc = self.dom.createElement("Description")
-        li.appendChild(li_desc)
-
-        self._make_node("em:version", manifest.get("em:version"),
-                        li_desc)
-
-        apps = manifest.dom.documentElement.getElementsByTagName(
-            "em:targetApplication"
-            )
-
-        for app in apps:
-            target_app = self.dom.createElement("em:targetApplication")
-            li_desc.appendChild(target_app)
-
-            ta_desc = self.dom.createElement("Description")
-            target_app.appendChild(ta_desc)
-
-            for name in ["em:id", "em:minVersion", "em:maxVersion"]:
-                elem = app.getElementsByTagName(name)[0]
-                self._make_node(name, elem.firstChild.nodeValue, ta_desc)
-
-            self._make_node("em:updateLink", update_link, ta_desc)
-
-class RDFManifest(RDF):
-    def __init__(self, path):
-        self.dom = xml.dom.minidom.parse(path)
-
-    def set(self, property, value):
-        elements = self.dom.documentElement.getElementsByTagName(property)
-        if not elements:
-            raise ValueError("Element with value not found: %s" % property)
-        if not elements[0].firstChild:
-            elements[0].appendChild(self.dom.createTextNode(value))
-        else:
-            elements[0].firstChild.nodeValue = value
-
-    def get(self, property, default=None):
-        elements = self.dom.documentElement.getElementsByTagName(property)
-        if not elements:
-            return default
-        return elements[0].firstChild.nodeValue
-
-    def remove(self, property):
-        elements = self.dom.documentElement.getElementsByTagName(property)
-        if not elements:
-            return True
-        else:
-            for i in elements:
-                i.parentNode.removeChild(i);
-
-        return True;
-
-def gen_manifest(template_root_dir, target_cfg, jid,
-                 update_url=None, bootstrap=True, enable_mobile=False):
-    install_rdf = os.path.join(template_root_dir, "install.rdf")
-    manifest = RDFManifest(install_rdf)
-    dom = manifest.dom
-
-    manifest.set("em:id", jid)
-    manifest.set("em:version",
-                 target_cfg.get('version', '1.0'))
-    manifest.set("em:name",
-                 target_cfg.get('title', target_cfg.get('fullName', target_cfg['name'])))
-    manifest.set("em:description",
-                 target_cfg.get("description", ""))
-    manifest.set("em:creator",
-                 target_cfg.get("author", ""))
-    manifest.set("em:bootstrap", str(bootstrap).lower())
-    # XPIs remain packed by default, but package.json can override that. The
-    # RDF format accepts "true" as True, anything else as False. We expect
-    # booleans in the .json file, not strings.
-    manifest.set("em:unpack", "true" if target_cfg.get("unpack") else "false")
-
-    if target_cfg.get('hasEmbeddedWebExtension', False):
-        elem = dom.createElement("em:hasEmbeddedWebExtension");
-        elem.appendChild(dom.createTextNode("true"))
-        dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
-
-    for translator in target_cfg.get("translators", [ ]):
-        elem = dom.createElement("em:translator");
-        elem.appendChild(dom.createTextNode(translator))
-        dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
-
-    for developer in target_cfg.get("developers", [ ]):
-        elem = dom.createElement("em:developer");
-        elem.appendChild(dom.createTextNode(developer))
-        dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
-
-    for contributor in target_cfg.get("contributors", [ ]):
-        elem = dom.createElement("em:contributor");
-        elem.appendChild(dom.createTextNode(contributor))
-        dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem)
-
-    if update_url:
-        manifest.set("em:updateURL", update_url)
-    else:
-        manifest.remove("em:updateURL")
-
-    if target_cfg.get("preferences"):
-        manifest.set("em:optionsType", "2")
-
-        # workaround until bug 971249 is fixed
-        # https://bugzilla.mozilla.org/show_bug.cgi?id=971249
-        manifest.set("em:optionsURL", "data:text/xml,<placeholder/>")
-
-        # workaround for workaround, for testing simple-prefs-regression
-        if (os.path.exists(os.path.join(template_root_dir, "options.xul"))):
-            manifest.remove("em:optionsURL")
-    else:
-        manifest.remove("em:optionsType")
-        manifest.remove("em:optionsURL")
-
-    if enable_mobile:
-        target_app = dom.createElement("em:targetApplication")
-        dom.documentElement.getElementsByTagName("Description")[0].appendChild(target_app)
-
-        ta_desc = dom.createElement("Description")
-        target_app.appendChild(ta_desc)
-
-        elem = dom.createElement("em:id")
-        elem.appendChild(dom.createTextNode("{aa3c5121-dab2-40e2-81ca-7ea25febc110}"))
-        ta_desc.appendChild(elem)
-
-        elem = dom.createElement("em:minVersion")
-        elem.appendChild(dom.createTextNode("26.0"))
-        ta_desc.appendChild(elem)
-
-        elem = dom.createElement("em:maxVersion")
-        elem.appendChild(dom.createTextNode("30.0a1"))
-        ta_desc.appendChild(elem)
-
-    if target_cfg.get("homepage"):
-        manifest.set("em:homepageURL", target_cfg.get("homepage"))
-    else:
-        manifest.remove("em:homepageURL")
-
-    return manifest
-
-if __name__ == "__main__":
-    print "Running smoke test."
-    root = os.path.join(os.path.dirname(__file__), '../../app-extension')
-    manifest = gen_manifest(root, {'name': 'test extension'},
-                            'fakeid', 'http://foo.com/update.rdf')
-    update = RDFUpdate()
-    update.add(manifest, "https://foo.com/foo.xpi")
-    exercise_str = str(manifest) + str(update)
-    for tagname in ["em:targetApplication", "em:version", "em:id"]:
-        if not len(update.dom.getElementsByTagName(tagname)):
-            raise Exception("tag does not exist: %s" % tagname)
-        if not update.dom.getElementsByTagName(tagname)[0].firstChild:
-            raise Exception("tag has no children: %s" % tagname)
-    print "Success!"
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/runner.py
+++ /dev/null
@@ -1,767 +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/.
-
-import os
-import sys
-import time
-import tempfile
-import atexit
-import shlex
-import subprocess
-import re
-import shutil
-
-import mozrunner
-from cuddlefish.prefs import DEFAULT_COMMON_PREFS
-from cuddlefish.prefs import DEFAULT_FIREFOX_PREFS
-from cuddlefish.prefs import DEFAULT_THUNDERBIRD_PREFS
-from cuddlefish.prefs import DEFAULT_FENNEC_PREFS
-from cuddlefish.prefs import DEFAULT_NO_CONNECTIONS_PREFS
-from cuddlefish.prefs import DEFAULT_TEST_PREFS
-
-# Used to remove noise from ADB output
-CLEANUP_ADB = re.compile(r'^(I|E)/(stdout|stderr|GeckoConsole)\s*\(\s*\d+\):\s*(.*)$')
-# Used to filter only messages send by `console` module
-FILTER_ONLY_CONSOLE_FROM_ADB = re.compile(r'^I/(stdout|stderr)\s*\(\s*\d+\):\s*((info|warning|error|debug): .*)$')
-
-# Used to detect the currently running test
-PARSEABLE_TEST_NAME = re.compile(r'TEST-START \| ([^\n]+)\n')
-
-# Maximum time we'll wait for tests to finish, in seconds.
-# The purpose of this timeout is to recover from infinite loops.  It should be
-# longer than the amount of time any test run takes, including those on slow
-# machines running slow (debug) versions of Firefox.
-RUN_TIMEOUT = 5400     #1.5 hours (1.5 * 60 * 60 sec)
-
-# Maximum time we'll wait for tests to emit output, in seconds.
-# The purpose of this timeout is to recover from hangs.  It should be longer
-# than the amount of time any test takes to report results.
-OUTPUT_TIMEOUT = 300   #five minutes (60 * 5 sec)
-
-def follow_file(filename):
-    """
-    Generator that yields the latest unread content from the given
-    file, or None if no new content is available.
-
-    For example:
-
-      >>> f = open('temp.txt', 'w')
-      >>> f.write('hello')
-      >>> f.flush()
-      >>> tail = follow_file('temp.txt')
-      >>> tail.next()
-      'hello'
-      >>> tail.next() is None
-      True
-      >>> f.write('there')
-      >>> f.flush()
-      >>> tail.next()
-      'there'
-      >>> f.close()
-      >>> os.remove('temp.txt')
-    """
-
-    last_pos = 0
-    last_size = 0
-    while True:
-        newstuff = None
-        if os.path.exists(filename):
-            size = os.stat(filename).st_size
-            if size > last_size:
-                last_size = size
-                f = open(filename, 'r')
-                f.seek(last_pos)
-                newstuff = f.read()
-                last_pos = f.tell()
-                f.close()
-        yield newstuff
-
-# subprocess.check_output only appeared in python2.7, so this code is taken
-# from python source code for compatibility with py2.5/2.6
-class CalledProcessError(Exception):
-    def __init__(self, returncode, cmd, output=None):
-        self.returncode = returncode
-        self.cmd = cmd
-        self.output = output
-    def __str__(self):
-        return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
-
-def check_output(*popenargs, **kwargs):
-    if 'stdout' in kwargs:
-        raise ValueError('stdout argument not allowed, it will be overridden.')
-    process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
-    output, unused_err = process.communicate()
-    retcode = process.poll()
-    if retcode:
-        cmd = kwargs.get("args")
-        if cmd is None:
-            cmd = popenargs[0]
-        raise CalledProcessError(retcode, cmd, output=output)
-    return output
-
-
-class FennecProfile(mozrunner.Profile):
-    preferences = {}
-    names = ['fennec']
-
-FENNEC_REMOTE_PATH = '/mnt/sdcard/jetpack-profile'
-
-class RemoteFennecRunner(mozrunner.Runner):
-    profile_class = FennecProfile
-
-    names = ['fennec']
-
-    _INTENT_PREFIX = 'org.mozilla.'
-
-    _adb_path = None
-
-    def __init__(self, binary=None, **kwargs):
-        # Check that we have a binary set
-        if not binary:
-            raise ValueError("You have to define `--binary` option set to the "
-                            "path to your ADB executable.")
-        # Ensure that binary refer to a valid ADB executable
-        output = subprocess.Popen([binary], stdout=subprocess.PIPE,
-                                  stderr=subprocess.PIPE).communicate()
-        output = "".join(output)
-        if not ("Android Debug Bridge" in output):
-            raise ValueError("`--binary` option should be the path to your "
-                            "ADB executable.")
-        self.binary = binary
-
-        mobile_app_name = kwargs['cmdargs'][0]
-        self.profile = kwargs['profile']
-        self._adb_path = binary
-
-        # This pref has to be set to `false` otherwise, we do not receive
-        # output of adb commands!
-        subprocess.call([self._adb_path, "shell",
-                        "setprop log.redirect-stdio false"])
-
-        # Android apps are launched by their "intent" name,
-        # Automatically detect already installed firefox by using `pm` program
-        # or use name given as cfx `--mobile-app` argument.
-        intents = self.getIntentNames()
-        if not intents:
-            raise ValueError("Unable to find any Firefox "
-                             "application on your device.")
-        elif mobile_app_name:
-            if not mobile_app_name in intents:
-                raise ValueError("Unable to find Firefox application "
-                                 "with intent name '%s'\n"
-                                 "Available ones are: %s" %
-                                 (mobile_app_name, ", ".join(intents)))
-            self._intent_name = self._INTENT_PREFIX + mobile_app_name
-        else:
-            if "firefox" in intents:
-                self._intent_name = self._INTENT_PREFIX + "firefox"
-            elif "firefox_beta" in intents:
-                self._intent_name = self._INTENT_PREFIX + "firefox_beta"
-            elif "firefox_nightly" in intents:
-                self._intent_name = self._INTENT_PREFIX + "firefox_nightly"
-            else:
-                self._intent_name = self._INTENT_PREFIX + intents[0]
-
-        print "Launching mobile application with intent name " + self._intent_name
-
-        # First try to kill firefox if it is already running
-        pid = self.getProcessPID(self._intent_name)
-        if pid != None:
-            print "Killing running Firefox instance ..."
-            subprocess.call([self._adb_path, "shell",
-                             "am force-stop " + self._intent_name])
-            time.sleep(7)
-            # It appears recently that the PID still exists even after
-            # Fennec closes, so removing this error still allows the tests
-            # to pass as the new Fennec instance is able to start.
-            # Leaving error in but commented out for now.
-            #
-            #if self.getProcessPID(self._intent_name) != None:
-            #    raise Exception("Unable to automatically kill running Firefox" +
-            #                    " instance. Please close it manually before " +
-            #                    "executing cfx.")
-
-        print "Pushing the addon to your device"
-
-        # Create a clean empty profile on the sd card
-        subprocess.call([self._adb_path, "shell", "rm -r " + FENNEC_REMOTE_PATH])
-        subprocess.call([self._adb_path, "shell", "mkdir " + FENNEC_REMOTE_PATH])
-
-        # Push the profile folder created by mozrunner to the device
-        # (we can't simply use `adb push` as it doesn't copy empty folders)
-        localDir = self.profile.profile
-        remoteDir = FENNEC_REMOTE_PATH
-        for root, dirs, files in os.walk(localDir, followlinks='true'):
-            relRoot = os.path.relpath(root, localDir)
-            # Note about os.path usage below:
-            # Local files may be using Windows `\` separators but
-            # remote are always `/`, so we need to convert local ones to `/`
-            for file in files:
-                localFile = os.path.join(root, file)
-                remoteFile = remoteDir.replace("/", os.sep)
-                if relRoot != ".":
-                    remoteFile = os.path.join(remoteFile, relRoot)
-                remoteFile = os.path.join(remoteFile, file)
-                remoteFile = "/".join(remoteFile.split(os.sep))
-                subprocess.Popen([self._adb_path, "push", localFile, remoteFile],
-                                 stderr=subprocess.PIPE).wait()
-            for dir in dirs:
-                targetDir = remoteDir.replace("/", os.sep)
-                if relRoot != ".":
-                    targetDir = os.path.join(targetDir, relRoot)
-                targetDir = os.path.join(targetDir, dir)
-                targetDir = "/".join(targetDir.split(os.sep))
-                # `-p` option is not supported on all devices!
-                subprocess.call([self._adb_path, "shell", "mkdir " + targetDir])
-
-    @property
-    def command(self):
-        """Returns the command list to run."""
-        return [self._adb_path,
-            "shell",
-            "am start " +
-                "-a android.activity.MAIN " +
-                "-n " + self._intent_name + "/" + self._intent_name + ".App " +
-                "--es args \"-profile " + FENNEC_REMOTE_PATH + "\""
-        ]
-
-    def start(self):
-        subprocess.call(self.command)
-
-    def getProcessPID(self, processName):
-        p = subprocess.Popen([self._adb_path, "shell", "ps"],
-                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        line = p.stdout.readline()
-        while line:
-            columns = line.split()
-            pid = columns[1]
-            name = columns[-1]
-            line = p.stdout.readline()
-            if processName in name:
-                return pid
-        return None
-
-    def getIntentNames(self):
-        p = subprocess.Popen([self._adb_path, "shell", "pm list packages"],
-                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        names = []
-        for line in p.stdout.readlines():
-            line = re.sub("(^package:)|\s", "", line)
-            if self._INTENT_PREFIX in line:
-                names.append(line.replace(self._INTENT_PREFIX, ""))
-        return names
-
-
-class XulrunnerAppProfile(mozrunner.Profile):
-    preferences = {}
-    names = []
-
-class XulrunnerAppRunner(mozrunner.Runner):
-    """
-    Runner for any XULRunner app. Can use a Firefox binary in XULRunner
-    mode to execute the app, or can use XULRunner itself. Expects the
-    app's application.ini to be passed in as one of the items in
-    'cmdargs' in the constructor.
-
-    This class relies a lot on the particulars of mozrunner.Runner's
-    implementation, and does some unfortunate acrobatics to get around
-    some of the class' limitations/assumptions.
-    """
-
-    profile_class = XulrunnerAppProfile
-
-    # This is a default, and will be overridden in the instance if
-    # Firefox is used in XULRunner mode.
-    names = ['xulrunner']
-
-    # Default location of XULRunner on OS X.
-    __DARWIN_PATH = "/Library/Frameworks/XUL.framework/xulrunner-bin"
-    __LINUX_PATH  = "/usr/bin/xulrunner"
-
-    # What our application.ini's path looks like if it's part of
-    # an "installed" XULRunner app on OS X.
-    __DARWIN_APP_INI_SUFFIX = '.app/Contents/Resources/application.ini'
-
-    def __init__(self, binary=None, **kwargs):
-        if sys.platform == 'darwin' and binary and binary.endswith('.app'):
-            # Assume it's a Firefox app dir.
-            binary = os.path.join(binary, 'Contents/MacOS/firefox-bin')
-
-        self.__app_ini = None
-        self.__real_binary = binary
-
-        mozrunner.Runner.__init__(self, **kwargs)
-
-        # See if we're using a genuine xulrunner-bin from the XULRunner SDK,
-        # or if we're being asked to use Firefox in XULRunner mode.
-        self.__is_xulrunner_sdk = 'xulrunner' in self.binary
-
-        if sys.platform == 'linux2' and not self.env.get('LD_LIBRARY_PATH'):
-            self.env['LD_LIBRARY_PATH'] = os.path.dirname(self.binary)
-
-        newargs = []
-        for item in self.cmdargs:
-            if 'application.ini' in item:
-                self.__app_ini = item
-            else:
-                newargs.append(item)
-        self.cmdargs = newargs
-
-        if not self.__app_ini:
-            raise ValueError('application.ini not found in cmdargs')
-        if not os.path.exists(self.__app_ini):
-            raise ValueError("file does not exist: '%s'" % self.__app_ini)
-
-        if (sys.platform == 'darwin' and
-            self.binary == self.__DARWIN_PATH and
-            self.__app_ini.endswith(self.__DARWIN_APP_INI_SUFFIX)):
-            # If the application.ini is in an app bundle, then
-            # it could be inside an "installed" XULRunner app.
-            # If this is the case, use the app's actual
-            # binary instead of the XUL framework's, so we get
-            # a proper app icon, etc.
-            new_binary = '/'.join(self.__app_ini.split('/')[:-2] +
-                                  ['MacOS', 'xulrunner'])
-            if os.path.exists(new_binary):
-                self.binary = new_binary
-
-    @property
-    def command(self):
-        """Returns the command list to run."""
-
-        if self.__is_xulrunner_sdk:
-            return [self.binary, self.__app_ini, '-profile',
-                    self.profile.profile]
-        else:
-            return [self.binary, '-app', self.__app_ini, '-profile',
-                    self.profile.profile]
-
-    def __find_xulrunner_binary(self):
-        if sys.platform == 'darwin':
-            if os.path.exists(self.__DARWIN_PATH):
-                return self.__DARWIN_PATH
-        if sys.platform == 'linux2':
-            if os.path.exists(self.__LINUX_PATH):
-                return self.__LINUX_PATH
-        return None
-
-    def find_binary(self):
-        # This gets called by the superclass constructor. It will
-        # always get called, even if a binary was passed into the
-        # constructor, because we want to have full control over
-        # what the exact setting of self.binary is.
-
-        if not self.__real_binary:
-            self.__real_binary = self.__find_xulrunner_binary()
-            if not self.__real_binary:
-                dummy_profile = {}
-                runner = mozrunner.FirefoxRunner(profile=dummy_profile)
-                self.__real_binary = runner.find_binary()
-                self.names = runner.names
-        return self.__real_binary
-
-def set_overloaded_modules(env_root, app_type, addon_id, preferences, overloads):
-    # win32 file scheme needs 3 slashes
-    desktop_file_scheme = "file://"
-    if not env_root.startswith("/"):
-      desktop_file_scheme = desktop_file_scheme + "/"
-
-    pref_prefix = "extensions.modules." + addon_id + ".path"
-
-    # Set preferences that will map require prefix to a given path
-    for name, path in overloads.items():
-        if len(name) == 0:
-            prefName = pref_prefix
-        else:
-            prefName = pref_prefix + "." + name
-        if app_type == "fennec-on-device":
-            # For testing on device, we have to copy overloaded files from fs
-            # to the device and use device path instead of local fs path.
-            # Actual copy of files if done after the call to Profile constructor
-            preferences[prefName] = "file://" + \
-                FENNEC_REMOTE_PATH + "/overloads/" + name
-        else:
-            preferences[prefName] = desktop_file_scheme + \
-                path.replace("\\", "/") + "/"
-
-def run_app(harness_root_dir, manifest_rdf, harness_options,
-            app_type, binary=None, profiledir=None, verbose=False,
-            parseable=False, enforce_timeouts=False,
-            logfile=None, addons=None, args=None, extra_environment={},
-            norun=None, noquit=None,
-            used_files=None, enable_mobile=False,
-            mobile_app_name=None,
-            env_root=None,
-            is_running_tests=False,
-            overload_modules=False,
-            bundle_sdk=True,
-            pkgdir="",
-            enable_e10s=False,
-            no_connections=False):
-    if binary:
-        binary = os.path.expanduser(binary)
-
-    if addons is None:
-        addons = []
-    else:
-        addons = list(addons)
-
-    cmdargs = []
-    preferences = dict(DEFAULT_COMMON_PREFS)
-
-    if is_running_tests:
-      preferences.update(DEFAULT_TEST_PREFS)
-
-    if no_connections:
-      preferences.update(DEFAULT_NO_CONNECTIONS_PREFS)
-
-    if enable_e10s:
-        preferences['browser.tabs.remote.autostart'] = True
-    else:
-        preferences['browser.tabs.remote.autostart'] = False
-        preferences['browser.tabs.remote.autostart.1'] = False
-        preferences['browser.tabs.remote.autostart.2'] = False
-
-    # For now, only allow running on Mobile with --force-mobile argument
-    if app_type in ["fennec-on-device"] and not enable_mobile:
-        print """
-  WARNING: Firefox Mobile support is still experimental.
-  If you would like to run an addon on this platform, use --force-mobile flag:
-
-    cfx --force-mobile"""
-        return 0
-
-    if app_type == "fennec-on-device":
-        profile_class = FennecProfile
-        preferences.update(DEFAULT_FENNEC_PREFS)
-        runner_class = RemoteFennecRunner
-        # We pass the intent name through command arguments
-        cmdargs.append(mobile_app_name)
-    elif app_type == "xulrunner":
-        profile_class = XulrunnerAppProfile
-        runner_class = XulrunnerAppRunner
-        cmdargs.append(os.path.join(harness_root_dir, 'application.ini'))
-    elif app_type == "firefox":
-        profile_class = mozrunner.FirefoxProfile
-        preferences.update(DEFAULT_FIREFOX_PREFS)
-        runner_class = mozrunner.FirefoxRunner
-    elif app_type == "thunderbird":
-        profile_class = mozrunner.ThunderbirdProfile
-        preferences.update(DEFAULT_THUNDERBIRD_PREFS)
-        runner_class = mozrunner.ThunderbirdRunner
-    else:
-        raise ValueError("Unknown app: %s" % app_type)
-    if sys.platform == 'darwin' and app_type != 'xulrunner':
-        cmdargs.append('-foreground')
-
-    if args:
-        cmdargs.extend(shlex.split(args))
-
-    # TODO: handle logs on remote device
-    if app_type != "fennec-on-device":
-        # tempfile.gettempdir() was constant, preventing two simultaneous "cfx
-        # run"/"cfx test" on the same host. On unix it points at /tmp (which is
-        # world-writeable), enabling a symlink attack (e.g. imagine some bad guy
-        # does 'ln -s ~/.ssh/id_rsa /tmp/harness_result'). NamedTemporaryFile
-        # gives us a unique filename that fixes both problems. We leave the
-        # (0-byte) file in place until the browser-side code starts writing to
-        # it, otherwise the symlink attack becomes possible again.
-        fileno,resultfile = tempfile.mkstemp(prefix="harness-result-")
-        os.close(fileno)
-        harness_options['resultFile'] = resultfile
-
-    def maybe_remove_logfile():
-        if os.path.exists(logfile):
-            os.remove(logfile)
-
-    logfile_tail = None
-
-    # We always buffer output through a logfile for two reasons:
-    # 1. On Windows, it's the only way to print console output to stdout/err.
-    # 2. It enables us to keep track of the last time output was emitted,
-    #    so we can raise an exception if the test runner hangs.
-    if not logfile:
-        fileno,logfile = tempfile.mkstemp(prefix="harness-log-")
-        os.close(fileno)
-    logfile_tail = follow_file(logfile)
-    atexit.register(maybe_remove_logfile)
-
-    logfile = os.path.abspath(os.path.expanduser(logfile))
-    maybe_remove_logfile()
-
-    env = {}
-    env.update(os.environ)
-    if no_connections:
-      env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
-    env['MOZ_NO_REMOTE'] = '1'
-    env['XPCOM_DEBUG_BREAK'] = 'stack'
-    env.update(extra_environment)
-    if norun:
-        cmdargs.append("-no-remote")
-
-    # Create the addon XPI so mozrunner will copy it to the profile it creates.
-    # We delete it below after getting mozrunner to create the profile.
-    from cuddlefish.xpi import build_xpi
-    xpi_path = tempfile.mktemp(suffix='cfx-tmp.xpi')
-    build_xpi(template_root_dir=harness_root_dir,
-              manifest=manifest_rdf,
-              xpi_path=xpi_path,
-              harness_options=harness_options,
-              limit_to=used_files,
-              bundle_sdk=bundle_sdk,
-              pkgdir=pkgdir)
-    addons.append(xpi_path)
-
-    starttime = last_output_time = time.time()
-
-    # Redirect runner output to a file so we can catch output not generated
-    # by us.
-    # In theory, we could do this using simple redirection on all platforms
-    # other than Windows, but this way we only have a single codepath to
-    # maintain.
-    fileno,outfile = tempfile.mkstemp(prefix="harness-stdout-")
-    os.close(fileno)
-    outfile_tail = follow_file(outfile)
-    def maybe_remove_outfile():
-        if os.path.exists(outfile):
-            try:
-                os.remove(outfile)
-            except Exception, e:
-                print "Error Cleaning up: " + str(e)
-    atexit.register(maybe_remove_outfile)
-    outf = open(outfile, "w")
-    popen_kwargs = { 'stdout': outf, 'stderr': outf}
-
-    profile = None
-
-    if app_type == "fennec-on-device":
-        # Install a special addon when we run firefox on mobile device
-        # in order to be able to kill it
-        mydir = os.path.dirname(os.path.abspath(__file__))
-        addon_dir = os.path.join(mydir, "mobile-utils")
-        addons.append(addon_dir)
-
-    # Overload addon-specific commonjs modules path with lib/ folder
-    overloads = dict()
-    if overload_modules:
-        overloads[""] = os.path.join(env_root, "lib")
-
-    # Overload tests/ mapping with test/ folder, only when running test
-    if is_running_tests:
-        overloads["tests"] = os.path.join(env_root, "test")
-
-    set_overloaded_modules(env_root, app_type, harness_options["jetpackID"], \
-                           preferences, overloads)
-
-    # the XPI file is copied into the profile here
-    profile = profile_class(addons=addons,
-                            profile=profiledir,
-                            preferences=preferences)
-
-    # Delete the temporary xpi file
-    os.remove(xpi_path)
-
-    # Copy overloaded files registered in set_overloaded_modules
-    # For testing on device, we have to copy overloaded files from fs
-    # to the device and use device path instead of local fs path.
-    # (has to be done after the call to profile_class() which eventualy creates
-    #  profile folder)
-    if app_type == "fennec-on-device":
-        profile_path = profile.profile
-        for name, path in overloads.items():
-            shutil.copytree(path, \
-                os.path.join(profile_path, "overloads", name))
-
-    runner = runner_class(profile=profile,
-                          binary=binary,
-                          env=env,
-                          cmdargs=cmdargs,
-                          kp_kwargs=popen_kwargs)
-
-    sys.stdout.flush(); sys.stderr.flush()
-
-    if app_type == "fennec-on-device":
-        if not enable_mobile:
-            print >>sys.stderr, """
-  WARNING: Firefox Mobile support is still experimental.
-  If you would like to run an addon on this platform, use --force-mobile flag:
-
-    cfx --force-mobile"""
-            return 0
-
-        # In case of mobile device, we need to get stdio from `adb logcat` cmd:
-
-        # First flush logs in order to avoid catching previous ones
-        subprocess.call([binary, "logcat", "-c"])
-
-        # Launch adb command
-        runner.start()
-
-        # We can immediatly remove temporary profile folder
-        # as it has been uploaded to the device
-        profile.cleanup()
-        # We are not going to use the output log file
-        outf.close()
-
-        # Then we simply display stdout of `adb logcat`
-        p = subprocess.Popen([binary, "logcat", "stderr:V stdout:V GeckoConsole:V *:S"], stdout=subprocess.PIPE)
-        while True:
-            line = p.stdout.readline()
-            if line == '':
-                break
-            # mobile-utils addon contains an application quit event observer
-            # that will print this string:
-            if "APPLICATION-QUIT" in line:
-                break
-
-            if verbose:
-                # if --verbose is given, we display everything:
-                # All JS Console messages, stdout and stderr.
-                m = CLEANUP_ADB.match(line)
-                if not m:
-                    print line.rstrip()
-                    continue
-                print m.group(3)
-            else:
-                # Otherwise, display addons messages dispatched through
-                # console.[info, log, debug, warning, error](msg)
-                m = FILTER_ONLY_CONSOLE_FROM_ADB.match(line)
-                if m:
-                    print m.group(2)
-
-        print >>sys.stderr, "Program terminated successfully."
-        return 0
-
-
-    print >>sys.stderr, "Using binary at '%s'." % runner.binary
-
-    # Ensure cfx is being used with Firefox 4.0+.
-    # TODO: instead of dying when Firefox is < 4, warn when Firefox is outside
-    # the minVersion/maxVersion boundaries.
-    version_output = check_output(runner.command + ["-v"])
-    # Note: this regex doesn't handle all valid versions in the Toolkit Version
-    # Format <https://developer.mozilla.org/en/Toolkit_version_format>, just the
-    # common subset that we expect Mozilla apps to use.
-    mo = re.search(r"Mozilla (Firefox|Iceweasel|Fennec)\b[^ ]* ((\d+)\.\S*)",
-                   version_output)
-    if not mo:
-        # cfx may be used with Thunderbird, SeaMonkey or an exotic Firefox
-        # version.
-        print """
-  WARNING: cannot determine Firefox version; please ensure you are running
-  a Mozilla application equivalent to Firefox 4.0 or greater.
-  """
-    elif mo.group(1) == "Fennec":
-        # For now, only allow running on Mobile with --force-mobile argument
-        if not enable_mobile:
-            print """
-  WARNING: Firefox Mobile support is still experimental.
-  If you would like to run an addon on this platform, use --force-mobile flag:
-
-    cfx --force-mobile"""
-            return
-    else:
-        version = mo.group(3)
-        if int(version) < 4:
-            print """
-  cfx requires Firefox 4 or greater and is unable to find a compatible
-  binary. Please install a newer version of Firefox or provide the path to
-  your existing compatible version with the --binary flag:
-
-    cfx --binary=PATH_TO_FIREFOX_BINARY"""
-            return
-
-        # Set the appropriate extensions.checkCompatibility preference to false,
-        # so the tests run even if the SDK is not marked as compatible with the
-        # version of Firefox on which they are running, and we don't have to
-        # ensure we update the maxVersion before the version of Firefox changes
-        # every six weeks.
-        #
-        # The regex we use here is effectively the same as BRANCH_REGEX from
-        # /toolkit/mozapps/extensions/content/extensions.js, which toolkit apps
-        # use to determine whether or not to load an incompatible addon.
-        #
-        br = re.search(r"^([^\.]+\.[0-9]+[a-z]*).*", mo.group(2), re.I)
-        if br:
-            prefname = 'extensions.checkCompatibility.' + br.group(1)
-            profile.preferences[prefname] = False
-            # Calling profile.set_preferences here duplicates the list of prefs
-            # in prefs.js, since the profile calls self.set_preferences in its
-            # constructor, but that is ok, because it doesn't change the set of
-            # preferences that are ultimately registered in Firefox.
-            profile.set_preferences(profile.preferences)
-
-    print >>sys.stderr, "Using profile at '%s'." % profile.profile
-    sys.stderr.flush()
-
-    if norun:
-        print "To launch the application, enter the following command:"
-        print " ".join(runner.command) + " " + (" ".join(runner.cmdargs))
-        return 0
-
-    runner.start()
-
-    done = False
-    result = None
-    test_name = "Jetpack startup"
-
-    def Timeout(message, test_name, parseable):
-        if parseable:
-            sys.stderr.write("TEST-UNEXPECTED-FAIL | %s | %s\n" % (test_name, message))
-            sys.stderr.flush()
-        return Exception(message)
-
-    try:
-        while not done:
-            time.sleep(0.05)
-            for tail in (logfile_tail, outfile_tail):
-                if tail:
-                    new_chars = tail.next()
-                    if new_chars:
-                        last_output_time = time.time()
-                        sys.stderr.write(new_chars)
-                        sys.stderr.flush()
-                        if is_running_tests and parseable:
-                            match = PARSEABLE_TEST_NAME.search(new_chars)
-                            if match:
-                                test_name = match.group(1)
-            if os.path.exists(resultfile):
-                result = open(resultfile).read()
-                if result:
-                    if result in ['OK', 'FAIL']:
-                        done = True
-                    else:
-                        sys.stderr.write("Hrm, resultfile (%s) contained something weird (%d bytes)\n" % (resultfile, len(result)))
-                        sys.stderr.write("'"+result+"'\n")
-            if enforce_timeouts:
-                if time.time() - last_output_time > OUTPUT_TIMEOUT:
-                    raise Timeout("Test output exceeded timeout (%ds)." %
-                                  OUTPUT_TIMEOUT, test_name, parseable)
-                if time.time() - starttime > RUN_TIMEOUT:
-                    raise Timeout("Test run exceeded timeout (%ds)." %
-                                  RUN_TIMEOUT, test_name, parseable)
-    except:
-        if not noquit:
-            runner.stop()
-        raise
-    else:
-        runner.wait(10)
-        # double kill - hack for bugs 942111, 1006043..
-        try:
-            runner.stop()
-        except:
-            pass
-    finally:
-        outf.close()
-        if profile:
-            profile.cleanup()
-
-    print >>sys.stderr, "Total time: %f seconds" % (time.time() - starttime)
-
-    if result == 'OK':
-        print >>sys.stderr, "Program terminated successfully."
-        return 0
-    else:
-        print >>sys.stderr, "Program terminated unsuccessfully."
-        return -1
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/templates.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#Template used by test-main.js
-TEST_MAIN_JS = '''\
-var main = require("./main");
-
-exports["test main"] = function(assert) {
-  assert.pass("Unit test running!");
-};
-
-exports["test main async"] = function(assert, done) {
-  assert.pass("async Unit test running!");
-  done();
-};
-
-require("sdk/test").run(exports);
-'''
-
-#Template used by package.json
-PACKAGE_JSON = '''\
-{
-  "name": "%(name)s",
-  "title": "%(title)s",
-  "id": "%(id)s",
-  "description": "a basic add-on",
-  "author": "",
-  "license": "MPL-2.0",
-  "version": "0.1"
-}
-'''
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/__init__.py
+++ /dev/null
@@ -1,52 +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/.
-
-import os
-import unittest
-import doctest
-import glob
-
-env_root = os.environ['CUDDLEFISH_ROOT']
-
-def get_tests():
-    import cuddlefish
-    import cuddlefish.tests
-
-    tests = []
-    packages = [cuddlefish, cuddlefish.tests]
-    for package in packages:
-        path = os.path.abspath(package.__path__[0])
-        pynames = glob.glob(os.path.join(path, '*.py'))
-        for filename in pynames:
-            basename = os.path.basename(filename)
-            module_name = os.path.splitext(basename)[0]
-            full_name = "%s.%s" % (package.__name__, module_name)
-            module = __import__(full_name, fromlist=[package.__name__])
-
-            loader = unittest.TestLoader()
-            suite = loader.loadTestsFromModule(module)
-            for test in suite:
-                tests.append(test)
-
-            finder = doctest.DocTestFinder()
-            doctests = finder.find(module)
-            for test in doctests:
-                if len(test.examples) > 0:
-                    tests.append(doctest.DocTestCase(test))
-
-    return tests
-
-def run(verbose=False):
-    if verbose:
-        verbosity = 2
-    else:
-        verbosity = 1
-
-    tests = get_tests()
-    suite = unittest.TestSuite(tests)
-    runner = unittest.TextTestRunner(verbosity=verbosity)
-    return runner.run(suite)
-
-if __name__ == '__main__':
-    run()
deleted file mode 100644
deleted file mode 100644
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/lib/main.js
+++ /dev/null
@@ -1,4 +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/. */
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "loader": "lib/main.js",
-  "icon": "explicit-icon.png",
-  "icon64": "explicit-icon64.png"
-}
deleted file mode 100644
deleted file mode 100644
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/lib/main.js
+++ /dev/null
@@ -1,4 +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/. */
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/lib/main.js
+++ /dev/null
@@ -1,4 +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/. */
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/lib/bar-loader.js
+++ /dev/null
@@ -1,4 +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/. */
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/bar-loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/lib/foo-loader.js
+++ /dev/null
@@ -1,4 +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/. */
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "loader": "lib/foo-loader.js",
-  "dependencies": ["bar"]
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/docs/main.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-minimal docs
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("minimal");
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "jspath-one",
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension."
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/doc/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/lib/foo-loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/foo-loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/test/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/docs/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/lib/foo-loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/foo-loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/tests/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/doc/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/foo.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "lib/loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/test/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/package.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/doc/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/foo.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "loader": "loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/test/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/foo.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/doc/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "directories": { "lib": "./alt-lib" },
-  "loader": "alt-lib/loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/test/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/foo.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/loader.js
+++ /dev/null
@@ -1,5 +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/. */
-
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/doc/foo.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-I am documentation for foo.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "lib": "./alt2-lib",
-  "loader": "alt2-lib/loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/test/test-foo.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.testThing = function(test) {
-  test.assertEqual(2, 1 + 1);
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/docs/main.md
+++ /dev/null
@@ -1,5 +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/. -->
-
-minimal docs
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("minimal");
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "extra-options",
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension.",
-  "loader": "lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "empty",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-    "title": "empty",
-    "id": "jid1-80fr8b6qeRlQSQ",
-    "unpack": false,
-    "description": "test unpack= support"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "empty",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-    "title": "empty",
-    "id": "jid1-80fr8b6qeRlQSQ",
-    "unpack": true,
-    "description": "test unpack= support"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "name": "empty",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-    "title": "empty",
-    "id": "jid1-80fr8b6qeRlQSQ",
-    "description": "test unpack= support"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "name": "empty",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-    "fullName": "a long fullName",
-    "id": "jid1-80123",
-    "description": "test addon name fallback to 'fullName' key"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "name": "a long none",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-
-    "id": "jid1-80123",
-    "description": "test addon name falls back all the way to the 'name' key"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "name": "empty",
-    "license": "MPL-2.0",
-    "author": "",
-    "version": "0.1",
-    "title": "a long title",
-    "id": "jid1-80123",
-    "description": "test addon name comes from the 'title' key"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar-e10s-adapter.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/. */
-
-if (this.sendMessage) {
-} else {
-  require('bar');
-
-  exports.register = function(process) {
-  };
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar.js
+++ /dev/null
@@ -1,5 +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/. */
-
-require('chrome');
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/foo.js
+++ /dev/null
@@ -1,5 +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/. */
-
-require('bar');
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/package.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/lib/main.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = "'main' mainly reigns in main(.js)";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "five",
-  "main": "./lib/main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/lib/misc.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = 42;
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{ "name": "four-a",
-  "directories": {"lib": "lib"},
-  "main": "./topfiles/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/topfiles/main.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = 42;
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/lib/main.js
+++ /dev/null
@@ -1,5 +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 a = require("four-a");
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "four",
-  "main": "main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/main.js
+++ /dev/null
@@ -1,9 +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 panel = require("sdk/panel");
-var two = require("two.js");
-var a = require("./two");
-var b = require("sdk/tabs.js");
-var c = require("./subdir/three");
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/subdir/three.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.foo = 1;
-var main = require("../main");
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/two.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-// this ought to find our sibling, not packages/development-mode/lib/main.js
-var main = require("main");
-exports.foo = 1;
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{ "name": "one",
-  "id": "jid1@jetpack",
-  "main": "main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/data/text.data
+++ /dev/null
@@ -1,1 +0,0 @@
-data
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var self = require("sdk/self"); // trigger inclusion of data
-exports.main = function () { console.log("main"); };
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/unused.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.unused = "just pretend I'm not here";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "name": "seven", 
-    "id": "jid7"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/lib/unused.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.unused = "I am.";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "six",
-  "main": "./unreachable"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/unreachable.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = "I am outside lib/ and cannot be reached, yet";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = 42;
-require("./subdir/subfile");
-require("sdk/self"); // trigger inclusion of our data/ directory
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/subdir/subfile.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = "I should be included in a subdir";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/unused.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = "unused, linker should not include me in the XPI";
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/locale/fr-FR.properties
+++ /dev/null
@@ -1,5 +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/.
-
-Yes= Oui
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "three-a",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/lib/main.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = 42;
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/locale/fr-FR.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-No= Non
-one= un
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "three-b",
-  "main": "./lib/main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/main.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.main = 42;
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/sub/foo.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.foo = "you found me down here";
-
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/locale/fr-FR.properties
+++ /dev/null
@@ -1,9 +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/.
-
-No= Nein
-What?= Quoi?
-plural=other
-plural[one]=one
-uft8_value=é
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "three-c",
-  "main": "lib/main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/msg.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-hello world
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/subdir/submsg.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-hello subdir
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var a = require("three-a");
-var b = require("three-b");
-var c = require("three-c");
-var c3 = require("three-c/sub/foo");
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{ "name": "three",
-  "main": "main"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/nontest.js
+++ /dev/null
@@ -1,5 +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/. */
-
-// dummy
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-one.js
+++ /dev/null
@@ -1,5 +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/. */
-
-// dummy
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-two.js
+++ /dev/null
@@ -1,5 +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/. */
-
-// dummy
deleted file mode 100644
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/ignore_me
+++ /dev/null
@@ -1,3 +0,0 @@
-The docs processor should tolerate (by ignoring) random non-.js files in lib
-directories, such as those left around by editors, version-control systems,
-or OS metadata like .DS_Store . This file exercises that tolerance.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("1 + 1 =", require("bar-module").add(1, 1));
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/surprise.js/ignore_me_too
+++ /dev/null
@@ -1,2 +0,0 @@
-The docs processor should also ignore directories named *.js, and their
-contents.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension.",
-  "keywords": ["potato"],
-  "version": "1.0",
-  "dependencies": ["addon-sdk", "barbeque"]
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("1 + 1 =", require("bar-module").add(1, 1));
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "anteater",
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension.",
-  "keywords": ["potato"],
-  "version": "1.0",
-  "dependencies": ["addon-sdk", "barbeque"]
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/lib/loader.js
+++ /dev/null
@@ -1,7 +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 module will be imported by the XPCOM harness/boostrapper
-// via Components.utils.import() and is responsible for creating a
-// CommonJS module loader.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "description": "A foundational package that provides a CommonJS module loader implementation.",
-  "keywords": ["potato", "jetpack-low-level"],
-  "loader": "lib/loader.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/lib/bar-module.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.add = function add(a, b) {
-  return a + b;
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "keywords": ["potato", "jetpack-low-level"],
-  "description": "A package used by 'aardvark' as a library."
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("minimal");
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension."
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/docs/third_party.md
+++ /dev/null
@@ -1,1 +0,0 @@
-hello, I'm a third party.
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/lib/third-party.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.main = function(options, callbacks) {
-  console.log("1 + 1 =", require("bar-module").add(1, 1));
-  callbacks.quit();
-};
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "author": "Jon Smith",
-  "description": "A package w/ a main module; can be built into an extension.",
-  "keywords": ["potato"],
-  "version": "1.0",
-  "dependencies": ["addon-sdk", "barbeque"]
-}
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/xpi-template/components/harness.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// This file contains XPCOM code that bootstraps an SDK-based add-on
-// by loading its harness-options.json, registering all its resource
-// directories, executing its loader, and then executing its program's
-// main() function.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py
+++ /dev/null
@@ -1,211 +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/.
-
-import os, unittest, shutil
-import zipfile
-from StringIO import StringIO
-from cuddlefish import initializer
-from cuddlefish.templates import TEST_MAIN_JS, PACKAGE_JSON
-
-tests_path = os.path.abspath(os.path.dirname(__file__))
-
-class TestInit(unittest.TestCase):
-
-    def run_init_in_subdir(self, dirname, f, *args, **kwargs):
-        top = os.path.abspath(os.getcwd())
-        basedir = os.path.abspath(os.path.join(".test_tmp",self.id(),dirname))
-        if os.path.isdir(basedir):
-            assert basedir.startswith(top)
-            shutil.rmtree(basedir)
-        os.makedirs(basedir)
-        try:
-            os.chdir(basedir)
-            return f(basedir, *args, **kwargs)
-        finally:
-            os.chdir(top)
-
-    def do_test_init(self,basedir):
-        # Let's init the addon, no error admitted
-        f = open(".ignoreme","w")
-        f.write("stuff")
-        f.close()
-
-        out, err = StringIO(), StringIO()
-        init_run = initializer(None, ["init"], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(init_run["result"], 0)
-        self.assertTrue("* lib directory created" in out)
-        self.assertTrue("* data directory created" in out)
-        self.assertTrue("Have fun!" in out)
-        self.assertEqual(err,"")
-        self.assertTrue(len(os.listdir(basedir))>0)
-        main_js = os.path.join(basedir,"lib","main.js")
-        package_json = os.path.join(basedir,"package.json")
-        test_main_js = os.path.join(basedir,"test","test-main.js")
-        self.assertTrue(os.path.exists(main_js))
-        self.assertTrue(os.path.exists(package_json))
-        self.assertTrue(os.path.exists(test_main_js))
-        self.assertEqual(open(main_js,"r").read(),"")
-        self.assertEqual(open(package_json,"r").read() % {"id":"tmp_addon_id" },
-                         PACKAGE_JSON % {"name":"tmp_addon_sample",
-                                         "title": "tmp_addon_SAMPLE",
-                                         "id":init_run["jid"] })
-        self.assertEqual(open(test_main_js,"r").read(),TEST_MAIN_JS)
-
-        # Let's check that the addon is initialized
-        out, err = StringIO(), StringIO()
-        init_run = initializer(None, ["init"], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.failIfEqual(init_run["result"],0)
-        self.assertTrue("This command must be run in an empty directory." in err)
-
-    def test_initializer(self):
-        self.run_init_in_subdir("tmp_addon_SAMPLE",self.do_test_init)
-
-    def do_test_args(self, basedir):
-        # check that running it with spurious arguments will fail
-        out,err = StringIO(), StringIO()
-        init_run = initializer(None, ["init", "specified-dirname", "extra-arg"], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.failIfEqual(init_run["result"], 0)
-        self.assertTrue("Too many arguments" in err)
-
-    def test_args(self):
-        self.run_init_in_subdir("tmp_addon_sample", self.do_test_args)
-
-    def _test_existing_files(self, basedir):
-        f = open("pay_attention_to_me","w")
-        f.write("stuff")
-        f.close()
-        out,err = StringIO(), StringIO()
-        rc = initializer(None, ["init"], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(rc["result"], 1)
-        self.failUnless("This command must be run in an empty directory" in err,
-                        err)
-        self.failIf(os.path.exists("lib"))
-
-    def test_existing_files(self):
-        self.run_init_in_subdir("existing_files", self._test_existing_files)
-
-    def test_init_subdir(self):
-        parent = os.path.abspath(os.path.join(".test_tmp", self.id()))
-        basedir = os.path.join(parent, "init-basedir")
-        if os.path.exists(parent):
-            shutil.rmtree(parent)
-        os.makedirs(parent)
-
-        # if the basedir exists and is not empty, init should refuse
-        os.makedirs(basedir)
-        f = open(os.path.join(basedir, "boo"), "w")
-        f.write("stuff")
-        f.close()
-        out, err = StringIO(), StringIO()
-        rc = initializer(None, ["init", basedir], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(rc["result"], 1)
-        self.assertTrue("testing if directory is empty" in out, out)
-        self.assertTrue("This command must be run in an empty directory." in err,
-                        err)
-
-        # a .dotfile should be tolerated
-        os.rename(os.path.join(basedir, "boo"), os.path.join(basedir, ".phew"))
-        out, err = StringIO(), StringIO()
-        rc = initializer(None, ["init", basedir], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(rc["result"], 0)
-        self.assertTrue("* data directory created" in out, out)
-        self.assertTrue("Have fun!" in out)
-        self.assertEqual(err,"")
-        self.assertTrue(os.listdir(basedir))
-        main_js = os.path.join(basedir,"lib","main.js")
-        package_json = os.path.join(basedir,"package.json")
-        self.assertTrue(os.path.exists(main_js))
-        self.assertTrue(os.path.exists(package_json))
-        shutil.rmtree(basedir)
-
-        # init should create directories that don't exist already
-        out, err = StringIO(), StringIO()
-        rc = initializer(None, ["init", basedir], out, err)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(rc["result"], 0)
-        self.assertTrue("* data directory created" in out)
-        self.assertTrue("Have fun!" in out)
-        self.assertEqual(err,"")
-        self.assertTrue(os.listdir(basedir))
-        main_js = os.path.join(basedir,"lib","main.js")
-        package_json = os.path.join(basedir,"package.json")
-        self.assertTrue(os.path.exists(main_js))
-        self.assertTrue(os.path.exists(package_json))
-
-
-class TestCfxQuits(unittest.TestCase):
-
-    def run_cfx(self, addon_path, command):
-        old_cwd = os.getcwd()
-        os.chdir(addon_path)
-        import sys
-        old_stdout = sys.stdout
-        old_stderr = sys.stderr
-        sys.stdout = out = StringIO()
-        sys.stderr = err = StringIO()
-        rc = 0
-        try:
-            import cuddlefish
-            args = list(command)
-            # Pass arguments given to cfx so that cfx can find firefox path
-            # if --binary option is given:
-            args.extend(sys.argv[1:])
-            cuddlefish.run(arguments=args)
-        except SystemExit, e:
-            if "code" in e:
-                rc = e.code
-            elif "args" in e and len(e.args)>0:
-                rc = e.args[0]
-            else:
-                rc = 0
-        finally:
-            sys.stdout = old_stdout
-            sys.stderr = old_stderr
-            os.chdir(old_cwd)
-        out.flush()
-        err.flush()
-        return rc, out.getvalue(), err.getvalue()
-
-    # this method doesn't exists in python 2.5,
-    # implements our own
-    def assertIn(self, member, container):
-        """Just like self.assertTrue(a in b), but with a nicer default message."""
-        if member not in container:
-            standardMsg = '"%s" not found in "%s"' % (member,
-                                                  container)
-            self.fail(standardMsg)
-
-    def test_cfx_init(self):
-        # Create an empty test directory
-        addon_path = os.path.abspath(os.path.join(".test_tmp", "test-cfx-init"))
-        if os.path.isdir(addon_path):
-            shutil.rmtree(addon_path)
-        os.makedirs(addon_path)
-
-        # Fake a call to cfx init
-        old_cwd = os.getcwd()
-        os.chdir(addon_path)
-        out, err = StringIO(), StringIO()
-        rc = initializer(None, ["init"], out, err)
-        os.chdir(old_cwd)
-        out, err = out.getvalue(), err.getvalue()
-        self.assertEqual(rc["result"], 0)
-        self.assertTrue("Have fun!" in out)
-        self.assertEqual(err,"")
-
-        # run cfx test
-        rc, out, err = self.run_cfx(addon_path, ["test"])
-        self.assertEqual(rc, 0)
-        self.assertIn("6 of 6 tests passed.", err)
-        self.assertIn("Program terminated successfully.", err)
-
-
-if __name__ == "__main__":
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_licenses.py
+++ /dev/null
@@ -1,100 +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/.
-
-import unittest
-import os.path
-
-parent = os.path.dirname
-test_dir = parent(os.path.abspath(__file__))
-sdk_root = parent(parent(parent(test_dir)))
-
-def from_sdk_top(fn):
-    return os.path.abspath(os.path.join(sdk_root, fn))
-
-MPL2_URL = "http://mozilla.org/MPL/2.0/"
-
-# These files all come with their own license headers
-skip = [
-    "python-lib/cuddlefish/_version.py", # generated, public domain
-    "doc/static-files/js/jquery.js", # MIT/GPL dual
-    "examples/annotator/data/jquery-1.4.2.min.js", # MIT/GPL dual
-    "examples/reddit-panel/data/jquery-1.4.4.min.js", # MIT/GPL dual
-    "examples/library-detector/data/library-detector.js", # MIT
-    "python-lib/mozrunner/killableprocess.py", # MIT? BSDish?
-    "python-lib/mozrunner/winprocess.py", # MIT
-    "packages/api-utils/tests/test-querystring.js", # MIT
-    "packages/api-utils/lib/promise.js", # MIT
-    "packages/api-utils/tests/test-promise.js", # MIT
-    "examples/actor-repl/README.md", # It's damn readme file
-    "examples/actor-repl/data/codemirror-compressed.js", # MIT
-    "examples/actor-repl/data/codemirror.css", # MIT
-    ]
-absskip = [from_sdk_top(os.path.join(*fn.split("/"))) for fn in skip]
-
-class Licenses(unittest.TestCase):
-    def test(self):
-        # Examine most SDK files to check if they've got an MPL2 license
-        # header. We exclude some files that are known to include different
-        # licenses.
-        self.missing = []
-        self.scan_file(from_sdk_top(os.path.join("python-lib", "jetpack_sdk_env.py")))
-        self.scan(os.path.join("python-lib", "cuddlefish"), [".js", ".py"],
-                  skipdirs=["sdk-docs"], # test_generate.py makes this
-                  )
-        self.scan(os.path.join("python-lib", "mozrunner"), [".py"])
-        self.scan("lib", [".js", ".jsm", ".css"],
-                  skipdirs=[
-                    "diffpatcher", # MIT
-                    "method", # MIT
-                    "child_process", # MPL 1.1/GPL 2.0/LGPL 2.1
-                    "fs" # MIT
-                  ])
-        self.scan("test", [".js", ".jsm", ".css", ".html"],
-                  skipdirs=[
-                    "buffers", # MIT
-                    "querystring", # MIT
-                    "path" # MIT
-                  ])
-        self.scan("modules", [".js", ".jsm"])
-        self.scan("examples", [".js", ".css", ".html", ".md"])
-        self.scan("bin", [".bat", ".ps1", ".js"])
-        for fn in [os.path.join("bin", "activate"),
-                   os.path.join("bin", "cfx"),
-                   os.path.join("bin", "integration-scripts", "buildbot-run-cfx-helper"),
-                   os.path.join("bin", "integration-scripts", "integration-check"),
-                   ]:
-            self.scan_file(from_sdk_top(fn))
-
-        if self.missing:
-            print
-            print "The following files are missing an MPL2 header:"
-            for fn in sorted(self.missing):
-                print " "+fn
-            self.fail("%d files are missing an MPL2 header" % len(self.missing))
-
-    def scan(self, start, extensions=[], skipdirs=[]):
-        # scan a whole subdirectory
-        start = from_sdk_top(start)
-        for root, dirs, files in os.walk(start):
-            for d in skipdirs:
-                if d in dirs:
-                    dirs.remove(d)
-            for fn in files:
-                ext = os.path.splitext(fn)[1]
-                if extensions and ext not in extensions:
-                    continue
-                absfn = os.path.join(root, fn)
-                if absfn in absskip:
-                    continue
-                self.scan_file(absfn)
-
-    def scan_file(self, fn):
-        # scan a single file
-        if not MPL2_URL in open(fn, "r").read():
-            relfile = fn[len(sdk_root)+1:]
-            self.missing.append(relfile)
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100755
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
+++ /dev/null
@@ -1,247 +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/.
-
-import os.path
-import shutil
-import zipfile
-from StringIO import StringIO
-import simplejson as json
-import unittest
-import cuddlefish
-from cuddlefish import packaging, manifest
-
-def up(path, generations=1):
-    for i in range(generations):
-        path = os.path.dirname(path)
-    return path
-
-ROOT = up(os.path.abspath(__file__), 4)
-def get_linker_files_dir(name):
-    return os.path.join(up(os.path.abspath(__file__)), "linker-files", name)
-
-class Basic(unittest.TestCase):
-    def get_pkg(self, name):
-        d = get_linker_files_dir(name)
-        return packaging.get_config_in_dir(d)
-
-    def test_deps(self):
-        target_cfg = self.get_pkg("one")
-        pkg_cfg = packaging.build_config(ROOT, target_cfg)
-        deps = packaging.get_deps_for_targets(pkg_cfg, ["one"])
-        self.failUnlessEqual(deps, ["one"])
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "one"])
-
-    def test_manifest(self):
-        target_cfg = self.get_pkg("one")
-        pkg_cfg = packaging.build_config(ROOT, target_cfg)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "one"])
-        # target_cfg.dependencies is not provided, so we'll search through
-        # all known packages (everything in 'deps').
-        m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
-        m = m.get_harness_options_manifest(False)
-
-        def assertReqIs(modname, reqname, path):
-            reqs = m["one/%s" % modname]["requirements"]
-            self.failUnlessEqual(reqs[reqname], path)
-
-        assertReqIs("main", "sdk/panel", "sdk/panel")
-        assertReqIs("main", "two.js", "one/two")
-        assertReqIs("main", "./two", "one/two")
-        assertReqIs("main", "sdk/tabs.js", "sdk/tabs")
-        assertReqIs("main", "./subdir/three", "one/subdir/three")
-        assertReqIs("two", "main", "one/main")
-        assertReqIs("subdir/three", "../main", "one/main")
-
-        target_cfg.dependencies = []
-
-        try:
-            # this should now work, as we ignore missing modules by default
-            m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
-            m = m.get_harness_options_manifest(False)
-
-            assertReqIs("main", "sdk/panel", "sdk/panel")
-            # note that with "addon-sdk" dependency present,
-            # "sdk/tabs.js" mapped to "sdk/tabs", but without,
-            # we just get the default (identity) mapping
-            assertReqIs("main", "sdk/tabs.js", "sdk/tabs.js")
-        except Exception, e:
-            self.fail("Must not throw from build_manifest() if modules are missing")
-
-        # now, because .dependencies *is* provided, we won't search 'deps',
-        # and stop_on_missing is True, we'll get a link error
-        self.assertRaises(manifest.ModuleNotFoundError,
-                          manifest.build_manifest,
-                          target_cfg, pkg_cfg, deps, scan_tests=False,
-                          abort_on_missing=True)
-
-    def test_main_in_deps(self):
-        target_cfg = self.get_pkg("three")
-        package_path = [get_linker_files_dir("three-deps")]
-        pkg_cfg = packaging.build_config(ROOT, target_cfg,
-                                         packagepath=package_path)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "three"])
-        m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
-        m = m.get_harness_options_manifest(False)
-        def assertReqIs(modname, reqname, path):
-            reqs = m["three/%s" % modname]["requirements"]
-            self.failUnlessEqual(reqs[reqname], path)
-        assertReqIs("main", "three-a", "three-a/main")
-        assertReqIs("main", "three-b", "three-b/main")
-        assertReqIs("main", "three-c", "three-c/main")
-
-    def test_relative_main_in_top(self):
-        target_cfg = self.get_pkg("five")
-        package_path = []
-        pkg_cfg = packaging.build_config(ROOT, target_cfg,
-                                         packagepath=package_path)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "five"])
-        # all we care about is that this next call doesn't raise an exception
-        m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
-        m = m.get_harness_options_manifest(False)
-        reqs = m["five/main"]["requirements"]
-        self.failUnlessEqual(reqs, {});
-
-    def test_unreachable_relative_main_in_top(self):
-        target_cfg = self.get_pkg("six")
-        package_path = []
-        pkg_cfg = packaging.build_config(ROOT, target_cfg,
-                                         packagepath=package_path)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "six"])
-        self.assertRaises(manifest.UnreachablePrefixError,
-                          manifest.build_manifest,
-                          target_cfg, pkg_cfg, deps, scan_tests=False)
-
-    def test_unreachable_in_deps(self):
-        target_cfg = self.get_pkg("four")
-        package_path = [get_linker_files_dir("four-deps")]
-        pkg_cfg = packaging.build_config(ROOT, target_cfg,
-                                         packagepath=package_path)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        self.failUnlessEqual(deps, ["addon-sdk", "four"])
-        self.assertRaises(manifest.UnreachablePrefixError,
-                          manifest.build_manifest,
-                          target_cfg, pkg_cfg, deps, scan_tests=False)
-
-class Contents(unittest.TestCase):
-
-    def run_in_subdir(self, dirname, f, *args, **kwargs):
-        top = os.path.abspath(os.getcwd())
-        basedir = os.path.abspath(os.path.join(".test_tmp",self.id(),dirname))
-        if os.path.isdir(basedir):
-            assert basedir.startswith(top)
-            shutil.rmtree(basedir)
-        os.makedirs(basedir)
-        try:
-            os.chdir(basedir)
-            return f(basedir, *args, **kwargs)
-        finally:
-            os.chdir(top)
-
-    def assertIn(self, what, inside_what):
-        self.failUnless(what in inside_what, inside_what)
-
-    def test_jetpackID(self):
-        # this uses "id": "jid7", to which a @jetpack should be appended
-        seven = get_linker_files_dir("seven")
-        def _test(basedir):
-            stdout = StringIO()
-            shutil.copytree(seven, "seven")
-            os.chdir("seven")
-            try:
-                # regrettably, run() always finishes with sys.exit()
-                cuddlefish.run(["xpi", "--no-strip-xpi"],
-                               stdout=stdout)
-            except SystemExit, e:
-                self.failUnlessEqual(e.args[0], 0)
-            zf = zipfile.ZipFile("seven.xpi", "r")
-            hopts = json.loads(zf.read("harness-options.json"))
-            self.failUnlessEqual(hopts["jetpackID"], "jid7@jetpack")
-        self.run_in_subdir("x", _test)
-
-    def test_jetpackID_suffix(self):
-        # this uses "id": "jid1@jetpack", so no suffix should be appended
-        one = get_linker_files_dir("one")
-        def _test(basedir):
-            stdout = StringIO()
-            shutil.copytree(one, "one")
-            os.chdir("one")
-            try:
-                # regrettably, run() always finishes with sys.exit()
-                cuddlefish.run(["xpi", "--no-strip-xpi"],
-                               stdout=stdout)
-            except SystemExit, e:
-                self.failUnlessEqual(e.args[0], 0)
-            zf = zipfile.ZipFile("one.xpi", "r")
-            hopts = json.loads(zf.read("harness-options.json"))
-            self.failUnlessEqual(hopts["jetpackID"], "jid1@jetpack")
-        self.run_in_subdir("x", _test)
-
-    def test_strip_default(self):
-        seven = get_linker_files_dir("seven")
-        # now run 'cfx xpi' in that directory, except put the generated .xpi
-        # elsewhere
-        def _test(basedir):
-            stdout = StringIO()
-            shutil.copytree(seven, "seven")
-            os.chdir("seven")
-            try:
-                # regrettably, run() always finishes with sys.exit()
-                cuddlefish.run(["xpi"], # --strip-xpi is now the default
-                               stdout=stdout)
-            except SystemExit, e:
-                self.failUnlessEqual(e.args[0], 0)
-            zf = zipfile.ZipFile("seven.xpi", "r")
-            names = zf.namelist()
-            # problem found in bug 664840 was that an addon
-            # without an explicit tests/ directory would copy all files from
-            # the package into a bogus JID-PKGNAME-tests/ directory, so check
-            # for that
-            testfiles = [fn for fn in names if "seven/tests" in fn]
-            self.failUnlessEqual([], testfiles)
-            # another problem was that data files were being stripped from
-            # the XPI. Note that data/ is only supposed to be included if a
-            # module that actually gets used does a require("self") .
-            self.assertIn("resources/seven/data/text.data",
-                          names)
-            self.failIf("seven/lib/unused.js"
-                        in names, names)
-        self.run_in_subdir("x", _test)
-
-    def test_no_strip(self):
-        seven = get_linker_files_dir("seven")
-        def _test(basedir):
-            stdout = StringIO()
-            shutil.copytree(seven, "seven")
-            os.chdir("seven")
-            try:
-                # regrettably, run() always finishes with sys.exit()
-                cuddlefish.run(["xpi", "--no-strip-xpi"],
-                               stdout=stdout)
-            except SystemExit, e:
-                self.failUnlessEqual(e.args[0], 0)
-            zf = zipfile.ZipFile("seven.xpi", "r")
-            names = zf.namelist()
-            self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names)
-            testfiles = [fn for fn in names if "seven/tests" in fn]
-            self.failUnlessEqual([], testfiles)
-            self.assertIn("resources/seven/data/text.data",
-                          names)
-            self.failUnless("resources/seven/lib/unused.js"
-                            in names, names)
-        self.run_in_subdir("x", _test)
-
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_manifest.py
+++ /dev/null
@@ -1,257 +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/.
-
-
-import unittest
-from StringIO import StringIO
-from cuddlefish.manifest import scan_module
-
-class Extra:
-    def failUnlessKeysAre(self, d, keys):
-        self.failUnlessEqual(sorted(d.keys()), sorted(keys))
-
-class Require(unittest.TestCase, Extra):
-    def scan(self, text):
-        lines = StringIO(text).readlines()
-        requires, problems, locations = scan_module("fake.js", lines)
-        self.failUnlessEqual(problems, False)
-        return requires
-
-    def scan_locations(self, text):
-        lines = StringIO(text).readlines()
-        requires, problems, locations = scan_module("fake.js", lines)
-        self.failUnlessEqual(problems, False)
-        return requires, locations
-
-    def test_modules(self):
-        mod = """var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        mod = """var foo = require(\"one\");"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        mod = """var foo=require(  'one' )  ;  """
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        mod = """var foo = require('o'+'ne'); // tricky, denied"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, [])
-
-        mod = """require('one').immediately.do().stuff();"""
-        requires, locations = self.scan_locations(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-        self.failUnlessEqual(locations, {"one": 1})
-
-        # these forms are commented out, and thus ignored
-
-        mod = """// var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, [])
-
-        mod = """/* var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, [])
-
-        mod = """ * var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, [])
-
-        mod = """ ' var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        mod = """ \" var foo = require('one');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        # multiple requires
-
-        mod = """const foo = require('one');
-        const foo = require('two');"""
-        requires, locations = self.scan_locations(mod)
-        self.failUnlessKeysAre(requires, ["one", "two"])
-        self.failUnlessEqual(locations["one"], 1)
-        self.failUnlessEqual(locations["two"], 2)
-
-        mod = """const foo = require('repeated');
-        const bar = require('repeated');
-        const baz = require('repeated');"""
-        requires, locations = self.scan_locations(mod)
-        self.failUnlessKeysAre(requires, ["repeated"])
-        self.failUnlessEqual(locations["repeated"], 1) # first occurrence
-
-        mod = """const foo = require('one'); const foo = require('two');"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one", "two"])
-
-        # define calls
-
-        mod = """define('one', ['two', 'numbers/three'], function(t, th) {});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["two", "numbers/three"])
-
-        mod = """define(
-        ['odd',
-        "numbers/four"], function() {});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["odd", "numbers/four"])
-
-        mod = """define(function(require, exports, module) {
-                var a = require("some/module/a"),
-                    b = require('b/v1');
-                exports.a = a;
-                //This is a fakeout: require('bad');
-                /* And another var bad = require('bad2'); */
-                require('foo').goFoo();
-            });"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["some/module/a", "b/v1", "foo"])
-
-        mod = """define (
-            "foo",
-            ["bar"], function (bar) {
-                var me = require("me");
-            }
-        )"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["bar", "me"])
-
-        mod = """define(['se' + 'ven', 'eight', nine], function () {});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["eight"])
-
-        # async require calls
-
-        mod = """require(['one'], function(one) {var o = require("one");});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one"])
-
-        mod = """require([  'one' ], function(one) {var t = require("two");});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["one", "two"])
-
-        mod = """require ( ['two', 'numbers/three'], function(t, th) {});"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["two", "numbers/three"])
-
-        mod = """require (
-            ["bar", "fa" + 'ke'  ], function (bar) {
-                var me = require("me");
-                // require("bad").doBad();
-            }
-        )"""
-        requires = self.scan(mod)
-        self.failUnlessKeysAre(requires, ["bar", "me"])
-
-def scan2(text, fn="fake.js"):
-    stderr = StringIO()
-    lines = StringIO(text).readlines()
-    requires, problems, locations = scan_module(fn, lines, stderr)
-    stderr.seek(0)
-    return requires, problems, stderr.readlines()
-
-class Chrome(unittest.TestCase, Extra):
-
-    def test_ignore_loader(self):
-        # we specifically ignore the loader itself
-        mod = """let {Cc,Ci} = require('chrome');"""
-        requires, problems, err = scan2(mod, "blah/cuddlefish.js")
-        self.failUnlessKeysAre(requires, ["chrome"])
-        self.failUnlessEqual(problems, False)
-        self.failUnlessEqual(err, [])
-
-    def test_chrome(self):
-        mod = """let {Cc,Ci} = require('chrome');"""
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, ["chrome"])
-        self.failUnlessEqual(problems, False)
-        self.failUnlessEqual(err, [])
-
-        mod = """var foo = require('foo');
-        let {Cc,Ci} = require('chrome');"""
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, ["foo", "chrome"])
-        self.failUnlessEqual(problems, False)
-        self.failUnlessEqual(err, [])
-
-        mod = """let c = require('chrome');"""
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, ["chrome"])
-        self.failUnlessEqual(problems, False)
-        self.failUnlessEqual(err, [])
-
-        mod = """var foo = require('foo');
-        let c = require('chrome');"""
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, ["foo", "chrome"])
-        self.failUnlessEqual(problems, False)
-        self.failUnlessEqual(err, [])
-
-    def test_not_chrome(self):
-        # from bug 596595
-        mod = r'soughtLines: new RegExp("^\\s*(\\[[0-9 .]*\\])?\\s*\\(\\((EE|WW)\\)|.* [Cc]hipsets?: \\)|\\s*Backtrace")'
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, [])
-        self.failUnlessEqual((problems,err), (False, []))
-
-    def test_not_chrome2(self):
-        # from bug 655788
-        mod = r"var foo = 'some stuff Cr';"
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, [])
-        self.failUnlessEqual((problems,err), (False, []))
-
-class BadChrome(unittest.TestCase, Extra):
-    def test_bad_alias(self):
-        # using Components.* gets you an error, with a message that teaches
-        # you the correct approach.
-        mod = """let Cc = Components.classes;
-        let Cu = Components.utils;
-        """
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, [])
-        self.failUnlessEqual(problems, True)
-        self.failUnlessEqual(err[1], "The following lines from file fake.js:\n")
-        self.failUnlessEqual(err[2], "   1: let Cc = Components.classes;\n")
-        self.failUnlessEqual(err[3], "   2: let Cu = Components.utils;\n")
-        self.failUnlessEqual(err[4], "use 'Components' to access chrome authority. To do so, you need to add a\n")
-        self.failUnlessEqual(err[5], "line somewhat like the following:\n")
-        self.failUnlessEqual(err[7], '  const {Cc,Cu} = require("chrome");\n')
-        self.failUnlessEqual(err[9], "Then you can use any shortcuts to its properties that you import from the\n")
-
-    def test_bad_misc(self):
-        # If it looks like you're using something that doesn't have an alias,
-        # the warning also suggests a better way.
-        mod = """if (Components.isSuccessCode(foo))
-        """
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, [])
-        self.failUnlessEqual(problems, True)
-        self.failUnlessEqual(err[1], "The following lines from file fake.js:\n")
-        self.failUnlessEqual(err[2], "   1: if (Components.isSuccessCode(foo))\n")
-        self.failUnlessEqual(err[3], "use 'Components' to access chrome authority. To do so, you need to add a\n")
-        self.failUnlessEqual(err[4], "line somewhat like the following:\n")
-        self.failUnlessEqual(err[6], '  const {components} = require("chrome");\n')
-        self.failUnlessEqual(err[8], "Then you can use any shortcuts to its properties that you import from the\n")
-
-    def test_chrome_components(self):
-        # Bug 636145/774636: We no longer tolerate usages of "Components",
-        # even when adding `require("chrome")` to your module.
-        mod = """require("chrome");
-        var ios = Components.classes['@mozilla.org/network/io-service;1'];"""
-        requires, problems, err = scan2(mod)
-        self.failUnlessKeysAre(requires, ["chrome"])
-        self.failUnlessEqual(problems, True)
-        self.failUnlessEqual(err[1], "The following lines from file fake.js:\n")
-        self.failUnlessEqual(err[2], "   2: var ios = Components.classes['@mozilla.org/network/io-service;1'];\n")
-        self.failUnlessEqual(err[3], "use 'Components' to access chrome authority. To do so, you need to add a\n")
-        self.failUnlessEqual(err[4], "line somewhat like the following:\n")
-        self.failUnlessEqual(err[6], '  const {Cc} = require("chrome");\n')
-        self.failUnlessEqual(err[8], "Then you can use any shortcuts to its properties that you import from the\n")
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_packaging.py
+++ /dev/null
@@ -1,117 +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/.
-
-import os
-import unittest
-
-from cuddlefish import packaging
-from cuddlefish.bunch import Bunch
-
-tests_path = os.path.abspath(os.path.dirname(__file__))
-static_files_path = os.path.join(tests_path, 'static-files')
-
-def get_configs(pkg_name, dirname='static-files'):
-    root_path = os.path.join(tests_path, dirname)
-    pkg_path = os.path.join(root_path, 'packages', pkg_name)
-    if not (os.path.exists(pkg_path) and os.path.isdir(pkg_path)):
-        raise Exception('path does not exist: %s' % pkg_path)
-    target_cfg = packaging.get_config_in_dir(pkg_path)
-    pkg_cfg = packaging.build_config(root_path, target_cfg)
-    deps = packaging.get_deps_for_targets(pkg_cfg, [pkg_name])
-    build = packaging.generate_build_for_target(
-        pkg_cfg=pkg_cfg,
-        target=pkg_name,
-        deps=deps,
-        is_running_tests=True,
-        )
-    return Bunch(target_cfg=target_cfg, pkg_cfg=pkg_cfg, build=build)
-
-class PackagingTests(unittest.TestCase):
-    def test_bug_588661(self):
-        configs = get_configs('foo', 'bug-588661-files')
-        self.assertEqual(configs.build.loader,
-                         'foo/lib/foo-loader.js')
-
-    def test_bug_614712(self):
-        configs = get_configs('commonjs-naming', 'bug-614712-files')
-        packages = configs.pkg_cfg.packages
-        base = os.path.join(tests_path, 'bug-614712-files', 'packages')
-        self.assertEqual(packages['original-naming'].tests,
-                         [os.path.join(base, 'original-naming', 'tests')])
-        self.assertEqual(packages['commonjs-naming'].tests,
-                         [os.path.join(base, 'commonjs-naming', 'test')])
-
-    def test_basic(self):
-        configs = get_configs('aardvark')
-        packages = configs.pkg_cfg.packages
-
-        self.assertTrue('addon-sdk' in packages)
-        self.assertTrue('aardvark' in packages)
-        self.assertTrue('addon-sdk' in packages.aardvark.dependencies)
-        self.assertEqual(packages['addon-sdk'].loader, 'lib/sdk/loader/cuddlefish.js')
-        self.assertTrue(packages.aardvark.main == 'main')
-        self.assertTrue(packages.aardvark.version == "1.0")
-
-class PackagePath(unittest.TestCase):
-    def test_packagepath(self):
-        root_path = os.path.join(tests_path, 'static-files')
-        pkg_path = os.path.join(root_path, 'packages', 'minimal')
-        target_cfg = packaging.get_config_in_dir(pkg_path)
-        pkg_cfg = packaging.build_config(root_path, target_cfg)
-        base_packages = set(pkg_cfg.packages.keys())
-        ppath = [os.path.join(tests_path, 'bug-611495-files')]
-        pkg_cfg2 = packaging.build_config(root_path, target_cfg, packagepath=ppath)
-        all_packages = set(pkg_cfg2.packages.keys())
-        self.assertEqual(sorted(["jspath-one"]),
-                         sorted(all_packages - base_packages))
-
-class Directories(unittest.TestCase):
-    # for bug 652227
-    packages_path = os.path.join(tests_path, "bug-652227-files", "packages")
-    def get_config(self, pkg_name):
-        pkg_path = os.path.join(tests_path, "bug-652227-files", "packages",
-                                pkg_name)
-        return packaging.get_config_in_dir(pkg_path)
-
-    def test_explicit_lib(self):
-        # package.json provides .lib
-        p = self.get_config('explicit-lib')
-        self.assertEqual(os.path.abspath(p.lib[0]),
-                         os.path.abspath(os.path.join(self.packages_path,
-                                                      "explicit-lib",
-                                                      "alt2-lib")))
-
-    def test_directories_lib(self):
-        # package.json provides .directories.lib
-        p = self.get_config('explicit-dir-lib')
-        self.assertEqual(os.path.abspath(p.lib[0]),
-                         os.path.abspath(os.path.join(self.packages_path,
-                                                      "explicit-dir-lib",
-                                                      "alt-lib")))
-
-    def test_lib(self):
-        # package.json is empty, but lib/ exists
-        p = self.get_config("default-lib")
-        self.assertEqual(os.path.abspath(p.lib[0]),
-                         os.path.abspath(os.path.join(self.packages_path,
-                                                      "default-lib",
-                                                      "lib")))
-
-    def test_root(self):
-        # package.json is empty, no lib/, so files are in root
-        p = self.get_config('default-root')
-        self.assertEqual(os.path.abspath(p.lib[0]),
-                         os.path.abspath(os.path.join(self.packages_path,
-                                                      "default-root")))
-
-    def test_locale(self):
-        # package.json is empty, but locale/ exists and should be used
-        p = self.get_config("default-locale")
-        self.assertEqual(os.path.abspath(p.locale),
-                         os.path.abspath(os.path.join(self.packages_path,
-                                                      "default-locale",
-                                                      "locale")))
-
-if __name__ == "__main__":
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_preflight.py
+++ /dev/null
@@ -1,147 +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/.
-
-
-import os, shutil
-import simplejson as json
-import unittest
-import hashlib
-import base64
-from cuddlefish import preflight
-from StringIO import StringIO
-
-class Util(unittest.TestCase):
-    def get_basedir(self):
-        return os.path.join(".test_tmp", self.id())
-    def make_basedir(self):
-        basedir = self.get_basedir()
-        if os.path.isdir(basedir):
-            here = os.path.abspath(os.getcwd())
-            assert os.path.abspath(basedir).startswith(here) # safety
-            shutil.rmtree(basedir)
-        os.makedirs(basedir)
-        return basedir
-
-    def test_base62(self):
-        for i in range(1000):
-            h = hashlib.sha1(str(i)).digest()
-            s1 = base64.b64encode(h, "AB").strip("=")
-            s2 = base64.b64encode(h).strip("=").replace("+","A").replace("/","B")
-            self.failUnlessEqual(s1, s2)
-
-    def write(self, config):
-        basedir = self.get_basedir()
-        fn = os.path.join(basedir, "package.json")
-        open(fn,"w").write(config)
-    def read(self):
-        basedir = self.get_basedir()
-        fn = os.path.join(basedir, "package.json")
-        return open(fn,"r").read()
-
-    def get_cfg(self):
-        cfg = json.loads(self.read())
-        if "name" not in cfg:
-            # the cfx parser always provides a name, even if package.json
-            # doesn't contain one
-            cfg["name"] = "pretend name"
-        return cfg
-
-    def parse(self, keydata):
-        fields = {}
-        fieldnames = []
-        for line in keydata.split("\n"):
-            if line.strip():
-                k,v = line.split(":", 1)
-                k = k.strip() ; v = v.strip()
-                fields[k] = v
-                fieldnames.append(k)
-        return fields, fieldnames
-
-    def test_preflight(self):
-        basedir = self.make_basedir()
-        fn = os.path.join(basedir, "package.json")
-
-        # empty config is not ok: need id (name is automatically supplied)
-        config_orig = "{}"
-        self.write(config_orig)
-        out = StringIO()
-        cfg = self.get_cfg()
-        config_was_ok, modified = preflight.preflight_config(cfg, fn,
-                                                             stderr=out)
-        self.failUnlessEqual(config_was_ok, False)
-        self.failUnlessEqual(modified, True)
-        backup_fn = os.path.join(basedir, "package.json.backup")
-        config_backup = open(backup_fn,"r").read()
-        self.failUnlessEqual(config_backup, config_orig)
-        config = json.loads(self.read())
-        self.failIf("name" in config)
-        self.failUnless("id" in config)
-        self.failUnless(config["id"].startswith("jid1-"), config["id"])
-        self.failUnlessEqual(out.getvalue().strip(),
-                             "No 'id' in package.json: creating a new ID for you.")
-        os.unlink(backup_fn)
-
-        # just a name? we add the id
-        config_orig = '{"name": "my-awesome-package"}'
-        self.write(config_orig)
-        out = StringIO()
-        cfg = self.get_cfg()
-        config_was_ok, modified = preflight.preflight_config(cfg, fn,
-                                                             stderr=out)
-        self.failUnlessEqual(config_was_ok, False)
-        self.failUnlessEqual(modified, True)
-        backup_fn = os.path.join(basedir, "package.json.backup")
-        config_backup = open(backup_fn,"r").read()
-        self.failUnlessEqual(config_backup, config_orig)
-        config = json.loads(self.read())
-        self.failUnlessEqual(config["name"], "my-awesome-package")
-        self.failUnless("id" in config)
-        self.failUnless(config["id"].startswith("jid1-"), config["id"])
-        jid = str(config["id"])
-        self.failUnlessEqual(out.getvalue().strip(),
-                             "No 'id' in package.json: creating a new ID for you.")
-        os.unlink(backup_fn)
-
-        # name and valid id? great! ship it!
-        config2 = '{"name": "my-awesome-package", "id": "%s"}' % jid
-        self.write(config2)
-        out = StringIO()
-        cfg = self.get_cfg()
-        config_was_ok, modified = preflight.preflight_config(cfg, fn,
-                                                             stderr=out)
-        self.failUnlessEqual(config_was_ok, True)
-        self.failUnlessEqual(modified, False)
-        config2a = self.read()
-        self.failUnlessEqual(config2a, config2)
-        self.failUnlessEqual(out.getvalue().strip(), "")
-
-        # name and anonymous ID? without asking to see its papers, ship it
-        config3 = '{"name": "my-old-skool-package", "id": "anonid0-deadbeef"}'
-        self.write(config3)
-        out = StringIO()
-        cfg = self.get_cfg()
-        config_was_ok, modified = preflight.preflight_config(cfg, fn,
-                                                             stderr=out)
-        self.failUnlessEqual(config_was_ok, True)
-        self.failUnlessEqual(modified, False)
-        config3a = self.read()
-        self.failUnlessEqual(config3a, config3)
-        self.failUnlessEqual(out.getvalue().strip(), "")
-
-        # name and old-style ID? with nostalgic trepidation, ship it
-        config4 = '{"name": "my-old-skool-package", "id": "foo@bar.baz"}'
-        self.write(config4)
-        out = StringIO()
-        cfg = self.get_cfg()
-        config_was_ok, modified = preflight.preflight_config(cfg, fn,
-                                                             stderr=out)
-        self.failUnlessEqual(config_was_ok, True)
-        self.failUnlessEqual(modified, False)
-        config4a = self.read()
-        self.failUnlessEqual(config4a, config4)
-        self.failUnlessEqual(out.getvalue().strip(), "")
-
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_property_parser.py
+++ /dev/null
@@ -1,93 +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/.
-
-import unittest
-
-from cuddlefish.property_parser import parse, MalformedLocaleFileError
-
-class TestParser(unittest.TestCase):
-
-    def test_parse(self):
-        lines = [
-          # Comments are striped only if `#` is the first non-space character
-          "sharp=#can be in value",
-          "# comment",
-          "#key=value",
-          "  # comment2",
-
-          "keyWithNoValue=",
-          "valueWithSpaces=   ",
-          "valueWithMultilineSpaces=  \\",
-          "  \\",
-          "  ",
-
-          # All spaces before/after are striped
-          " key = value ",
-          "key2=value2",
-          # Keys can contain '%'
-          "%s key=%s value",
-
-          # Accept empty lines
-          "",
-          "   ",
-
-          # Multiline string must use backslash at end of lines
-          "multi=line\\", "value",
-          # With multiline string, left spaces are stripped ...
-          "some= spaces\\", " are\\  ", " stripped ",
-          # ... but not right spaces, except the last line!
-          "but=not \\", "all of \\", " them ",
-
-          # Explicit [other] plural definition
-          "explicitPlural[one] = one",
-          "explicitPlural[other] = other",
-
-          # Implicit [other] plural definition
-          "implicitPlural[one] = one",
-          "implicitPlural = other", # This key is the [other] one
-        ]
-        # Ensure that all lines end with a `\n`
-        # And that strings are unicode ones (parser code relies on it)
-        lines = [unicode(l + "\n") for l in lines]
-        pairs = parse(lines)
-        expected = {
-          "sharp": "#can be in value",
-
-          "key": "value",
-          "key2": "value2",
-          "%s key": "%s value",
-
-          "keyWithNoValue": "",
-          "valueWithSpaces": "",
-          "valueWithMultilineSpaces": "",
-
-          "multi": "linevalue",
-          "some": "spacesarestripped",
-          "but": "not all of them",
-
-          "implicitPlural": {
-            "one": "one",
-            "other": "other"
-          },
-          "explicitPlural": {
-            "one": "one",
-            "other": "other"
-          },
-        }
-        self.assertEqual(pairs, expected)
-
-    def test_exceptions(self):
-        self.failUnlessRaises(MalformedLocaleFileError, parse,
-                              ["invalid line with no key value"])
-        self.failUnlessRaises(MalformedLocaleFileError, parse,
-                              ["plural[one]=plural with no [other] value"])
-        self.failUnlessRaises(MalformedLocaleFileError, parse,
-                              ["multiline with no last empty line=\\"])
-        self.failUnlessRaises(MalformedLocaleFileError, parse,
-                              ["=no key"])
-        self.failUnlessRaises(MalformedLocaleFileError, parse,
-                              ["   =only spaces in key"])
-
-if __name__ == "__main__":
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import unittest
-import xml.dom.minidom
-import os.path
-
-from cuddlefish import rdf, packaging
-
-parent = os.path.dirname
-test_dir = parent(os.path.abspath(__file__))
-template_dir = os.path.join(parent(test_dir), "../../app-extension")
-
-class RDFTests(unittest.TestCase):
-    def testBug567660(self):
-        obj = rdf.RDF()
-        data = u'\u2026'.encode('utf-8')
-        x = '<?xml version="1.0" encoding="utf-8"?><blah>%s</blah>' % data
-        obj.dom = xml.dom.minidom.parseString(x)
-        self.assertEqual(obj.dom.documentElement.firstChild.nodeValue,
-                         u'\u2026')
-        self.assertEqual(str(obj).replace("\n",""), x.replace("\n",""))
-
-    def failUnlessIn(self, substring, s, msg=""):
-        if substring not in s:
-            self.fail("(%s) substring '%s' not in string '%s'"
-                      % (msg, substring, s))
-
-    def testUnpack(self):
-        basedir = os.path.join(test_dir, "bug-715340-files")
-        for n in ["pkg-1-pack", "pkg-2-unpack", "pkg-3-pack"]:
-            cfg = packaging.get_config_in_dir(os.path.join(basedir, n))
-            m = rdf.gen_manifest(template_dir, cfg, jid="JID")
-            if n.endswith("-pack"):
-                # these ones should remain packed
-                self.failUnlessEqual(m.get("em:unpack"), "false")
-                self.failUnlessIn("<em:unpack>false</em:unpack>", str(m), n)
-            else:
-                # and these should be unpacked
-                self.failUnlessEqual(m.get("em:unpack"), "true")
-                self.failUnlessIn("<em:unpack>true</em:unpack>", str(m), n)
-
-    def testTitle(self):
-        basedir = os.path.join(test_dir, 'bug-906359-files')
-        for n in ['title', 'fullName', 'none']:
-            cfg = packaging.get_config_in_dir(os.path.join(basedir, n))
-            m = rdf.gen_manifest(template_dir, cfg, jid='JID')
-            self.failUnlessEqual(m.get('em:name'), 'a long ' + n)
-            self.failUnlessIn('<em:name>a long ' + n + '</em:name>', str(m), n)
-
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_runner.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-def xulrunner_app_runner_doctests():
-    """
-    >>> import sys
-    >>> from cuddlefish import runner
-    >>> runner.XulrunnerAppRunner(binary='foo')
-    Traceback (most recent call last):
-    ...
-    Exception: Binary path does not exist foo
-
-    >>> runner.XulrunnerAppRunner(binary=sys.executable)
-    Traceback (most recent call last):
-    ...
-    ValueError: application.ini not found in cmdargs
-
-    >>> runner.XulrunnerAppRunner(binary=sys.executable,
-    ...                         cmdargs=['application.ini'])
-    Traceback (most recent call last):
-    ...
-    ValueError: file does not exist: 'application.ini'
-    """
-
-    pass
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_util.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-import unittest
-from cuddlefish.manifest import filter_filenames, filter_dirnames
-
-class Filter(unittest.TestCase):
-    def test_filter_filenames(self):
-        names = ["foo", "bar.js", "image.png",
-                 ".hidden", "foo~", ".foo.swp", "bar.js.swp"]
-        self.failUnlessEqual(sorted(filter_filenames(names)),
-                             sorted(["foo", "bar.js", "image.png"]))
-
-    def test_filter_dirnames(self):
-        names = ["subdir", "data", ".git", ".hg", ".svn", "defaults"]
-        self.failUnlessEqual(sorted(filter_dirnames(names)),
-                             sorted(["subdir", "data", "defaults"]))
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_version.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import os
-import unittest
-import shutil
-
-from cuddlefish._version import get_versions
-
-class Version(unittest.TestCase):
-    def get_basedir(self):
-        return os.path.join(".test_tmp", self.id())
-    def make_basedir(self):
-        basedir = self.get_basedir()
-        if os.path.isdir(basedir):
-            here = os.path.abspath(os.getcwd())
-            assert os.path.abspath(basedir).startswith(here) # safety
-            shutil.rmtree(basedir)
-        os.makedirs(basedir)
-        return basedir
-
-    def test_current_version(self):
-        # the SDK should be able to determine its own version. We don't care
-        # what it is, merely that it can be computed.
-        version = get_versions()["version"]
-        self.failUnless(isinstance(version, str), (version, type(version)))
-        self.failUnless(len(version) > 0, version)
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py
+++ /dev/null
@@ -1,310 +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/.
-
-import os
-import unittest
-import zipfile
-import pprint
-import shutil
-
-import simplejson as json
-from cuddlefish import xpi, packaging, manifest, buildJID
-from cuddlefish.tests import test_packaging
-from test_linker import up
-
-import xml.etree.ElementTree as ElementTree
-
-xpi_template_path = os.path.join(test_packaging.static_files_path,
-                                 'xpi-template')
-
-fake_manifest = '<RDF><!-- Extension metadata is here. --></RDF>'
-
-
-class Bug588119Tests(unittest.TestCase):
-    def makexpi(self, pkg_name):
-        self.xpiname = "%s.xpi" % pkg_name
-        create_xpi(self.xpiname, pkg_name, 'bug-588119-files')
-        self.xpi = zipfile.ZipFile(self.xpiname, 'r')
-        options = self.xpi.read('harness-options.json')
-        self.xpi_harness_options = json.loads(options)
-
-    def setUp(self):
-        self.xpiname = None
-        self.xpi = None
-
-    def tearDown(self):
-        if self.xpi:
-            self.xpi.close()
-        if self.xpiname and os.path.exists(self.xpiname):
-            os.remove(self.xpiname)
-
-    def testPackageWithImplicitIcon(self):
-        self.makexpi('implicit-icon')
-        assert 'icon.png' in self.xpi.namelist()
-
-    def testPackageWithImplicitIcon64(self):
-        self.makexpi('implicit-icon')
-        assert 'icon64.png' in self.xpi.namelist()
-
-    def testPackageWithExplicitIcon(self):
-        self.makexpi('explicit-icon')
-        assert 'icon.png' in self.xpi.namelist()
-
-    def testPackageWithExplicitIcon64(self):
-        self.makexpi('explicit-icon')
-        assert 'icon64.png' in self.xpi.namelist()
-
-    def testPackageWithNoIcon(self):
-        self.makexpi('no-icon')
-        assert 'icon.png' not in self.xpi.namelist()
-
-    def testIconPathNotInHarnessOptions(self):
-        self.makexpi('implicit-icon')
-        assert 'icon' not in self.xpi_harness_options
-
-    def testIcon64PathNotInHarnessOptions(self):
-        self.makexpi('implicit-icon')
-        assert 'icon64' not in self.xpi_harness_options
-
-class ExtraHarnessOptions(unittest.TestCase):
-    def setUp(self):
-        self.xpiname = None
-        self.xpi = None
-
-    def tearDown(self):
-        if self.xpi:
-            self.xpi.close()
-        if self.xpiname and os.path.exists(self.xpiname):
-            os.remove(self.xpiname)
-
-    def testOptions(self):
-        pkg_name = "extra-options"
-        self.xpiname = "%s.xpi" % pkg_name
-        create_xpi(self.xpiname, pkg_name, "bug-669274-files",
-                   extra_harness_options={"builderVersion": "futuristic"})
-        self.xpi = zipfile.ZipFile(self.xpiname, 'r')
-        options = self.xpi.read('harness-options.json')
-        hopts = json.loads(options)
-        self.failUnless("builderVersion" in hopts)
-        self.failUnlessEqual(hopts["builderVersion"], "futuristic")
-
-    def testBadOptionName(self):
-        pkg_name = "extra-options"
-        self.xpiname = "%s.xpi" % pkg_name
-        self.failUnlessRaises(xpi.HarnessOptionAlreadyDefinedError,
-                              create_xpi,
-                              self.xpiname, pkg_name, "bug-669274-files",
-                              extra_harness_options={"main": "already in use"})
-
-class SmallXPI(unittest.TestCase):
-    def setUp(self):
-        self.root = up(os.path.abspath(__file__), 4)
-    def get_linker_files_dir(self, name):
-        return os.path.join(up(os.path.abspath(__file__)), "linker-files", name)
-    def get_pkg(self, name):
-        d = self.get_linker_files_dir(name)
-        return packaging.get_config_in_dir(d)
-
-    def get_basedir(self):
-        return os.path.join(".test_tmp", self.id())
-    def make_basedir(self):
-        basedir = self.get_basedir()
-        if os.path.isdir(basedir):
-            here = os.path.abspath(os.getcwd())
-            assert os.path.abspath(basedir).startswith(here) # safety
-            shutil.rmtree(basedir)
-        os.makedirs(basedir)
-        return basedir
-
-    def test_contents(self):
-        target_cfg = self.get_pkg("three")
-        package_path = [self.get_linker_files_dir("three-deps")]
-        pkg_cfg = packaging.build_config(self.root, target_cfg,
-                                         packagepath=package_path)
-        deps = packaging.get_deps_for_targets(pkg_cfg,
-                                              [target_cfg.name, "addon-sdk"])
-        addon_sdk_dir = pkg_cfg.packages["addon-sdk"].lib[0]
-        m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
-        used_files = list(m.get_used_files(True))
-        here = up(os.path.abspath(__file__))
-        def absify(*parts):
-            fn = os.path.join(here, "linker-files", *parts)
-            return os.path.abspath(fn)
-        expected = [absify(*parts) for parts in
-                    [("three", "lib", "main.js"),
-                     ("three-deps", "three-a", "lib", "main.js"),
-                     ("three-deps", "three-a", "lib", "subdir", "subfile.js"),
-                     ("three", "data", "msg.txt"),
-                     ("three", "data", "subdir", "submsg.txt"),
-                     ("three-deps", "three-b", "lib", "main.js"),
-                     ("three-deps", "three-c", "lib", "main.js"),
-                     ("three-deps", "three-c", "lib", "sub", "foo.js")
-                     ]]
-
-        add_addon_sdk= lambda path: os.path.join(addon_sdk_dir, path)
-        expected.extend([add_addon_sdk(module) for module in [
-            os.path.join("sdk", "self.js"),
-            os.path.join("sdk", "core", "promise.js"),
-            os.path.join("sdk", "net", "url.js"),
-            os.path.join("sdk", "util", "object.js"),
-            os.path.join("sdk", "util", "array.js"),
-            os.path.join("sdk", "preferences", "service.js")
-            ]])
-
-        missing = set(expected) - set(used_files)
-        extra = set(used_files) - set(expected)
-        self.failUnlessEqual(list(missing), [])
-        self.failUnlessEqual(list(extra), [])
-        used_deps = m.get_used_packages()
-
-        build = packaging.generate_build_for_target(pkg_cfg, target_cfg.name,
-                                                    used_deps,
-                                                    include_tests=False)
-        options = {'main': target_cfg.main}
-        options.update(build)
-        basedir = self.make_basedir()
-        xpi_name = os.path.join(basedir, "contents.xpi")
-        xpi.build_xpi(template_root_dir=xpi_template_path,
-                      manifest=fake_manifest,
-                      xpi_path=xpi_name,
-                      harness_options=options,
-                      limit_to=used_files)
-        x = zipfile.ZipFile(xpi_name, "r")
-        names = x.namelist()
-        expected = ["components/",
-                    "components/harness.js",
-                    # the real template also has 'bootstrap.js', but the fake
-                    # one in tests/static-files/xpi-template doesn't
-                    "harness-options.json",
-                    "install.rdf",
-                    "resources/",
-                    "resources/addon-sdk/",
-                    "resources/addon-sdk/lib/",
-                    "resources/addon-sdk/lib/sdk/",
-                    "resources/addon-sdk/lib/sdk/self.js",
-                    "resources/addon-sdk/lib/sdk/core/",
-                    "resources/addon-sdk/lib/sdk/util/",
-                    "resources/addon-sdk/lib/sdk/net/",
-                    "resources/addon-sdk/lib/sdk/core/promise.js",
-                    "resources/addon-sdk/lib/sdk/util/object.js",
-                    "resources/addon-sdk/lib/sdk/util/array.js",
-                    "resources/addon-sdk/lib/sdk/net/url.js",
-                    "resources/addon-sdk/lib/sdk/preferences/",
-                    "resources/addon-sdk/lib/sdk/preferences/service.js",
-                    "resources/three/",
-                    "resources/three/lib/",
-                    "resources/three/lib/main.js",
-                    "resources/three/data/",
-                    "resources/three/data/msg.txt",
-                    "resources/three/data/subdir/",
-                    "resources/three/data/subdir/submsg.txt",
-                    "resources/three-a/",
-                    "resources/three-a/lib/",
-                    "resources/three-a/lib/main.js",
-                    "resources/three-a/lib/subdir/",
-                    "resources/three-a/lib/subdir/subfile.js",
-                    "resources/three-b/",
-                    "resources/three-b/lib/",
-                    "resources/three-b/lib/main.js",
-                    "resources/three-c/",
-                    "resources/three-c/lib/",
-                    "resources/three-c/lib/main.js",
-                    "resources/three-c/lib/sub/",
-                    "resources/three-c/lib/sub/foo.js",
-                    # notably absent: three-a/lib/unused.js
-                    "locale/",
-                    "locale/fr-FR.json",
-                    "locales.json",
-                    ]
-        # showing deltas makes failures easier to investigate
-        missing = set(expected) - set(names)
-        extra = set(names) - set(expected)
-        self.failUnlessEqual((list(missing), list(extra)), ([], []))
-        self.failUnlessEqual(sorted(names), sorted(expected))
-
-        # check locale files
-        localedata = json.loads(x.read("locales.json"))
-        self.failUnlessEqual(sorted(localedata["locales"]), sorted(["fr-FR"]))
-        content = x.read("locale/fr-FR.json")
-        locales = json.loads(content)
-        # Locale files are merged into one.
-        # Conflicts are silently resolved by taking last package translation,
-        # so that we get "No" translation from three-c instead of three-b one.
-        self.failUnlessEqual(locales, json.loads(u'''
-          {
-            "No": "Nein",
-            "one": "un",
-            "What?": "Quoi?",
-            "Yes": "Oui",
-            "plural": {
-              "other": "other",
-              "one": "one"
-            },
-            "uft8_value": "\u00e9"
-          }'''))
-
-
-def document_dir(name):
-    if name in ['packages', 'xpi-template']:
-        dirname = os.path.join(test_packaging.static_files_path, name)
-        document_dir_files(dirname)
-    elif name == 'xpi-output':
-        create_xpi('test-xpi.xpi')
-        document_zip_file('test-xpi.xpi')
-        os.remove('test-xpi.xpi')
-    else:
-        raise Exception('unknown dir: %s' % name)
-
-def normpath(path):
-    """
-    Make a platform-specific relative path use '/' as a separator.
-    """
-
-    return path.replace(os.path.sep, '/')
-
-def document_zip_file(path):
-    zip = zipfile.ZipFile(path, 'r')
-    for name in sorted(zip.namelist()):
-        contents = zip.read(name)
-        lines = contents.splitlines()
-        if len(lines) == 1 and name.endswith('.json') and len(lines[0]) > 75:
-            # Ideally we would json-decode this, but it results
-            # in an annoying 'u' before every string literal,
-            # since json decoding makes all strings unicode.
-            contents = eval(contents)
-            contents = pprint.pformat(contents)
-            lines = contents.splitlines()
-        contents = "\n  ".join(lines)
-        print "%s:\n  %s" % (normpath(name), contents)
-    zip.close()
-
-def document_dir_files(path):
-    filename_contents_tuples = []
-    for dirpath, dirnames, filenames in os.walk(path):
-        relpath = dirpath[len(path)+1:]
-        for filename in filenames:
-            abspath = os.path.join(dirpath, filename)
-            contents = open(abspath, 'r').read()
-            contents = "\n  ".join(contents.splitlines())
-            relfilename = os.path.join(relpath, filename)
-            filename_contents_tuples.append((normpath(relfilename), contents))
-    filename_contents_tuples.sort()
-    for filename, contents in filename_contents_tuples:
-        print "%s:" % filename
-        print "  %s" % contents
-
-def create_xpi(xpiname, pkg_name='aardvark', dirname='static-files',
-               extra_harness_options={}):
-    configs = test_packaging.get_configs(pkg_name, dirname)
-    options = {'main': configs.target_cfg.main,
-               'jetpackID': buildJID(configs.target_cfg), }
-    options.update(configs.build)
-    xpi.build_xpi(template_root_dir=xpi_template_path,
-                  manifest=fake_manifest,
-                  xpi_path=xpiname,
-                  harness_options=options,
-                  extra_harness_options=extra_harness_options)
-
-if __name__ == '__main__':
-    unittest.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/util.py
+++ /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/.
-
-
-IGNORED_FILE_PREFIXES = ["."]
-IGNORED_FILE_SUFFIXES = ["~", ".swp"]
-IGNORED_DIRS = [".git", ".svn", ".hg"]
-
-def filter_filenames(filenames, ignored_files=[".hgignore"]):
-    for filename in filenames:
-        if filename in ignored_files:
-            continue
-        if any([filename.startswith(suffix)
-                for suffix in IGNORED_FILE_PREFIXES]):
-            continue
-        if any([filename.endswith(suffix)
-                for suffix in IGNORED_FILE_SUFFIXES]):
-            continue
-        yield filename
-
-def filter_dirnames(dirnames):
-    return [dirname for dirname in dirnames if dirname not in IGNORED_DIRS]
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/version_comparator.py
+++ /dev/null
@@ -1,206 +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 really crummy, slow Python implementation of the Mozilla
-    platform's nsIVersionComparator interface:
-
-      https://developer.mozilla.org/En/NsIVersionComparator
-
-    For more information, also see:
-
-      http://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsVersionComparator.cpp
-'''
-
-import re
-import sys
-
-class VersionPart(object):
-    '''
-    Examples:
-
-      >>> VersionPart('1')
-      (1, None, 0, None)
-
-      >>> VersionPart('1pre')
-      (1, 'pre', 0, None)
-
-      >>> VersionPart('1pre10')
-      (1, 'pre', 10, None)
-
-      >>> VersionPart('1pre10a')
-      (1, 'pre', 10, 'a')
-
-      >>> VersionPart('1+')
-      (2, 'pre', 0, None)
-
-      >>> VersionPart('*').numA == sys.maxint
-      True
-
-      >>> VersionPart('1') < VersionPart('2')
-      True
-
-      >>> VersionPart('2') > VersionPart('1')
-      True
-
-      >>> VersionPart('1') == VersionPart('1')
-      True
-
-      >>> VersionPart('1pre') > VersionPart('1')
-      False
-
-      >>> VersionPart('1') < VersionPart('1pre')
-      False
-
-      >>> VersionPart('1pre1') < VersionPart('1pre2')
-      True
-
-      >>> VersionPart('1pre10b') > VersionPart('1pre10a')
-      True
-
-      >>> VersionPart('1pre10b') == VersionPart('1pre10b')
-      True
-
-      >>> VersionPart('1pre10a') < VersionPart('1pre10b')
-      True
-
-      >>> VersionPart('1') > VersionPart('')
-      True
-    '''
-
-    _int_part = re.compile('[+-]?(\d*)(.*)')
-    _num_chars = '0123456789+-'
-
-    def __init__(self, part):
-        self.numA = 0
-        self.strB = None
-        self.numC = 0
-        self.extraD = None
-
-        if not part:
-            return
-
-        if part == '*':
-            self.numA = sys.maxint
-        else:
-            match = self._int_part.match(part)
-            self.numA = int(match.group(1))
-            self.strB = match.group(2) or None
-        if self.strB == '+':
-            self.strB = 'pre'
-            self.numA += 1
-        elif self.strB:
-            i = 0
-            num_found = -1
-            for char in self.strB:
-                if char in self._num_chars:
-                    num_found = i
-                    break
-                i += 1
-            if num_found != -1:
-                match = self._int_part.match(self.strB[num_found:])
-                self.numC = int(match.group(1))
-                self.extraD = match.group(2) or None
-                self.strB = self.strB[:num_found]
-
-    def _strcmp(self, str1, str2):
-        # Any string is *before* no string.
-        if str1 is None:
-            if str2 is None:
-                return 0
-            else:
-                return 1
-
-        if str2 is None:
-            return -1
-
-        return cmp(str1, str2)
-
-    def __cmp__(self, other):
-        r = cmp(self.numA, other.numA)
-        if r:
-            return r
-
-        r = self._strcmp(self.strB, other.strB)
-        if r:
-            return r
-
-        r = cmp(self.numC, other.numC)
-        if r:
-            return r
-
-        return self._strcmp(self.extraD, other.extraD)
-
-    def __repr__(self):
-        return repr((self.numA, self.strB, self.numC, self.extraD))
-
-def compare(a, b):
-    '''
-    Examples:
-
-      >>> compare('1', '2')
-      -1
-
-      >>> compare('1', '1')
-      0
-
-      >>> compare('2', '1')
-      1
-
-      >>> compare('1.0pre1', '1.0pre2')
-      -1
-
-      >>> compare('1.0pre2', '1.0')
-      -1
-
-      >>> compare('1.0', '1.0.0')
-      0
-
-      >>> compare('1.0.0', '1.0.0.0')
-      0
-
-      >>> compare('1.0.0.0', '1.1pre')
-      -1
-
-      >>> compare('1.1pre', '1.1pre0')
-      0
-
-      >>> compare('1.1pre0', '1.0+')
-      0
-
-      >>> compare('1.0+', '1.1pre1a')
-      -1
-
-      >>> compare('1.1pre1a', '1.1pre1')
-      -1
-
-      >>> compare('1.1pre1', '1.1pre10a')
-      -1
-
-      >>> compare('1.1pre10a', '1.1pre10')
-      -1
-
-      >>> compare('1.1pre10a', '1.*')
-      -1
-    '''
-
-    a_parts = a.split('.')
-    b_parts = b.split('.')
-
-    if len(a_parts) < len(b_parts):
-        a_parts.extend([''] * (len(b_parts) - len(a_parts)))
-    else:
-        b_parts.extend([''] * (len(a_parts) - len(b_parts)))
-
-    for a_part, b_part in zip(a_parts, b_parts):
-        r = cmp(VersionPart(a_part), VersionPart(b_part))
-        if r:
-            return r
-
-    return 0
-
-if __name__ == '__main__':
-    import doctest
-
-    doctest.testmod(verbose=True)
deleted file mode 100644
--- a/addon-sdk/source/python-lib/cuddlefish/xpi.py
+++ /dev/null
@@ -1,169 +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/.
-
-import os
-import zipfile
-import simplejson as json
-from cuddlefish.util import filter_filenames, filter_dirnames
-
-class HarnessOptionAlreadyDefinedError(Exception):
-    """You cannot use --harness-option on keys that already exist in
-    harness-options.json"""
-
-ZIPSEP = "/" # always use "/" in zipfiles
-
-def make_zipfile_path(localroot, localpath):
-    return ZIPSEP.join(localpath[len(localroot)+1:].split(os.sep))
-
-def mkzipdir(zf, path):
-    dirinfo = zipfile.ZipInfo(path)
-    dirinfo.external_attr = int("040755", 8) << 16L
-    zf.writestr(dirinfo, "")
-
-def build_xpi(template_root_dir, manifest, xpi_path,
-              harness_options, limit_to=None, extra_harness_options={},
-              bundle_sdk=True, pkgdir=""):
-    IGNORED_FILES = [".hgignore", ".DS_Store",
-                     "application.ini", xpi_path]
-    IGNORED_TOP_LVL_FILES = ["install.rdf"]
-
-    files_to_copy = {} # maps zipfile path to local-disk abspath
-    dirs_to_create = set() # zipfile paths, no trailing slash
-
-    zf = zipfile.ZipFile(xpi_path, "w", zipfile.ZIP_DEFLATED)
-
-    zf.writestr('install.rdf', str(manifest))
-
-    # Handle add-on icon
-    if 'icon' in harness_options:
-        zf.write(os.path.join(str(harness_options['icon'])), 'icon.png')
-        del harness_options['icon']
-
-    if 'icon64' in harness_options:
-        zf.write(os.path.join(str(harness_options['icon64'])), 'icon64.png')
-        del harness_options['icon64']
-
-    # chrome.manifest
-    if os.path.isfile(os.path.join(pkgdir, 'chrome.manifest')):
-      files_to_copy['chrome.manifest'] = os.path.join(pkgdir, 'chrome.manifest')
-
-    def add_special_dir(folder):
-      if os.path.exists(os.path.join(pkgdir, folder)):
-        dirs_to_create.add(folder)
-        # cp -r folder
-        abs_dirname = os.path.join(pkgdir, folder)
-        for dirpath, dirnames, filenames in os.walk(abs_dirname):
-          goodfiles = list(filter_filenames(filenames, IGNORED_FILES))
-          dirnames[:] = filter_dirnames(dirnames)
-          for dirname in dirnames:
-            arcpath = make_zipfile_path(template_root_dir,
-                                        os.path.join(dirpath, dirname))
-            dirs_to_create.add(arcpath)
-          for filename in goodfiles:
-              abspath = os.path.join(dirpath, filename)
-              arcpath = ZIPSEP.join(
-                  [folder,
-                   make_zipfile_path(abs_dirname, os.path.join(dirpath, filename)),
-                   ])
-              files_to_copy[str(arcpath)] = str(abspath)
-
-
-    # chrome folder (would contain content, skin, and locale folders typically)
-    add_special_dir('chrome')
-    # optionally include a `webextension/` dir from the add-on dir.
-    add_special_dir('webextension')
-
-    for dirpath, dirnames, filenames in os.walk(template_root_dir):
-        if template_root_dir == dirpath:
-            filenames = list(filter_filenames(filenames, IGNORED_TOP_LVL_FILES))
-        filenames = list(filter_filenames(filenames, IGNORED_FILES))
-        dirnames[:] = filter_dirnames(dirnames)
-        for dirname in dirnames:
-            arcpath = make_zipfile_path(template_root_dir,
-                                        os.path.join(dirpath, dirname))
-            dirs_to_create.add(arcpath)
-        for filename in filenames:
-            abspath = os.path.join(dirpath, filename)
-            arcpath = make_zipfile_path(template_root_dir, abspath)
-            files_to_copy[arcpath] = abspath
-
-    # `packages` attribute contains a dictionnary of dictionnary
-    # of all packages sections directories
-    for packageName in harness_options['packages']:
-      base_arcpath = ZIPSEP.join(['resources', packageName])
-      # Eventually strip sdk files.
-      if not bundle_sdk and packageName == 'addon-sdk':
-          continue
-      # Always write the top directory, even if it contains no files, since
-      # the harness will try to access it.
-      dirs_to_create.add(base_arcpath)
-      for sectionName in harness_options['packages'][packageName]:
-        abs_dirname = harness_options['packages'][packageName][sectionName]
-        base_arcpath = ZIPSEP.join(['resources', packageName, sectionName])
-        # Always write the top directory, even if it contains no files, since
-        # the harness will try to access it.
-        dirs_to_create.add(base_arcpath)
-        # cp -r stuff from abs_dirname/ into ZIP/resources/RESOURCEBASE/
-        for dirpath, dirnames, filenames in os.walk(abs_dirname):
-            goodfiles = list(filter_filenames(filenames, IGNORED_FILES))
-            dirnames[:] = filter_dirnames(dirnames)
-            for filename in goodfiles:
-                abspath = os.path.join(dirpath, filename)
-                if limit_to is not None and abspath not in limit_to:
-                    continue  # strip unused files
-                arcpath = ZIPSEP.join(
-                    ['resources',
-                     packageName,
-                     sectionName,
-                     make_zipfile_path(abs_dirname,
-                                       os.path.join(dirpath, filename)),
-                     ])
-                files_to_copy[str(arcpath)] = str(abspath)
-    del harness_options['packages']
-
-    locales_json_data = {"locales": []}
-    mkzipdir(zf, "locale/")
-    for language in sorted(harness_options['locale']):
-        locales_json_data["locales"].append(language)
-        locale = harness_options['locale'][language]
-        # Be carefull about strings, we need to always ensure working with UTF-8
-        jsonStr = json.dumps(locale, indent=1, sort_keys=True, ensure_ascii=False)
-        info = zipfile.ZipInfo('locale/' + language + '.json')
-        info.external_attr = 0644 << 16L
-        zf.writestr(info, jsonStr.encode( "utf-8" ))
-    del harness_options['locale']
-
-    jsonStr = json.dumps(locales_json_data, ensure_ascii=True) +"\n"
-    info = zipfile.ZipInfo('locales.json')
-    info.external_attr = 0644 << 16L
-    zf.writestr(info, jsonStr.encode("utf-8"))
-
-    # now figure out which directories we need: all retained files parents
-    for arcpath in files_to_copy:
-        bits = arcpath.split("/")
-        for i in range(1,len(bits)):
-            parentpath = ZIPSEP.join(bits[0:i])
-            dirs_to_create.add(parentpath)
-
-    # Create zipfile in alphabetical order, with each directory before its
-    # files
-    for name in sorted(dirs_to_create.union(set(files_to_copy))):
-        if name in dirs_to_create:
-            mkzipdir(zf, name+"/")
-        if name in files_to_copy:
-            zf.write(files_to_copy[name], name)
-
-    # Add extra harness options
-    harness_options = harness_options.copy()
-    for key,value in extra_harness_options.items():
-        if key in harness_options:
-            msg = "Can't use --harness-option for existing key '%s'" % key
-            raise HarnessOptionAlreadyDefinedError(msg)
-        harness_options[key] = value
-
-    # Write harness-options.json
-    zf.writestr('harness-options.json', json.dumps(harness_options, indent=1,
-                                                   sort_keys=True))
-
-    zf.close()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/jetpack_sdk_env.py
+++ /dev/null
@@ -1,66 +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/.
-
-import sys
-import os
-
-def welcome():
-    """
-    Perform a bunch of sanity tests to make sure the Add-on SDK
-    environment is sane, and then display a welcome message.
-    """
-
-    try:
-        if sys.version_info[0] > 2:
-            print ("Error: You appear to be using Python %d, but "
-                   "the Add-on SDK only supports the Python 2.x line." %
-                   (sys.version_info[0]))
-            return
-
-        import mozrunner
-
-        if 'CUDDLEFISH_ROOT' not in os.environ:
-            print ("Error: CUDDLEFISH_ROOT environment variable does "
-                   "not exist! It should point to the root of the "
-                   "Add-on SDK repository.")
-            return
-
-        env_root = os.environ['CUDDLEFISH_ROOT']
-
-        bin_dir = os.path.join(env_root, 'bin')
-        python_lib_dir = os.path.join(env_root, 'python-lib')
-        path = os.environ['PATH'].split(os.path.pathsep)
-
-        if bin_dir not in path:
-            print ("Warning: the Add-on SDK binary directory %s "
-                   "does not appear to be in your PATH. You may "
-                   "not be able to run 'cfx' or other SDK tools." %
-                   bin_dir)
-
-        if python_lib_dir not in sys.path:
-            print ("Warning: the Add-on SDK python-lib directory %s "
-                   "does not appear to be in your sys.path, which "
-                   "is odd because I'm running from it." % python_lib_dir)
-
-        if not mozrunner.__path__[0].startswith(env_root):
-            print ("Warning: your mozrunner package is installed at %s, "
-                   "which does not seem to be located inside the Jetpack "
-                   "SDK. This may cause problems, and you may want to "
-                   "uninstall the other version. See bug 556562 for "
-                   "more information." % mozrunner.__path__[0])
-    except Exception:
-        # Apparently we can't get the actual exception object in the
-        # 'except' clause in a way that's syntax-compatible for both
-        # Python 2.x and 3.x, so we'll have to use the traceback module.
-
-        import traceback
-        _, e, _ = sys.exc_info()
-        print ("Verification of Add-on SDK environment failed (%s)." % e)
-        print ("Your SDK may not work properly.")
-        return
-
-    print ("Welcome to the Add-on SDK. For the docs, visit https://developer.mozilla.org/en-US/Add-ons/SDK")
-
-if __name__ == '__main__':
-    welcome()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/mozrunner/__init__.py
+++ /dev/null
@@ -1,694 +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/.
-
-import os
-import sys
-import copy
-import tempfile
-import signal
-import commands
-import zipfile
-import optparse
-import killableprocess
-import subprocess
-import platform
-import shutil
-from StringIO import StringIO
-from xml.dom import minidom
-
-from distutils import dir_util
-from time import sleep
-
-# conditional (version-dependent) imports
-try:
-    import simplejson
-except ImportError:
-    import json as simplejson
-
-import logging
-logger = logging.getLogger(__name__)
-
-# Use dir_util for copy/rm operations because shutil is all kinds of broken
-copytree = dir_util.copy_tree
-rmtree = dir_util.remove_tree
-
-def findInPath(fileName, path=os.environ['PATH']):
-    dirs = path.split(os.pathsep)
-    for dir in dirs:
-        if os.path.isfile(os.path.join(dir, fileName)):
-            return os.path.join(dir, fileName)
-        if os.name == 'nt' or sys.platform == 'cygwin':
-            if os.path.isfile(os.path.join(dir, fileName + ".exe")):
-                return os.path.join(dir, fileName + ".exe")
-    return None
-
-stdout = sys.stdout
-stderr = sys.stderr
-stdin = sys.stdin
-
-def run_command(cmd, env=None, **kwargs):
-    """Run the given command in killable process."""
-    killable_kwargs = {'stdout':stdout ,'stderr':stderr, 'stdin':stdin}
-    killable_kwargs.update(kwargs)
-
-    if sys.platform != "win32":
-        return killableprocess.Popen(cmd, preexec_fn=lambda : os.setpgid(0, 0),
-                                     env=env, **killable_kwargs)
-    else:
-        return killableprocess.Popen(cmd, env=env, **killable_kwargs)
-
-def getoutput(l):
-    tmp = tempfile.mktemp()
-    x = open(tmp, 'w')
-    subprocess.call(l, stdout=x, stderr=x)
-    x.close(); x = open(tmp, 'r')
-    r = x.read() ; x.close()
-    os.remove(tmp)
-    return r
-
-def get_pids(name, minimun_pid=0):
-    """Get all the pids matching name, exclude any pids below minimum_pid."""
-    if os.name == 'nt' or sys.platform == 'cygwin':
-        import wpk
-
-        pids = wpk.get_pids(name)
-
-    else:
-        data = getoutput(['ps', 'ax']).splitlines()
-        pids = [int(line.split()[0]) for line in data if line.find(name) is not -1]
-
-    matching_pids = [m for m in pids if m > minimun_pid]
-    return matching_pids
-
-def makedirs(name):
-
-    head, tail = os.path.split(name)
-    if not tail:
-        head, tail = os.path.split(head)
-    if head and tail and not os.path.exists(head):
-        try:
-            makedirs(head)
-        except OSError, e:
-            pass
-        if tail == os.curdir:           # xxx/newdir/. exists if xxx/newdir exists
-            return
-    try:
-        os.mkdir(name)
-    except:
-        pass
-
-# addon_details() copied from mozprofile
-def addon_details(install_rdf_fh):
-    """
-    returns a dictionary of details about the addon
-    - addon_path : path to the addon directory
-    Returns:
-    {'id':      u'rainbow@colors.org', # id of the addon
-     'version': u'1.4',                # version of the addon
-     'name':    u'Rainbow',            # name of the addon
-     'unpack': # whether to unpack the addon
-    """
-
-    details = {
-        'id': None,
-        'unpack': False,
-        'name': None,
-        'version': None
-    }
-
-    def get_namespace_id(doc, url):
-        attributes = doc.documentElement.attributes
-        namespace = ""
-        for i in range(attributes.length):
-            if attributes.item(i).value == url:
-                if ":" in attributes.item(i).name:
-                    # If the namespace is not the default one remove 'xlmns:'
-                    namespace = attributes.item(i).name.split(':')[1] + ":"
-                    break
-        return namespace
-
-    def get_text(element):
-        """Retrieve the text value of a given node"""
-        rc = []
-        for node in element.childNodes:
-            if node.nodeType == node.TEXT_NODE:
-                rc.append(node.data)
-        return ''.join(rc).strip()
-
-    doc = minidom.parse(install_rdf_fh)
-
-    # Get the namespaces abbreviations
-    em = get_namespace_id(doc, "http://www.mozilla.org/2004/em-rdf#")
-    rdf = get_namespace_id(doc, "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
-
-    description = doc.getElementsByTagName(rdf + "Description").item(0)
-    for node in description.childNodes:
-        # Remove the namespace prefix from the tag for comparison
-        entry = node.nodeName.replace(em, "")
-        if entry in details.keys():
-            details.update({ entry: get_text(node) })
-
-    # turn unpack into a true/false value
-    if isinstance(details['unpack'], basestring):
-        details['unpack'] = details['unpack'].lower() == 'true'
-
-    return details
-
-class Profile(object):
-    """Handles all operations regarding profile. Created new profiles, installs extensions,
-    sets preferences and handles cleanup."""
-
-    def __init__(self, binary=None, profile=None, addons=None,
-                 preferences=None):
-
-        self.binary = binary
-
-        self.create_new = not(bool(profile))
-        if profile:
-            self.profile = profile
-        else:
-            self.profile = self.create_new_profile(self.binary)
-
-        self.addons_installed = []
-        self.addons = addons or []
-
-        ### set preferences from class preferences
-        preferences = preferences or {}
-        if hasattr(self.__class__, 'preferences'):
-            self.preferences = self.__class__.preferences.copy()
-        else:
-            self.preferences = {}
-        self.preferences.update(preferences)
-
-        for addon in self.addons:
-            self.install_addon(addon)
-
-        self.set_preferences(self.preferences)
-
-    def create_new_profile(self, binary):
-        """Create a new clean profile in tmp which is a simple empty folder"""
-        profile = tempfile.mkdtemp(suffix='.mozrunner')
-        return profile
-
-    def unpack_addon(self, xpi_zipfile, addon_path):
-        for name in xpi_zipfile.namelist():
-            if name.endswith('/'):
-                makedirs(os.path.join(addon_path, name))
-            else:
-                if not os.path.isdir(os.path.dirname(os.path.join(addon_path, name))):
-                    makedirs(os.path.dirname(os.path.join(addon_path, name)))
-                data = xpi_zipfile.read(name)
-                f = open(os.path.join(addon_path, name), 'wb')
-                f.write(data) ; f.close()
-                zi = xpi_zipfile.getinfo(name)
-                os.chmod(os.path.join(addon_path,name), (zi.external_attr>>16))
-
-    def install_addon(self, path):
-        """Installs the given addon or directory of addons in the profile."""
-
-        extensions_path = os.path.join(self.profile, 'extensions')
-        if not os.path.exists(extensions_path):
-            os.makedirs(extensions_path)
-
-        addons = [path]
-        if not path.endswith('.xpi') and not os.path.exists(os.path.join(path, 'install.rdf')):
-            addons = [os.path.join(path, x) for x in os.listdir(path)]
-
-        for addon in addons:
-            if addon.endswith('.xpi'):
-                xpi_zipfile = zipfile.ZipFile(addon, "r")
-                details = addon_details(StringIO(xpi_zipfile.read('install.rdf')))
-                addon_path = os.path.join(extensions_path, details["id"])
-                if details.get("unpack", True):
-                    self.unpack_addon(xpi_zipfile, addon_path)
-                    self.addons_installed.append(addon_path)
-                else:
-                    shutil.copy(addon, addon_path + '.xpi')
-            else:
-                # it's already unpacked, but we need to extract the id so we
-                # can copy it
-                details = addon_details(open(os.path.join(addon, "install.rdf"), "rb"))
-                addon_path = os.path.join(extensions_path, details["id"])
-                shutil.copytree(addon, addon_path, symlinks=True)
-
-    def set_preferences(self, preferences):
-        """Adds preferences dict to profile preferences"""
-        prefs_file = os.path.join(self.profile, 'user.js')
-        # Ensure that the file exists first otherwise create an empty file
-        if os.path.isfile(prefs_file):
-            f = open(prefs_file, 'a+')
-        else:
-            f = open(prefs_file, 'w')
-
-        f.write('\n#MozRunner Prefs Start\n')
-
-        pref_lines = ['user_pref(%s, %s);' %
-                      (simplejson.dumps(k), simplejson.dumps(v) ) for k, v in
-                       preferences.items()]
-        for line in pref_lines:
-            f.write(line+'\n')
-        f.write('#MozRunner Prefs End\n')
-        f.flush() ; f.close()
-
-    def pop_preferences(self):
-        """
-        pop the last set of preferences added
-        returns True if popped
-        """
-
-        # our magic markers
-        delimeters = ('#MozRunner Prefs Start', '#MozRunner Prefs End')
-
-        lines = file(os.path.join(self.profile, 'user.js')).read().splitlines()
-        def last_index(_list, value):
-            """
-            returns the last index of an item;
-            this should actually be part of python code but it isn't
-            """
-            for index in reversed(range(len(_list))):
-                if _list[index] == value:
-                    return index
-        s = last_index(lines, delimeters[0])
-        e = last_index(lines, delimeters[1])
-
-        # ensure both markers are found
-        if s is None:
-            assert e is None, '%s found without %s' % (delimeters[1], delimeters[0])
-            return False # no preferences found
-        elif e is None:
-            assert e is None, '%s found without %s' % (delimeters[0], delimeters[1])
-
-        # ensure the markers are in the proper order
-        assert e > s, '%s found at %s, while %s found at %s' (delimeter[1], e, delimeter[0], s)
-
-        # write the prefs
-        cleaned_prefs = '\n'.join(lines[:s] + lines[e+1:])
-        f = file(os.path.join(self.profile, 'user.js'), 'w')
-        f.write(cleaned_prefs)
-        f.close()
-        return True
-
-    def clean_preferences(self):
-        """Removed preferences added by mozrunner."""
-        while True:
-            if not self.pop_preferences():
-                break
-
-    def clean_addons(self):
-        """Cleans up addons in the profile."""
-        for addon in self.addons_installed:
-            if os.path.isdir(addon):
-                rmtree(addon)
-
-    def cleanup(self):
-        """Cleanup operations on the profile."""
-        def oncleanup_error(function, path, excinfo):
-            #TODO: How should we handle this?
-            print "Error Cleaning up: " + str(excinfo[1])
-        if self.create_new:
-            shutil.rmtree(self.profile, False, oncleanup_error)
-        else:
-            self.clean_preferences()
-            self.clean_addons()
-
-class FirefoxProfile(Profile):
-    """Specialized Profile subclass for Firefox"""
-    preferences = {# Don't automatically update the application
-                   'app.update.enabled' : False,
-                   # Don't restore the last open set of tabs if the browser has crashed
-                   'browser.sessionstore.resume_from_crash': False,
-                   # Don't check for the default web browser
-                   'browser.shell.checkDefaultBrowser' : False,
-                   # Don't warn on exit when multiple tabs are open
-                   'browser.tabs.warnOnClose' : False,
-                   # Don't warn when exiting the browser
-                   'browser.warnOnQuit': False,
-                   # Only install add-ons from the profile and the app folder
-                   'extensions.enabledScopes' : 5,
-                   # Don't automatically update add-ons
-                   'extensions.update.enabled'    : False,
-                   # Don't open a dialog to show available add-on updates
-                   'extensions.update.notifyUser' : False,
-                   }
-
-    # The possible names of application bundles on Mac OS X, in order of
-    # preference from most to least preferred.
-    # Note: Nightly is obsolete, as it has been renamed to FirefoxNightly,
-    # but it will still be present if users update an older nightly build
-    # via the app update service.
-    bundle_names = ['Firefox', 'FirefoxNightly', 'Nightly']
-
-    # The possible names of binaries, in order of preference from most to least
-    # preferred.
-    @property
-    def names(self):
-        if sys.platform == 'darwin':
-            return ['firefox', 'nightly', 'shiretoko']
-        if (sys.platform == 'linux2') or (sys.platform in ('sunos5', 'solaris')):
-            return ['firefox', 'mozilla-firefox', 'iceweasel']
-        if os.name == 'nt' or sys.platform == 'cygwin':
-            return ['firefox']
-
-class ThunderbirdProfile(Profile):
-    preferences = {'extensions.update.enabled'    : False,
-                   'extensions.update.notifyUser' : False,
-                   'browser.shell.checkDefaultBrowser' : False,
-                   'browser.tabs.warnOnClose' : False,
-                   'browser.warnOnQuit': False,
-                   'browser.sessionstore.resume_from_crash': False,
-                   }
-
-    # The possible names of application bundles on Mac OS X, in order of
-    # preference from most to least preferred.
-    bundle_names = ["Thunderbird", "Shredder"]
-
-    # The possible names of binaries, in order of preference from most to least
-    # preferred.
-    names = ["thunderbird", "shredder"]
-
-
-class Runner(object):
-    """Handles all running operations. Finds bins, runs and kills the process."""
-
-    def __init__(self, binary=None, profile=None, cmdargs=[], env=None,
-                 kp_kwargs={}):
-        if binary is None:
-            self.binary = self.find_binary()
-        elif sys.platform == 'darwin' and binary.find('Contents/MacOS/') == -1:
-            self.binary = os.path.join(binary, 'Contents/MacOS/%s-bin' % self.names[0])
-        else:
-            self.binary = binary
-
-        if not os.path.exists(self.binary):
-            raise Exception("Binary path does not exist "+self.binary)
-
-        if sys.platform == 'linux2' and self.binary.endswith('-bin'):
-            dirname = os.path.dirname(self.binary)
-            if os.environ.get('LD_LIBRARY_PATH', None):
-                os.environ['LD_LIBRARY_PATH'] = '%s:%s' % (os.environ['LD_LIBRARY_PATH'], dirname)
-            else:
-                os.environ['LD_LIBRARY_PATH'] = dirname
-
-        # Disable the crash reporter by default
-        os.environ['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
-
-        self.profile = profile
-
-        self.cmdargs = cmdargs
-        if env is None:
-            self.env = copy.copy(os.environ)
-            self.env.update({'MOZ_NO_REMOTE':"1",})
-        else:
-            self.env = env
-        self.kp_kwargs = kp_kwargs or {}
-
-    def find_binary(self):
-        """Finds the binary for self.names if one was not provided."""
-        binary = None
-        if sys.platform in ('linux2', 'sunos5', 'solaris') \
-                or sys.platform.startswith('freebsd'):
-            for name in reversed(self.names):
-                binary = findInPath(name)
-        elif os.name == 'nt' or sys.platform == 'cygwin':
-
-            # find the default executable from the windows registry
-            try:
-                import _winreg
-            except ImportError:
-                pass
-            else:
-                sam_flags = [0]
-                # KEY_WOW64_32KEY etc only appeared in 2.6+, but that's OK as
-                # only 2.6+ has functioning 64bit builds.
-                if hasattr(_winreg, "KEY_WOW64_32KEY"):
-                    if "64 bit" in sys.version:
-                        # a 64bit Python should also look in the 32bit registry
-                        sam_flags.append(_winreg.KEY_WOW64_32KEY)
-                    else:
-                        # possibly a 32bit Python on 64bit Windows, so look in
-                        # the 64bit registry incase there is a 64bit app.
-                        sam_flags.append(_winreg.KEY_WOW64_64KEY)
-                for sam_flag in sam_flags:
-                    try:
-                        # assumes self.app_name is defined, as it should be for
-                        # implementors
-                        keyname = r"Software\Mozilla\Mozilla %s" % self.app_name
-                        sam = _winreg.KEY_READ | sam_flag
-                        app_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname, 0, sam)
-                        version, _type = _winreg.QueryValueEx(app_key, "CurrentVersion")
-                        version_key = _winreg.OpenKey(app_key, version + r"\Main")
-                        path, _ = _winreg.QueryValueEx(version_key, "PathToExe")
-                        return path
-                    except _winreg.error:
-                        pass
-
-            # search for the binary in the path            
-            for name in reversed(self.names):
-                binary = findInPath(name)
-                if sys.platform == 'cygwin':
-                    program_files = os.environ['PROGRAMFILES']
-                else:
-                    program_files = os.environ['ProgramFiles']
-
-                if binary is None:
-                    for bin in [(program_files, 'Mozilla Firefox', 'firefox.exe'),
-                                (os.environ.get("ProgramFiles(x86)"),'Mozilla Firefox', 'firefox.exe'),
-                                (program_files, 'Nightly', 'firefox.exe'),
-                                (os.environ.get("ProgramFiles(x86)"),'Nightly', 'firefox.exe'),
-                                (program_files, 'Aurora', 'firefox.exe'),
-                                (os.environ.get("ProgramFiles(x86)"),'Aurora', 'firefox.exe')
-                                ]:
-                        path = os.path.join(*bin)
-                        if os.path.isfile(path):
-                            binary = path
-                            break
-        elif sys.platform == 'darwin':
-            for bundle_name in self.bundle_names:
-                # Look for the application bundle in the user's home directory
-                # or the system-wide /Applications directory.  If we don't find
-                # it in one of those locations, we move on to the next possible
-                # bundle name.
-                appdir = os.path.join("~/Applications/%s.app" % bundle_name)
-                if not os.path.isdir(appdir):
-                    appdir = "/Applications/%s.app" % bundle_name
-                if not os.path.isdir(appdir):
-                    continue
-
-                # Look for a binary with any of the possible binary names
-                # inside the application bundle.
-                for binname in self.names:
-                    binpath = os.path.join(appdir,
-                                           "Contents/MacOS/%s-bin" % binname)
-                    if (os.path.isfile(binpath)):
-                        binary = binpath
-                        break
-
-                if binary:
-                    break
-
-        if binary is None:
-            raise Exception('Mozrunner could not locate your binary, you will need to set it.')
-        return binary
-
-    @property
-    def command(self):
-        """Returns the command list to run."""
-        cmd = [self.binary, '-profile', self.profile.profile]
-        # On i386 OS X machines, i386+x86_64 universal binaries need to be told
-        # to run as i386 binaries.  If we're not running a i386+x86_64 universal
-        # binary, then this command modification is harmless.
-        if sys.platform == 'darwin':
-            if hasattr(platform, 'architecture') and platform.architecture()[0] == '32bit':
-                cmd = ['arch', '-i386'] + cmd
-        return cmd
-
-    def get_repositoryInfo(self):
-        """Read repository information from application.ini and platform.ini."""
-        import ConfigParser
-
-        config = ConfigParser.RawConfigParser()
-        dirname = os.path.dirname(self.binary)
-        repository = { }
-
-        for entry in [['application', 'App'], ['platform', 'Build']]:
-            (file, section) = entry
-            config.read(os.path.join(dirname, '%s.ini' % file))
-
-            for entry in [['SourceRepository', 'repository'], ['SourceStamp', 'changeset']]:
-                (key, id) = entry
-
-                try:
-                    repository['%s_%s' % (file, id)] = config.get(section, key);
-                except:
-                    repository['%s_%s' % (file, id)] = None
-
-        return repository
-
-    def start(self):
-        """Run self.command in the proper environment."""
-        if self.profile is None:
-            self.profile = self.profile_class()
-        self.process_handler = run_command(self.command+self.cmdargs, self.env, **self.kp_kwargs)
-
-    def wait(self, timeout=None):
-        """Wait for the browser to exit."""
-        self.process_handler.wait(timeout=timeout)
-
-        if sys.platform != 'win32':
-            for name in self.names:
-                for pid in get_pids(name, self.process_handler.pid):
-                    self.process_handler.pid = pid
-                    self.process_handler.wait(timeout=timeout)
-
-    def kill(self, kill_signal=signal.SIGTERM):
-        """Kill the browser"""
-        if sys.platform != 'win32':
-            self.process_handler.kill()
-            for name in self.names:
-                for pid in get_pids(name, self.process_handler.pid):
-                    self.process_handler.pid = pid
-                    self.process_handler.kill()
-        else:
-            try:
-                self.process_handler.kill(group=True)
-                # On windows, it sometimes behooves one to wait for dust to settle
-                # after killing processes.  Let's try that.
-                # TODO: Bug 640047 is invesitgating the correct way to handle this case
-                self.process_handler.wait(timeout=10)
-            except Exception, e:
-                logger.error('Cannot kill process, '+type(e).__name__+' '+e.message)
-
-    def stop(self):
-        self.kill()
-
-class FirefoxRunner(Runner):
-    """Specialized Runner subclass for running Firefox."""
-
-    app_name = 'Firefox'
-    profile_class = FirefoxProfile
-
-    # The possible names of application bundles on Mac OS X, in order of
-    # preference from most to least preferred.
-    # Note: Nightly is obsolete, as it has been renamed to FirefoxNightly,
-    # but it will still be present if users update an older nightly build
-    # only via the app update service.
-    bundle_names = ['Firefox', 'FirefoxNightly', 'Nightly']
-
-    @property
-    def names(self):
-        if sys.platform == 'darwin':
-            return ['firefox', 'nightly', 'shiretoko']
-        if sys.platform in ('linux2', 'sunos5', 'solaris') \
-                or sys.platform.startswith('freebsd'):
-            return ['firefox', 'mozilla-firefox', 'iceweasel']
-        if os.name == 'nt' or sys.platform == 'cygwin':
-            return ['firefox']
-
-class ThunderbirdRunner(Runner):
-    """Specialized Runner subclass for running Thunderbird"""
-
-    app_name = 'Thunderbird'
-    profile_class = ThunderbirdProfile
-
-    # The possible names of application bundles on Mac OS X, in order of
-    # preference from most to least preferred.
-    bundle_names = ["Thunderbird", "Shredder"]
-
-    # The possible names of binaries, in order of preference from most to least
-    # preferred.
-    names = ["thunderbird", "shredder"]
-
-class CLI(object):
-    """Command line interface."""
-
-    runner_class = FirefoxRunner
-    profile_class = FirefoxProfile
-    module = "mozrunner"
-
-    parser_options = {("-b", "--binary",): dict(dest="binary", help="Binary path.",
-                                                metavar=None, default=None),
-                      ('-p', "--profile",): dict(dest="profile", help="Profile path.",
-                                                 metavar=None, default=None),
-                      ('-a', "--addons",): dict(dest="addons", 
-                                                help="Addons paths to install.",
-                                                metavar=None, default=None),
-                      ("--info",): dict(dest="info", default=False,
-                                        action="store_true",
-                                        help="Print module information")
-                     }
-
-    def __init__(self):
-        """ Setup command line parser and parse arguments """
-        self.metadata = self.get_metadata_from_egg()
-        self.parser = optparse.OptionParser(version="%prog " + self.metadata["Version"])
-        for names, opts in self.parser_options.items():
-            self.parser.add_option(*names, **opts)
-        (self.options, self.args) = self.parser.parse_args()
-
-        if self.options.info:
-            self.print_metadata()
-            sys.exit(0)
-            
-        # XXX should use action='append' instead of rolling our own
-        try:
-            self.addons = self.options.addons.split(',')
-        except:
-            self.addons = []
-            
-    def get_metadata_from_egg(self):
-        import pkg_resources
-        ret = {}
-        dist = pkg_resources.get_distribution(self.module)
-        if dist.has_metadata("PKG-INFO"):
-            for line in dist.get_metadata_lines("PKG-INFO"):
-                key, value = line.split(':', 1)
-                ret[key] = value
-        if dist.has_metadata("requires.txt"):
-            ret["Dependencies"] = "\n" + dist.get_metadata("requires.txt")    
-        return ret
-        
-    def print_metadata(self, data=("Name", "Version", "Summary", "Home-page", 
-                                   "Author", "Author-email", "License", "Platform", "Dependencies")):
-        for key in data:
-            if key in self.metadata:
-                print key + ": " + self.metadata[key]
-
-    def create_runner(self):
-        """ Get the runner object """
-        runner = self.get_runner(binary=self.options.binary)
-        profile = self.get_profile(binary=runner.binary,
-                                   profile=self.options.profile,
-                                   addons=self.addons)
-        runner.profile = profile
-        return runner
-
-    def get_runner(self, binary=None, profile=None):
-        """Returns the runner instance for the given command line binary argument
-        the profile instance returned from self.get_profile()."""
-        return self.runner_class(binary, profile)
-
-    def get_profile(self, binary=None, profile=None, addons=None, preferences=None):
-        """Returns the profile instance for the given command line arguments."""
-        addons = addons or []
-        preferences = preferences or {}
-        return self.profile_class(binary, profile, addons, preferences)
-
-    def run(self):
-        runner = self.create_runner()
-        self.start(runner)
-        runner.profile.cleanup()
-
-    def start(self, runner):
-        """Starts the runner and waits for Firefox to exitor Keyboard Interrupt.
-        Shoule be overwritten to provide custom running of the runner instance."""
-        runner.start()
-        print 'Started:', ' '.join(runner.command)
-        try:
-            runner.wait()
-        except KeyboardInterrupt:
-            runner.stop()
-
-
-def cli():
-    CLI().run()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/mozrunner/killableprocess.py
+++ /dev/null
@@ -1,329 +0,0 @@
-# killableprocess - subprocesses which can be reliably killed
-#
-# Parts of this module are copied from the subprocess.py file contained
-# in the Python distribution.
-#
-# Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
-#
-# Additions and modifications written by Benjamin Smedberg
-# <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
-# <http://www.mozilla.org/>
-#
-# More Modifications
-# Copyright (c) 2006-2007 by Mike Taylor <bear@code-bear.com>
-# Copyright (c) 2007-2008 by Mikeal Rogers <mikeal@mozilla.com>
-#
-# By obtaining, using, and/or copying this software and/or its
-# associated documentation, you agree that you have read, understood,
-# and will comply with the following terms and conditions:
-#
-# Permission to use, copy, modify, and distribute this software and
-# its associated documentation for any purpose and without fee is
-# hereby granted, provided that the above copyright notice appears in
-# all copies, and that both that copyright notice and this permission
-# notice appear in supporting documentation, and that the name of the
-# author not be used in advertising or publicity pertaining to
-# distribution of the software without specific, written prior
-# permission.
-#
-# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-"""killableprocess - Subprocesses which can be reliably killed
-
-This module is a subclass of the builtin "subprocess" module. It allows
-processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
-
-It also adds a timeout argument to Wait() for a limited period of time before
-forcefully killing the process.
-
-Note: On Windows, this module requires Windows 2000 or higher (no support for
-Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
-Python 2.5+ or available from http://python.net/crew/theller/ctypes/
-"""
-
-import subprocess
-import sys
-import os
-import time
-import datetime
-import types
-import exceptions
-
-try:
-    from subprocess import CalledProcessError
-except ImportError:
-    # Python 2.4 doesn't implement CalledProcessError
-    class CalledProcessError(Exception):
-        """This exception is raised when a process run by check_call() returns
-        a non-zero exit status. The exit status will be stored in the
-        returncode attribute."""
-        def __init__(self, returncode, cmd):
-            self.returncode = returncode
-            self.cmd = cmd
-        def __str__(self):
-            return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
-
-mswindows = (sys.platform == "win32")
-
-if mswindows:
-    import winprocess
-else:
-    import signal
-
-# This is normally defined in win32con, but we don't want
-# to incur the huge tree of dependencies (pywin32 and friends)
-# just to get one constant.  So here's our hack
-STILL_ACTIVE = 259
-
-def call(*args, **kwargs):
-    waitargs = {}
-    if "timeout" in kwargs:
-        waitargs["timeout"] = kwargs.pop("timeout")
-
-    return Popen(*args, **kwargs).wait(**waitargs)
-
-def check_call(*args, **kwargs):
-    """Call a program with an optional timeout. If the program has a non-zero
-    exit status, raises a CalledProcessError."""
-
-    retcode = call(*args, **kwargs)
-    if retcode:
-        cmd = kwargs.get("args")
-        if cmd is None:
-            cmd = args[0]
-        raise CalledProcessError(retcode, cmd)
-
-if not mswindows:
-    def DoNothing(*args):
-        pass
-
-class Popen(subprocess.Popen):
-    kill_called = False
-    if mswindows:
-        def _execute_child(self, *args_tuple):
-            # workaround for bug 958609
-            if sys.hexversion < 0x02070600: # prior to 2.7.6
-                (args, executable, preexec_fn, close_fds,
-                    cwd, env, universal_newlines, startupinfo,
-                    creationflags, shell,
-                    p2cread, p2cwrite,
-                    c2pread, c2pwrite,
-                    errread, errwrite) = args_tuple
-                to_close = set()
-            else: # 2.7.6 and later
-                (args, executable, preexec_fn, close_fds,
-                    cwd, env, universal_newlines, startupinfo,
-                    creationflags, shell, to_close,
-                    p2cread, p2cwrite,
-                    c2pread, c2pwrite,
-                    errread, errwrite) = args_tuple
-
-            if not isinstance(args, types.StringTypes):
-                args = subprocess.list2cmdline(args)
-
-            # Always or in the create new process group
-            creationflags |= winprocess.CREATE_NEW_PROCESS_GROUP
-
-            if startupinfo is None:
-                startupinfo = winprocess.STARTUPINFO()
-
-            if None not in (p2cread, c2pwrite, errwrite):
-                startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
-
-                startupinfo.hStdInput = int(p2cread)
-                startupinfo.hStdOutput = int(c2pwrite)
-                startupinfo.hStdError = int(errwrite)
-            if shell:
-                startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
-                startupinfo.wShowWindow = winprocess.SW_HIDE
-                comspec = os.environ.get("COMSPEC", "cmd.exe")
-                args = comspec + " /c " + args
-
-            # determine if we can create create a job
-            canCreateJob = winprocess.CanCreateJobObject()
-
-            # set process creation flags
-            creationflags |= winprocess.CREATE_SUSPENDED
-            creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
-            if canCreateJob:
-                # Uncomment this line below to discover very useful things about your environment
-                #print "++++ killableprocess: releng twistd patch not applied, we can create job objects"
-                creationflags |= winprocess.CREATE_BREAKAWAY_FROM_JOB
-
-            # create the process
-            hp, ht, pid, tid = winprocess.CreateProcess(
-                executable, args,
-                None, None, # No special security
-                1, # Must inherit handles!
-                creationflags,
-                winprocess.EnvironmentBlock(env),
-                cwd, startupinfo)
-            self._child_created = True
-            self._handle = hp
-            self._thread = ht
-            self.pid = pid
-            self.tid = tid
-
-            if canCreateJob:
-                # We create a new job for this process, so that we can kill
-                # the process and any sub-processes
-                self._job = winprocess.CreateJobObject()
-                winprocess.AssignProcessToJobObject(self._job, int(hp))
-            else:
-                self._job = None
-
-            winprocess.ResumeThread(int(ht))
-            ht.Close()
-
-            if p2cread is not None:
-                p2cread.Close()
-            if c2pwrite is not None:
-                c2pwrite.Close()
-            if errwrite is not None:
-                errwrite.Close()
-            time.sleep(.1)
-
-    def kill(self, group=True):
-        """Kill the process. If group=True, all sub-processes will also be killed."""
-        self.kill_called = True
-
-        if mswindows:
-            if group and self._job:
-                winprocess.TerminateJobObject(self._job, 127)
-            else:
-                winprocess.TerminateProcess(self._handle, 127)
-            self.returncode = 127
-        else:
-            if group:
-                try:
-                    os.killpg(self.pid, signal.SIGKILL)
-                except: pass
-            else:
-                os.kill(self.pid, signal.SIGKILL)
-            self.returncode = -9
-
-    def wait(self, timeout=None, group=True):
-        """Wait for the process to terminate. Returns returncode attribute.
-        If timeout seconds are reached and the process has not terminated,
-        it will be forcefully killed. If timeout is -1, wait will not
-        time out."""
-        if timeout is not None:
-            # timeout is now in milliseconds
-            timeout = timeout * 1000
-
-        starttime = datetime.datetime.now()
-
-        if mswindows:
-            if timeout is None:
-                timeout = -1
-            rc = winprocess.WaitForSingleObject(self._handle, timeout)
-
-            if (rc == winprocess.WAIT_OBJECT_0 or
-                rc == winprocess.WAIT_ABANDONED or
-                rc == winprocess.WAIT_FAILED):
-                # Object has either signaled, or the API call has failed.  In 
-                # both cases we want to give the OS the benefit of the doubt
-                # and supply a little time before we start shooting processes
-                # with an M-16.
-
-                # Returns 1 if running, 0 if not, -1 if timed out
-                def check():
-                    now = datetime.datetime.now()
-                    diff = now - starttime
-                    if (diff.seconds * 1000000 + diff.microseconds) < (timeout * 1000):    # (1000*1000)
-                        if self._job:
-                            if (winprocess.QueryInformationJobObject(self._job, 8)['BasicInfo']['ActiveProcesses'] > 0):
-                                # Job Object is still containing active processes
-                                return 1
-                        else:
-                            # No job, we use GetExitCodeProcess, which will tell us if the process is still active
-                            self.returncode = winprocess.GetExitCodeProcess(self._handle)
-                            if (self.returncode == STILL_ACTIVE):
-                                # Process still active, continue waiting
-                                return 1
-                        # Process not active, return 0
-                        return 0
-                    else:
-                        # Timed out, return -1
-                        return -1
-
-                notdone = check()
-                while notdone == 1:
-                    time.sleep(.5)
-                    notdone = check()
-
-                if notdone == -1:
-                    # Then check timed out, we have a hung process, attempt
-                    # last ditch kill with explosives
-                    self.kill(group)
-                                
-            else:
-                # In this case waitforsingleobject timed out.  We have to
-                # take the process behind the woodshed and shoot it.
-                self.kill(group)
-
-        else:
-            if sys.platform in ('linux2', 'sunos5', 'solaris') \
-                    or sys.platform.startswith('freebsd'):
-                def group_wait(timeout):
-                    try:
-                        os.waitpid(self.pid, 0)
-                    except OSError, e:
-                        pass # If wait has already been called on this pid, bad things happen
-                    return self.returncode
-            elif sys.platform == 'darwin':
-                def group_wait(timeout):
-                    try:
-                        count = 0
-                        if timeout is None and self.kill_called:
-                            timeout = 10 # Have to set some kind of timeout or else this could go on forever
-                        if timeout is None:
-                            while 1:
-                                os.killpg(self.pid, signal.SIG_DFL)
-                        while ((count * 2) <= timeout):
-                            os.killpg(self.pid, signal.SIG_DFL)
-                            # count is increased by 500ms for every 0.5s of sleep
-                            time.sleep(.5); count += 500
-                    except exceptions.OSError:
-                        return self.returncode
-                        
-            if timeout is None:
-                if group is True:
-                    return group_wait(timeout)
-                else:
-                    subprocess.Popen.wait(self)
-                    return self.returncode
-
-            returncode = False
-
-            now = datetime.datetime.now()
-            diff = now - starttime
-            while (diff.seconds * 1000 * 1000 + diff.microseconds) < (timeout * 1000) and ( returncode is False ):
-                if group is True:
-                    return group_wait(timeout)
-                else:
-                    if subprocess.poll() is not None:
-                        returncode = self.returncode
-                time.sleep(.5)
-                now = datetime.datetime.now()
-                diff = now - starttime
-            return self.returncode
-
-        return self.returncode
-    # We get random maxint errors from subprocesses __del__
-    __del__ = lambda self: None        
-        
-def setpgid_preexec_fn():
-    os.setpgid(0, 0)
-   
-def runCommand(cmd, **kwargs):
-    if sys.platform != "win32":
-        return Popen(cmd, preexec_fn=setpgid_preexec_fn, **kwargs)
-    else:
-        return Popen(cmd, **kwargs)
deleted file mode 100644
--- a/addon-sdk/source/python-lib/mozrunner/qijo.py
+++ /dev/null
@@ -1,166 +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/.
-
-from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE, addressof, c_size_t, c_ulong
-from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LARGE_INTEGER
-
-LPVOID = c_void_p
-LPDWORD = POINTER(DWORD)
-SIZE_T = c_size_t
-ULONG_PTR = POINTER(c_ulong)
-
-# A ULONGLONG is a 64-bit unsigned integer.
-# Thus there are 8 bytes in a ULONGLONG.
-# XXX why not import c_ulonglong ?
-ULONGLONG = BYTE * 8
-
-class IO_COUNTERS(Structure):
-    # The IO_COUNTERS struct is 6 ULONGLONGs.
-    # TODO: Replace with non-dummy fields.
-    _fields_ = [('dummy', ULONGLONG * 6)]
-
-class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION(Structure):
-    _fields_ = [('TotalUserTime', LARGE_INTEGER),
-                ('TotalKernelTime', LARGE_INTEGER),
-                ('ThisPeriodTotalUserTime', LARGE_INTEGER),
-                ('ThisPeriodTotalKernelTime', LARGE_INTEGER),
-                ('TotalPageFaultCount', DWORD),
-                ('TotalProcesses', DWORD),
-                ('ActiveProcesses', DWORD),
-                ('TotalTerminatedProcesses', DWORD)]
-
-class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION(Structure):
-    _fields_ = [('BasicInfo', JOBOBJECT_BASIC_ACCOUNTING_INFORMATION),
-                ('IoInfo', IO_COUNTERS)]
-
-# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
-class JOBOBJECT_BASIC_LIMIT_INFORMATION(Structure):
-    _fields_ = [('PerProcessUserTimeLimit', LARGE_INTEGER),
-                ('PerJobUserTimeLimit', LARGE_INTEGER),
-                ('LimitFlags', DWORD),
-                ('MinimumWorkingSetSize', SIZE_T),
-                ('MaximumWorkingSetSize', SIZE_T),
-                ('ActiveProcessLimit', DWORD),
-                ('Affinity', ULONG_PTR),
-                ('PriorityClass', DWORD),
-                ('SchedulingClass', DWORD)
-                ]
-
-# see http://msdn.microsoft.com/en-us/library/ms684156%28VS.85%29.aspx
-class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(Structure):
-    _fields_ = [('BasicLimitInformation', JOBOBJECT_BASIC_LIMIT_INFORMATION),
-                ('IoInfo', IO_COUNTERS),
-                ('ProcessMemoryLimit', SIZE_T),
-                ('JobMemoryLimit', SIZE_T),
-                ('PeakProcessMemoryUsed', SIZE_T),
-                ('PeakJobMemoryUsed', SIZE_T)]
-
-# XXX Magical numbers like 8 should be documented
-JobObjectBasicAndIoAccountingInformation = 8
-
-# ...like magical number 9 comes from
-# http://community.flexerasoftware.com/archive/index.php?t-181670.html
-# I wish I had a more canonical source
-JobObjectExtendedLimitInformation = 9
-
-class JobObjectInfo(object):
-    mapping = { 'JobObjectBasicAndIoAccountingInformation': 8,
-                'JobObjectExtendedLimitInformation': 9
-                }
-    structures = { 8: JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION,
-                   9: JOBOBJECT_EXTENDED_LIMIT_INFORMATION
-                   }
-    def __init__(self, _class):
-        if isinstance(_class, basestring):
-            assert _class in self.mapping, 'Class should be one of %s; you gave %s' % (self.mapping, _class)
-            _class = self.mapping[_class]
-        assert _class in self.structures, 'Class should be one of %s; you gave %s' % (self.structures, _class)
-        self.code = _class
-        self.info = self.structures[_class]()
-    
-
-QueryInformationJobObjectProto = WINFUNCTYPE(
-    BOOL,        # Return type
-    HANDLE,      # hJob
-    DWORD,       # JobObjectInfoClass
-    LPVOID,      # lpJobObjectInfo
-    DWORD,       # cbJobObjectInfoLength
-    LPDWORD      # lpReturnLength
-    )
-
-QueryInformationJobObjectFlags = (
-    (1, 'hJob'),
-    (1, 'JobObjectInfoClass'),
-    (1, 'lpJobObjectInfo'),
-    (1, 'cbJobObjectInfoLength'),
-    (1, 'lpReturnLength', None)
-    )
-
-_QueryInformationJobObject = QueryInformationJobObjectProto(
-    ('QueryInformationJobObject', windll.kernel32),
-    QueryInformationJobObjectFlags
-    )
-
-class SubscriptableReadOnlyStruct(object):
-    def __init__(self, struct):
-        self._struct = struct
-
-    def _delegate(self, name):
-        result = getattr(self._struct, name)
-        if isinstance(result, Structure):
-            return SubscriptableReadOnlyStruct(result)
-        return result
-
-    def __getitem__(self, name):
-        match = [fname for fname, ftype in self._struct._fields_
-                 if fname == name]
-        if match:
-            return self._delegate(name)
-        raise KeyError(name)
-
-    def __getattr__(self, name):
-        return self._delegate(name)
-
-def QueryInformationJobObject(hJob, JobObjectInfoClass):
-    jobinfo = JobObjectInfo(JobObjectInfoClass)
-    result = _QueryInformationJobObject(
-        hJob=hJob,
-        JobObjectInfoClass=jobinfo.code,
-        lpJobObjectInfo=addressof(jobinfo.info),
-        cbJobObjectInfoLength=sizeof(jobinfo.info)
-        )
-    if not result:
-        raise WinError()
-    return SubscriptableReadOnlyStruct(jobinfo.info)
-
-def test_qijo():
-    from killableprocess import Popen
-
-    popen = Popen('c:\\windows\\notepad.exe')
-
-    try:
-        result = QueryInformationJobObject(0, 8)
-        raise AssertionError('throw should occur')
-    except WindowsError, e:
-        pass
-
-    try:
-        result = QueryInformationJobObject(0, 1)
-        raise AssertionError('throw should occur')
-    except NotImplementedError, e:
-        pass
-
-    result = QueryInformationJobObject(popen._job, 8)
-    if result['BasicInfo']['ActiveProcesses'] != 1:
-        raise AssertionError('expected ActiveProcesses to be 1')
-    popen.kill()
-
-    result = QueryInformationJobObject(popen._job, 8)
-    if result.BasicInfo.ActiveProcesses != 0:
-        raise AssertionError('expected ActiveProcesses to be 0')
-
-if __name__ == '__main__':
-    print "testing."
-    test_qijo()
-    print "success!"
deleted file mode 100644
--- a/addon-sdk/source/python-lib/mozrunner/winprocess.py
+++ /dev/null
@@ -1,379 +0,0 @@
-# A module to expose various thread/process/job related structures and
-# methods from kernel32
-#
-# The MIT License
-#
-# Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
-#
-# Additions and modifications written by Benjamin Smedberg
-# <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
-# <http://www.mozilla.org/>
-#
-# More Modifications
-# Copyright (c) 2006-2007 by Mike Taylor <bear@code-bear.com>
-# Copyright (c) 2007-2008 by Mikeal Rogers <mikeal@mozilla.com>
-#
-# By obtaining, using, and/or copying this software and/or its
-# associated documentation, you agree that you have read, understood,
-# and will comply with the following terms and conditions:
-#
-# Permission to use, copy, modify, and distribute this software and
-# its associated documentation for any purpose and without fee is
-# hereby granted, provided that the above copyright notice appears in
-# all copies, and that both that copyright notice and this permission
-# notice appear in supporting documentation, and that the name of the
-# author not be used in advertising or publicity pertaining to
-# distribution of the software without specific, written prior
-# permission.
-#
-# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE
-from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, \
-                            c_buffer, c_ulong, byref
-from qijo import QueryInformationJobObject
-
-LPVOID = c_void_p
-LPBYTE = POINTER(BYTE)
-LPDWORD = POINTER(DWORD)
-LPBOOL = POINTER(BOOL)
-
-def ErrCheckBool(result, func, args):
-    """errcheck function for Windows functions that return a BOOL True
-    on success"""
-    if not result:
-        raise WinError()
-    return args
-
-
-# AutoHANDLE
-
-class AutoHANDLE(HANDLE):
-    """Subclass of HANDLE which will call CloseHandle() on deletion."""
-    
-    CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE)
-    CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32))
-    CloseHandle.errcheck = ErrCheckBool
-    
-    def Close(self):
-        if self.value and self.value != HANDLE(-1).value:
-            self.CloseHandle(self)
-            self.value = 0
-    
-    def __del__(self):
-        self.Close()
-
-    def __int__(self):
-        return self.value
-
-def ErrCheckHandle(result, func, args):
-    """errcheck function for Windows functions that return a HANDLE."""
-    if not result:
-        raise WinError()
-    return AutoHANDLE(result)
-
-# PROCESS_INFORMATION structure
-
-class PROCESS_INFORMATION(Structure):
-    _fields_ = [("hProcess", HANDLE),
-                ("hThread", HANDLE),
-                ("dwProcessID", DWORD),
-                ("dwThreadID", DWORD)]
-
-    def __init__(self):
-        Structure.__init__(self)
-        
-        self.cb = sizeof(self)
-
-LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
-
-# STARTUPINFO structure
-
-class STARTUPINFO(Structure):
-    _fields_ = [("cb", DWORD),
-                ("lpReserved", LPWSTR),
-                ("lpDesktop", LPWSTR),
-                ("lpTitle", LPWSTR),
-                ("dwX", DWORD),
-                ("dwY", DWORD),
-                ("dwXSize", DWORD),
-                ("dwYSize", DWORD),
-                ("dwXCountChars", DWORD),
-                ("dwYCountChars", DWORD),
-                ("dwFillAttribute", DWORD),
-                ("dwFlags", DWORD),
-                ("wShowWindow", WORD),
-                ("cbReserved2", WORD),
-                ("lpReserved2", LPBYTE),
-                ("hStdInput", HANDLE),
-                ("hStdOutput", HANDLE),
-                ("hStdError", HANDLE)
-                ]
-LPSTARTUPINFO = POINTER(STARTUPINFO)
-
-SW_HIDE                 = 0
-
-STARTF_USESHOWWINDOW    = 0x01
-STARTF_USESIZE          = 0x02
-STARTF_USEPOSITION      = 0x04
-STARTF_USECOUNTCHARS    = 0x08
-STARTF_USEFILLATTRIBUTE = 0x10
-STARTF_RUNFULLSCREEN    = 0x20
-STARTF_FORCEONFEEDBACK  = 0x40
-STARTF_FORCEOFFFEEDBACK = 0x80
-STARTF_USESTDHANDLES    = 0x100
-
-# EnvironmentBlock
-
-class EnvironmentBlock:
-    """An object which can be passed as the lpEnv parameter of CreateProcess.
-    It is initialized with a dictionary."""
-
-    def __init__(self, dict):
-        if not dict:
-            self._as_parameter_ = None
-        else:
-            values = ["%s=%s" % (key, value)
-                      for (key, value) in dict.iteritems()]
-            values.append("")
-            self._as_parameter_ = LPCWSTR("\0".join(values))
-        
-# CreateProcess()
-
-CreateProcessProto = WINFUNCTYPE(BOOL,                  # Return type
-                                 LPCWSTR,               # lpApplicationName
-                                 LPWSTR,                # lpCommandLine
-                                 LPVOID,                # lpProcessAttributes
-                                 LPVOID,                # lpThreadAttributes
-                                 BOOL,                  # bInheritHandles
-                                 DWORD,                 # dwCreationFlags
-                                 LPVOID,                # lpEnvironment
-                                 LPCWSTR,               # lpCurrentDirectory
-                                 LPSTARTUPINFO,         # lpStartupInfo
-                                 LPPROCESS_INFORMATION  # lpProcessInformation
-                                 )
-
-CreateProcessFlags = ((1, "lpApplicationName", None),
-                      (1, "lpCommandLine"),
-                      (1, "lpProcessAttributes", None),
-                      (1, "lpThreadAttributes", None),
-                      (1, "bInheritHandles", True),
-                      (1, "dwCreationFlags", 0),
-                      (1, "lpEnvironment", None),
-                      (1, "lpCurrentDirectory", None),
-                      (1, "lpStartupInfo"),
-                      (2, "lpProcessInformation"))
-
-def ErrCheckCreateProcess(result, func, args):
-    ErrCheckBool(result, func, args)
-    # return a tuple (hProcess, hThread, dwProcessID, dwThreadID)
-    pi = args[9]
-    return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID
-
-CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32),
-                                   CreateProcessFlags)
-CreateProcess.errcheck = ErrCheckCreateProcess
-
-# flags for CreateProcess
-CREATE_BREAKAWAY_FROM_JOB = 0x01000000
-CREATE_DEFAULT_ERROR_MODE = 0x04000000
-CREATE_NEW_CONSOLE = 0x00000010
-CREATE_NEW_PROCESS_GROUP = 0x00000200
-CREATE_NO_WINDOW = 0x08000000
-CREATE_SUSPENDED = 0x00000004
-CREATE_UNICODE_ENVIRONMENT = 0x00000400
-
-# flags for job limit information
-# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
-JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
-JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
-
-# XXX these flags should be documented
-DEBUG_ONLY_THIS_PROCESS = 0x00000002
-DEBUG_PROCESS = 0x00000001
-DETACHED_PROCESS = 0x00000008
-
-# CreateJobObject()
-
-CreateJobObjectProto = WINFUNCTYPE(HANDLE,             # Return type
-                                   LPVOID,             # lpJobAttributes
-                                   LPCWSTR             # lpName
-                                   )
-
-CreateJobObjectFlags = ((1, "lpJobAttributes", None),
-                        (1, "lpName", None))
-
-CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32),
-                                       CreateJobObjectFlags)
-CreateJobObject.errcheck = ErrCheckHandle
-
-# AssignProcessToJobObject()
-
-AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL,      # Return type
-                                            HANDLE,    # hJob
-                                            HANDLE     # hProcess
-                                            )
-AssignProcessToJobObjectFlags = ((1, "hJob"),
-                                 (1, "hProcess"))
-AssignProcessToJobObject = AssignProcessToJobObjectProto(
-    ("AssignProcessToJobObject", windll.kernel32),
-    AssignProcessToJobObjectFlags)
-AssignProcessToJobObject.errcheck = ErrCheckBool
-
-# GetCurrentProcess()
-# because os.getPid() is way too easy
-GetCurrentProcessProto = WINFUNCTYPE(HANDLE    # Return type
-                                     )
-GetCurrentProcessFlags = ()
-GetCurrentProcess = GetCurrentProcessProto(
-    ("GetCurrentProcess", windll.kernel32),
-    GetCurrentProcessFlags)
-GetCurrentProcess.errcheck = ErrCheckHandle
-
-# IsProcessInJob()
-try:
-    IsProcessInJobProto = WINFUNCTYPE(BOOL,     # Return type
-                                      HANDLE,   # Process Handle
-                                      HANDLE,   # Job Handle
-                                      LPBOOL      # Result
-                                      )
-    IsProcessInJobFlags = ((1, "ProcessHandle"),
-                           (1, "JobHandle", HANDLE(0)),
-                           (2, "Result"))
-    IsProcessInJob = IsProcessInJobProto(
-        ("IsProcessInJob", windll.kernel32),
-        IsProcessInJobFlags)
-    IsProcessInJob.errcheck = ErrCheckBool 
-except AttributeError:
-    # windows 2k doesn't have this API
-    def IsProcessInJob(process):
-        return False
-
-
-# ResumeThread()
-
-def ErrCheckResumeThread(result, func, args):
-    if result == -1:
-        raise WinError()
-
-    return args
-
-ResumeThreadProto = WINFUNCTYPE(DWORD,      # Return type
-                                HANDLE      # hThread
-                                )
-ResumeThreadFlags = ((1, "hThread"),)
-ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32),
-                                 ResumeThreadFlags)
-ResumeThread.errcheck = ErrCheckResumeThread
-
-# TerminateProcess()
-
-TerminateProcessProto = WINFUNCTYPE(BOOL,   # Return type
-                                    HANDLE, # hProcess
-                                    UINT    # uExitCode
-                                    )
-TerminateProcessFlags = ((1, "hProcess"),
-                         (1, "uExitCode", 127))
-TerminateProcess = TerminateProcessProto(
-    ("TerminateProcess", windll.kernel32),
-    TerminateProcessFlags)
-TerminateProcess.errcheck = ErrCheckBool
-
-# TerminateJobObject()
-
-TerminateJobObjectProto = WINFUNCTYPE(BOOL,   # Return type
-                                      HANDLE, # hJob
-                                      UINT    # uExitCode
-                                      )
-TerminateJobObjectFlags = ((1, "hJob"),
-                           (1, "uExitCode", 127))
-TerminateJobObject = TerminateJobObjectProto(
-    ("TerminateJobObject", windll.kernel32),
-    TerminateJobObjectFlags)
-TerminateJobObject.errcheck = ErrCheckBool
-
-# WaitForSingleObject()
-
-WaitForSingleObjectProto = WINFUNCTYPE(DWORD,  # Return type
-                                       HANDLE, # hHandle
-                                       DWORD,  # dwMilliseconds
-                                       )
-WaitForSingleObjectFlags = ((1, "hHandle"),
-                            (1, "dwMilliseconds", -1))
-WaitForSingleObject = WaitForSingleObjectProto(
-    ("WaitForSingleObject", windll.kernel32),
-    WaitForSingleObjectFlags)
-
-INFINITE = -1
-WAIT_TIMEOUT = 0x0102
-WAIT_OBJECT_0 = 0x0
-WAIT_ABANDONED = 0x0080
-WAIT_FAILED = 0xFFFFFFFF
-
-# GetExitCodeProcess()
-
-GetExitCodeProcessProto = WINFUNCTYPE(BOOL,    # Return type
-                                      HANDLE,  # hProcess
-                                      LPDWORD, # lpExitCode
-                                      )
-GetExitCodeProcessFlags = ((1, "hProcess"),
-                           (2, "lpExitCode"))
-GetExitCodeProcess = GetExitCodeProcessProto(
-    ("GetExitCodeProcess", windll.kernel32),
-    GetExitCodeProcessFlags)
-GetExitCodeProcess.errcheck = ErrCheckBool
-
-def CanCreateJobObject():
-    # Running firefox in a job (from cfx) hangs on sites using flash plugin
-    # so job creation is turned off for now. (see Bug 768651).
-    return False
-
-### testing functions
-
-def parent():
-    print 'Starting parent'
-    currentProc = GetCurrentProcess()
-    if IsProcessInJob(currentProc):
-        print >> sys.stderr, "You should not be in a job object to test"
-        sys.exit(1)
-    assert CanCreateJobObject()
-    print 'File: %s' % __file__
-    command = [sys.executable, __file__, '-child']
-    print 'Running command: %s' % command
-    process = Popen(command)
-    process.kill()
-    code = process.returncode
-    print 'Child code: %s' % code
-    assert code == 127
-        
-def child():
-    print 'Starting child'
-    currentProc = GetCurrentProcess()
-    injob = IsProcessInJob(currentProc)
-    print "Is in a job?: %s" % injob
-    can_create = CanCreateJobObject()
-    print 'Can create job?: %s' % can_create
-    process = Popen('c:\\windows\\notepad.exe')
-    assert process._job
-    jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation')
-    print 'Job info: %s' % jobinfo
-    limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
-    print 'LimitFlags: %s' % limitflags
-    process.kill()
-
-if __name__ == '__main__':
-    import sys
-    from killableprocess import Popen
-    nargs = len(sys.argv[1:])
-    if nargs:
-        if nargs != 1 or sys.argv[1] != '-child':
-            raise AssertionError('Wrong flags; run like `python /path/to/winprocess.py`')
-        child()
-    else:
-        parent()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/mozrunner/wpk.py
+++ /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/.
-
-from ctypes import sizeof, windll, addressof, c_wchar, create_unicode_buffer
-from ctypes.wintypes import DWORD, HANDLE
-
-PROCESS_TERMINATE = 0x0001
-PROCESS_QUERY_INFORMATION = 0x0400
-PROCESS_VM_READ = 0x0010
-
-def get_pids(process_name):
-    BIG_ARRAY = DWORD * 4096
-    processes = BIG_ARRAY()
-    needed = DWORD()
-
-    pids = []
-    result = windll.psapi.EnumProcesses(processes,
-                                        sizeof(processes),
-                                        addressof(needed))
-    if not result:
-        return pids
-
-    num_results = needed.value / sizeof(DWORD)
-
-    for i in range(num_results):
-        pid = processes[i]
-        process = windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION |
-                                              PROCESS_VM_READ,
-                                              0, pid)
-        if process:
-            module = HANDLE()
-            result = windll.psapi.EnumProcessModules(process,
-                                                     addressof(module),
-                                                     sizeof(module),
-                                                     addressof(needed))
-            if result:
-                name = create_unicode_buffer(1024)
-                result = windll.psapi.GetModuleBaseNameW(process, module,
-                                                         name, len(name))
-                # TODO: This might not be the best way to
-                # match a process name; maybe use a regexp instead.
-                if name.value.startswith(process_name):
-                    pids.append(pid)
-                windll.kernel32.CloseHandle(module)
-            windll.kernel32.CloseHandle(process)
-
-    return pids
-
-def kill_pid(pid):
-    process = windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid)
-    if process:
-        windll.kernel32.TerminateProcess(process, 0)
-        windll.kernel32.CloseHandle(process)
-
-if __name__ == '__main__':
-    import subprocess
-    import time
-
-    # This test just opens a new notepad instance and kills it.
-
-    name = 'notepad'
-
-    old_pids = set(get_pids(name))
-    subprocess.Popen([name])
-    time.sleep(0.25)
-    new_pids = set(get_pids(name)).difference(old_pids)
-
-    if len(new_pids) != 1:
-        raise Exception('%s was not opened or get_pids() is '
-                        'malfunctioning' % name)
-
-    kill_pid(tuple(new_pids)[0])
-
-    newest_pids = set(get_pids(name)).difference(old_pids)
-
-    if len(newest_pids) != 0:
-        raise Exception('kill_pid() is malfunctioning')
-
-    print "Test passed."
deleted file mode 100644
--- a/addon-sdk/source/python-lib/plural-rules-generator.py
+++ /dev/null
@@ -1,185 +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/.
-
-# Program used to generate /packages/api-utils/lib/l10n/plural-rules.js
-# Fetch unicode.org data in order to build functions specific to each language
-# that will return for a given integer, its plural form name.
-# Plural form names are: zero, one, two, few, many, other.
-#
-# More information here:
-#   http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
-#   http://cldr.unicode.org/index/cldr-spec/plural-rules
-
-# Usage:
-# $ python plural-rules-generator.py > ../packages/api-utils/lib/l10n/plural-rules.js
-
-import urllib2
-import xml.dom.minidom
-import json
-import re
-
-PRINT_CONDITIONS_IN_COMMENTS = False
-
-UNICODE_ORG_XML_URL = "http://unicode.org/repos/cldr/trunk/common/supplemental/plurals.xml"
-
-CONDITION_RE = r'n( mod \d+)? (is|in|within|(not in))( not)? ([^\s]+)'
-
-
-def parseCondition(g):
-    """
-    For a given regexp.MatchObject `g` for `CONDITION_RE`, 
-    returns the equivalent JS piece of code
-    i.e. maps pseudo conditional language from unicode.org XML to JS code
-    """
-    lvalue = "n"
-    if g.group(1):
-        lvalue = "(n %% %d)" % int(g.group(1).replace("mod ", ""))
-
-    operator = g.group(2)
-    if g.group(4):
-        operator += " not"
-
-    rvalue = g.group(5)
-
-    if operator == "is":
-        return "%s == %s" % (lvalue, rvalue)
-    if operator == "is not":
-        return "%s != %s" % (lvalue, rvalue)
-
-    # "in", "within" or "not in" case:
-    notPrefix = ""
-    if operator == "not in":
-        notPrefix = "!"
-
-    # `rvalue` is a comma seperated list of either:
-    #  - numbers: 42
-    #  - ranges: 42..72
-    sections = rvalue.split(',')
-
-    if ".." not in rvalue:
-        # If we don't have range, but only a list of integer,
-        # we can simplify the generated code by using `isIn`
-        # n in 1,3,6,42
-        return "%sisIn(%s, [%s])" % (notPrefix, lvalue, ", ".join(sections))
-
-    # n in 1..42
-    # n in 1..3,42
-    subCondition = []
-    integers = []
-    for sub in sections:
-        if ".." in sub:
-            left, right = sub.split("..")
-            subCondition.append("isBetween(%s, %d, %d)" % (
-                                lvalue,
-                                int(left),
-                                int(right)
-                               ))
-        else:
-            integers.append(int(sub))
-    if len(integers) > 1:
-      subCondition.append("isIn(%s, [%s])" % (lvalue, ", ".join(integers)))
-    elif len(integers) == 1:
-      subCondition.append("(%s == %s)" % (lvalue, integers[0]))
-    return "%s(%s)" % (notPrefix, " || ".join(subCondition))
-
-def computeRules():
-    """
-    Fetch plural rules data directly from unicode.org website:
-    """
-    url = UNICODE_ORG_XML_URL
-    f = urllib2.urlopen(url)
-    doc = xml.dom.minidom.parse(f)
-
-    # Read XML document and extract locale to rules mapping
-    localesMapping = {}
-    algorithms = {}
-    for index,pluralRules in enumerate(doc.getElementsByTagName("pluralRules")):
-        if not index in algorithms:
-            algorithms[index] = {}
-        for locale in pluralRules.getAttribute("locales").split():
-            localesMapping[locale] = index
-        for rule in pluralRules.childNodes:
-            if rule.nodeType != rule.ELEMENT_NODE or rule.tagName != "pluralRule":
-                continue
-            pluralForm = rule.getAttribute("count")
-            algorithm = rule.firstChild.nodeValue
-            algorithms[index][pluralForm] = algorithm
-
-    # Go through all rules and compute a Javascript code for each of them
-    rules = {}
-    for index,rule in algorithms.iteritems():
-        lines = []
-        for pluralForm in rule:
-            condition = rule[pluralForm]
-            originalCondition = str(condition)
-
-            # Convert pseudo language to JS code
-            condition = rule[pluralForm].lower()
-            condition = re.sub(CONDITION_RE, parseCondition, condition)
-            condition = re.sub(r'or', "||", condition)
-            condition = re.sub(r'and', "&&", condition)
-
-            # Prints original condition in unicode.org pseudo language
-            if PRINT_CONDITIONS_IN_COMMENTS:
-                lines.append( '// %s' % originalCondition )
-
-            lines.append( 'if (%s)' % condition )
-            lines.append( '  return "%s";' % pluralForm )
-            
-        rules[index] = "\n    ".join(lines)
-    return localesMapping, rules
-
-
-localesMapping, rules = computeRules()
-
-rulesLines = []
-for index in rules:
-    lines = rules[index]
-    rulesLines.append('"%d": function (n) {' % index)
-    rulesLines.append('  %s' % lines)
-    rulesLines.append('  return "other"')
-    rulesLines.append('},')
-
-print """/* 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 file is automatically generated with /python-lib/plural-rules-generator.py
-// Fetching data from: %s
-
-// Mapping of short locale name == to == > rule index in following list
-const LOCALES_TO_RULES = %s;
-
-// Utility functions for plural rules methods
-function isIn(n, list) {
-  return list.indexOf(n) !== -1;
-}
-function isBetween(n, start, end) {
-  return start <= n && n <= end;
-}
-
-// List of all plural rules methods, that maps an integer to the plural form name to use
-const RULES = {
-  %s
-};
-
-/**
-  * Return a function that gives the plural form name for a given integer
-  * for the specified `locale`
-  *   let fun = getRulesForLocale('en');
-  *   fun(1)    -> 'one'
-  *   fun(0)    -> 'other'
-  *   fun(1000) -> 'other'
-  */
-exports.getRulesForLocale = function getRulesForLocale(locale) {
-  let index = LOCALES_TO_RULES[locale];
-  if (!(index in RULES)) {
-    console.warn('Plural form unknown for locale "' + locale + '"');
-    return function () { return "other"; };
-  }
-  return RULES[index];
-}
-""" % (UNICODE_ORG_XML_URL,
-        json.dumps(localesMapping, sort_keys=True, indent=2),
-        "\n  ".join(rulesLines))
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2006 Bob Ippolito
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/__init__.py
+++ /dev/null
@@ -1,376 +0,0 @@
-r"""
-A simple, fast, extensible JSON encoder and decoder
-
-JSON (JavaScript Object Notation) <http://json.org> is a subset of
-JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
-interchange format.
-
-simplejson exposes an API familiar to uses of the standard library
-marshal and pickle modules.
-
-Encoding basic Python object hierarchies::
-    
-    >>> import simplejson
-    >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
-    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
-    >>> print simplejson.dumps("\"foo\bar")
-    "\"foo\bar"
-    >>> print simplejson.dumps(u'\u1234')
-    "\u1234"
-    >>> print simplejson.dumps('\\')
-    "\\"
-    >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
-    {"a": 0, "b": 0, "c": 0}
-    >>> from StringIO import StringIO
-    >>> io = StringIO()
-    >>> simplejson.dump(['streaming API'], io)
-    >>> io.getvalue()
-    '["streaming API"]'
-
-Compact encoding::
-
-    >>> import simplejson
-    >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
-    '[1,2,3,{"4":5,"6":7}]'
-
-Pretty printing::
-
-    >>> import simplejson
-    >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
-    {
-        "4": 5, 
-        "6": 7
-    }
-
-Decoding JSON::
-    
-    >>> import simplejson
-    >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
-    [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
-    >>> simplejson.loads('"\\"foo\\bar"')
-    u'"foo\x08ar'
-    >>> from StringIO import StringIO
-    >>> io = StringIO('["streaming API"]')
-    >>> simplejson.load(io)
-    [u'streaming API']
-
-Specializing JSON object decoding::
-
-    >>> import simplejson
-    >>> def as_complex(dct):
-    ...     if '__complex__' in dct:
-    ...         return complex(dct['real'], dct['imag'])
-    ...     return dct
-    ... 
-    >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}',
-    ...     object_hook=as_complex)
-    (1+2j)
-    >>> import decimal
-    >>> simplejson.loads('1.1', parse_float=decimal.Decimal)
-    Decimal("1.1")
-
-Extending JSONEncoder::
-    
-    >>> import simplejson
-    >>> class ComplexEncoder(simplejson.JSONEncoder):
-    ...     def default(self, obj):
-    ...         if isinstance(obj, complex):
-    ...             return [obj.real, obj.imag]
-    ...         return simplejson.JSONEncoder.default(self, obj)
-    ... 
-    >>> dumps(2 + 1j, cls=ComplexEncoder)
-    '[2.0, 1.0]'
-    >>> ComplexEncoder().encode(2 + 1j)
-    '[2.0, 1.0]'
-    >>> list(ComplexEncoder().iterencode(2 + 1j))
-    ['[', '2.0', ', ', '1.0', ']']
-    
-
-Using simplejson from the shell to validate and
-pretty-print::
-    
-    $ echo '{"json":"obj"}' | python -msimplejson.tool
-    {
-        "json": "obj"
-    }
-    $ echo '{ 1.2:3.4}' | python -msimplejson.tool
-    Expecting property name: line 1 column 2 (char 2)
-
-Note that the JSON produced by this module's default settings
-is a subset of YAML, so it may be used as a serializer for that as well.
-"""
-__version__ = '1.9.2'
-__all__ = [
-    'dump', 'dumps', 'load', 'loads',
-    'JSONDecoder', 'JSONEncoder',
-]
-
-if __name__ == '__main__':
-    import warnings
-    warnings.warn('python -msimplejson is deprecated, use python -msiplejson.tool', DeprecationWarning)
-    from simplejson.decoder import JSONDecoder
-    from simplejson.encoder import JSONEncoder
-else:
-    from decoder import JSONDecoder
-    from encoder import JSONEncoder
-
-_default_encoder = JSONEncoder(
-    skipkeys=False,
-    ensure_ascii=True,
-    check_circular=True,
-    allow_nan=True,
-    indent=None,
-    separators=None,
-    encoding='utf-8',
-    default=None,
-)
-
-def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
-        allow_nan=True, cls=None, indent=None, separators=None,
-        encoding='utf-8', default=None, **kw):
-    """
-    Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
-    ``.write()``-supporting file-like object).
-
-    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
-    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 
-    will be skipped instead of raising a ``TypeError``.
-
-    If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
-    may be ``unicode`` instances, subject to normal Python ``str`` to
-    ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
-    understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
-    to cause an error.
-
-    If ``check_circular`` is ``False``, then the circular reference check
-    for container types will be skipped and a circular reference will
-    result in an ``OverflowError`` (or worse).
-
-    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
-    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
-    in strict compliance of the JSON specification, instead of using the
-    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
-    If ``indent`` is a non-negative integer, then JSON array elements and object
-    members will be pretty-printed with that indent level. An indent level
-    of 0 will only insert newlines. ``None`` is the most compact representation.
-
-    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
-    then it will be used instead of the default ``(', ', ': ')`` separators.
-    ``(',', ':')`` is the most compact JSON representation.
-
-    ``encoding`` is the character encoding for str instances, default is UTF-8.
-
-    ``default(obj)`` is a function that should return a serializable version
-    of obj or raise TypeError. The default simply raises TypeError.
-
-    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
-    ``.default()`` method to serialize additional types), specify it with
-    the ``cls`` kwarg.
-    """
-    # cached encoder
-    if (skipkeys is False and ensure_ascii is True and
-        check_circular is True and allow_nan is True and
-        cls is None and indent is None and separators is None and
-        encoding == 'utf-8' and default is None and not kw):
-        iterable = _default_encoder.iterencode(obj)
-    else:
-        if cls is None:
-            cls = JSONEncoder
-        iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
-            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
-            separators=separators, encoding=encoding,
-            default=default, **kw).iterencode(obj)
-    # could accelerate with writelines in some versions of Python, at
-    # a debuggability cost
-    for chunk in iterable:
-        fp.write(chunk)
-
-
-def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
-        allow_nan=True, cls=None, indent=None, separators=None,
-        encoding='utf-8', default=None, **kw):
-    """
-    Serialize ``obj`` to a JSON formatted ``str``.
-
-    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
-    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 
-    will be skipped instead of raising a ``TypeError``.
-
-    If ``ensure_ascii`` is ``False``, then the return value will be a
-    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
-    coercion rules instead of being escaped to an ASCII ``str``.
-
-    If ``check_circular`` is ``False``, then the circular reference check
-    for container types will be skipped and a circular reference will
-    result in an ``OverflowError`` (or worse).
-
-    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
-    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
-    strict compliance of the JSON specification, instead of using the
-    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
-    If ``indent`` is a non-negative integer, then JSON array elements and
-    object members will be pretty-printed with that indent level. An indent
-    level of 0 will only insert newlines. ``None`` is the most compact
-    representation.
-
-    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
-    then it will be used instead of the default ``(', ', ': ')`` separators.
-    ``(',', ':')`` is the most compact JSON representation.
-
-    ``encoding`` is the character encoding for str instances, default is UTF-8.
-
-    ``default(obj)`` is a function that should return a serializable version
-    of obj or raise TypeError. The default simply raises TypeError.
-
-    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
-    ``.default()`` method to serialize additional types), specify it with
-    the ``cls`` kwarg.
-    """
-    # cached encoder
-    if (skipkeys is False and ensure_ascii is True and
-        check_circular is True and allow_nan is True and
-        cls is None and indent is None and separators is None and
-        encoding == 'utf-8' and default is None and not kw):
-        return _default_encoder.encode(obj)
-    if cls is None:
-        cls = JSONEncoder
-    return cls(
-        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
-        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
-        separators=separators, encoding=encoding, default=default,
-        **kw).encode(obj)
-
-
-_default_decoder = JSONDecoder(encoding=None, object_hook=None)
-
-
-def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
-        parse_int=None, parse_constant=None, **kw):
-    """
-    Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
-    a JSON document) to a Python object.
-
-    If the contents of ``fp`` is encoded with an ASCII based encoding other
-    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
-    be specified. Encodings that are not ASCII based (such as UCS-2) are
-    not allowed, and should be wrapped with
-    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
-    object and passed to ``loads()``
-
-    ``object_hook`` is an optional function that will be called with the
-    result of any object literal decode (a ``dict``). The return value of
-    ``object_hook`` will be used instead of the ``dict``. This feature
-    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-    
-    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
-    kwarg.
-    """
-    return loads(fp.read(),
-        encoding=encoding, cls=cls, object_hook=object_hook,
-        parse_float=parse_float, parse_int=parse_int,
-        parse_constant=parse_constant, **kw)
-
-
-def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
-        parse_int=None, parse_constant=None, **kw):
-    """
-    Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
-    document) to a Python object.
-
-    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
-    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
-    must be specified. Encodings that are not ASCII based (such as UCS-2)
-    are not allowed and should be decoded to ``unicode`` first.
-
-    ``object_hook`` is an optional function that will be called with the
-    result of any object literal decode (a ``dict``). The return value of
-    ``object_hook`` will be used instead of the ``dict``. This feature
-    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-
-    ``parse_float``, if specified, will be called with the string
-    of every JSON float to be decoded. By default this is equivalent to
-    float(num_str). This can be used to use another datatype or parser
-    for JSON floats (e.g. decimal.Decimal).
-
-    ``parse_int``, if specified, will be called with the string
-    of every JSON int to be decoded. By default this is equivalent to
-    int(num_str). This can be used to use another datatype or parser
-    for JSON integers (e.g. float).
-
-    ``parse_constant``, if specified, will be called with one of the
-    following strings: -Infinity, Infinity, NaN, null, true, false.
-    This can be used to raise an exception if invalid JSON numbers
-    are encountered.
-
-    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
-    kwarg.
-    """
-    if (cls is None and encoding is None and object_hook is None and
-            parse_int is None and parse_float is None and
-            parse_constant is None and not kw):
-        return _default_decoder.decode(s)
-    if cls is None:
-        cls = JSONDecoder
-    if object_hook is not None:
-        kw['object_hook'] = object_hook
-    if parse_float is not None:
-        kw['parse_float'] = parse_float
-    if parse_int is not None:
-        kw['parse_int'] = parse_int
-    if parse_constant is not None:
-        kw['parse_constant'] = parse_constant
-    return cls(encoding=encoding, **kw).decode(s)
-
-
-#
-# Compatibility cruft from other libraries
-#
-
-
-def decode(s):
-    """
-    demjson, python-cjson API compatibility hook. Use loads(s) instead.
-    """
-    import warnings
-    warnings.warn("simplejson.loads(s) should be used instead of decode(s)",
-        DeprecationWarning)
-    return loads(s)
-
-
-def encode(obj):
-    """
-    demjson, python-cjson compatibility hook. Use dumps(s) instead.
-    """
-    import warnings
-    warnings.warn("simplejson.dumps(s) should be used instead of encode(s)",
-        DeprecationWarning)
-    return dumps(obj)
-
-
-def read(s):
-    """
-    jsonlib, JsonUtils, python-json, json-py API compatibility hook.
-    Use loads(s) instead.
-    """
-    import warnings
-    warnings.warn("simplejson.loads(s) should be used instead of read(s)",
-        DeprecationWarning)
-    return loads(s)
-
-
-def write(obj):
-    """
-    jsonlib, JsonUtils, python-json, json-py API compatibility hook.
-    Use dumps(s) instead.
-    """
-    import warnings
-    warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
-        DeprecationWarning)
-    return dumps(obj)
-
-
-if __name__ == '__main__':
-    import simplejson.tool
-    simplejson.tool.main()
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/decoder.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""
-Implementation of JSONDecoder
-"""
-import re
-import sys
-
-from simplejson.scanner import Scanner, pattern
-try:
-    from simplejson._speedups import scanstring as c_scanstring
-except ImportError:
-    pass
-
-FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
-
-def _floatconstants():
-    import struct
-    import sys
-    _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
-    if sys.byteorder != 'big':
-        _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
-    nan, inf = struct.unpack('dd', _BYTES)
-    return nan, inf, -inf
-
-NaN, PosInf, NegInf = _floatconstants()
-
-
-def linecol(doc, pos):
-    lineno = doc.count('\n', 0, pos) + 1
-    if lineno == 1:
-        colno = pos
-    else:
-        colno = pos - doc.rindex('\n', 0, pos)
-    return lineno, colno
-
-
-def errmsg(msg, doc, pos, end=None):
-    lineno, colno = linecol(doc, pos)
-    if end is None:
-        return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
-    endlineno, endcolno = linecol(doc, end)
-    return '%s: line %d column %d - line %d column %d (char %d - %d)' % (
-        msg, lineno, colno, endlineno, endcolno, pos, end)
-
-
-_CONSTANTS = {
-    '-Infinity': NegInf,
-    'Infinity': PosInf,
-    'NaN': NaN,
-    'true': True,
-    'false': False,
-    'null': None,
-}
-
-def JSONConstant(match, context, c=_CONSTANTS):
-    s = match.group(0)
-    fn = getattr(context, 'parse_constant', None)
-    if fn is None:
-        rval = c[s]
-    else:
-        rval = fn(s)
-    return rval, None
-pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant)
-
-
-def JSONNumber(match, context):
-    match = JSONNumber.regex.match(match.string, *match.span())
-    integer, frac, exp = match.groups()
-    if frac or exp:
-        fn = getattr(context, 'parse_float', None) or float
-        res = fn(integer + (frac or '') + (exp or ''))
-    else:
-        fn = getattr(context, 'parse_int', None) or int
-        res = fn(integer)
-    return res, None
-pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)
-
-
-STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
-BACKSLASH = {
-    '"': u'"', '\\': u'\\', '/': u'/',
-    'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
-}
-
-DEFAULT_ENCODING = "utf-8"
-
-def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match):
-    if encoding is None:
-        encoding = DEFAULT_ENCODING
-    chunks = []
-    _append = chunks.append
-    begin = end - 1
-    while 1:
-        chunk = _m(s, end)
-        if chunk is None:
-            raise ValueError(
-                errmsg("Unterminated string starting at", s, begin))
-        end = chunk.end()
-        content, terminator = chunk.groups()
-        if content:
-            if not isinstance(content, unicode):
-                content = unicode(content, encoding)
-            _append(content)
-        if terminator == '"':
-            break
-        elif terminator != '\\':
-            if strict:
-                raise ValueError(errmsg("Invalid control character %r at", s, end))
-            else:
-                _append(terminator)
-                continue
-        try:
-            esc = s[end]
-        except IndexError:
-            raise ValueError(
-                errmsg("Unterminated string starting at", s, begin))
-        if esc != 'u':
-            try:
-                m = _b[esc]
-            except KeyError:
-                raise ValueError(
-                    errmsg("Invalid \\escape: %r" % (esc,), s, end))
-            end += 1
-        else:
-            esc = s[end + 1:end + 5]
-            next_end = end + 5
-            msg = "Invalid \\uXXXX escape"
-            try:
-                if len(esc) != 4:
-                    raise ValueError
-                uni = int(esc, 16)
-                if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
-                    msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
-                    if not s[end + 5:end + 7] == '\\u':
-                        raise ValueError
-                    esc2 = s[end + 7:end + 11]
-                    if len(esc2) != 4:
-                        raise ValueError
-                    uni2 = int(esc2, 16)
-                    uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
-                    next_end += 6
-                m = unichr(uni)
-            except ValueError:
-                raise ValueError(errmsg(msg, s, end))
-            end = next_end
-        _append(m)
-    return u''.join(chunks), end
-
-
-# Use speedup
-try:
-    scanstring = c_scanstring
-except NameError:
-    scanstring = py_scanstring
-
-def JSONString(match, context):
-    encoding = getattr(context, 'encoding', None)
-    strict = getattr(context, 'strict', True)
-    return scanstring(match.string, match.end(), encoding, strict)
-pattern(r'"')(JSONString)
-
-
-WHITESPACE = re.compile(r'\s*', FLAGS)
-
-def JSONObject(match, context, _w=WHITESPACE.match):
-    pairs = {}
-    s = match.string
-    end = _w(s, match.end()).end()
-    nextchar = s[end:end + 1]
-    # Trivial empty object
-    if nextchar == '}':
-        return pairs, end + 1
-    if nextchar != '"':
-        raise ValueError(errmsg("Expecting property name", s, end))
-    end += 1
-    encoding = getattr(context, 'encoding', None)
-    strict = getattr(context, 'strict', True)
-    iterscan = JSONScanner.iterscan
-    while True:
-        key, end = scanstring(s, end, encoding, strict)
-        end = _w(s, end).end()
-        if s[end:end + 1] != ':':
-            raise ValueError(errmsg("Expecting : delimiter", s, end))
-        end = _w(s, end + 1).end()
-        try:
-            value, end = iterscan(s, idx=end, context=context).next()
-        except StopIteration:
-            raise ValueError(errmsg("Expecting object", s, end))
-        pairs[key] = value
-        end = _w(s, end).end()
-        nextchar = s[end:end + 1]
-        end += 1
-        if nextchar == '}':
-            break
-        if nextchar != ',':
-            raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
-        end = _w(s, end).end()
-        nextchar = s[end:end + 1]
-        end += 1
-        if nextchar != '"':
-            raise ValueError(errmsg("Expecting property name", s, end - 1))
-    object_hook = getattr(context, 'object_hook', None)
-    if object_hook is not None:
-        pairs = object_hook(pairs)
-    return pairs, end
-pattern(r'{')(JSONObject)
-
-
-def JSONArray(match, context, _w=WHITESPACE.match):
-    values = []
-    s = match.string
-    end = _w(s, match.end()).end()
-    # Look-ahead for trivial empty array
-    nextchar = s[end:end + 1]
-    if nextchar == ']':
-        return values, end + 1
-    iterscan = JSONScanner.iterscan
-    while True:
-        try:
-            value, end = iterscan(s, idx=end, context=context).next()
-        except StopIteration:
-            raise ValueError(errmsg("Expecting object", s, end))
-        values.append(value)
-        end = _w(s, end).end()
-        nextchar = s[end:end + 1]
-        end += 1
-        if nextchar == ']':
-            break
-        if nextchar != ',':
-            raise ValueError(errmsg("Expecting , delimiter", s, end))
-        end = _w(s, end).end()
-    return values, end
-pattern(r'\[')(JSONArray)
-
-
-ANYTHING = [
-    JSONObject,
-    JSONArray,
-    JSONString,
-    JSONConstant,
-    JSONNumber,
-]
-
-JSONScanner = Scanner(ANYTHING)
-
-
-class JSONDecoder(object):
-    """
-    Simple JSON <http://json.org> decoder
-
-    Performs the following translations in decoding by default:
-    
-    +---------------+-------------------+
-    | JSON          | Python            |
-    +===============+===================+
-    | object        | dict              |
-    +---------------+-------------------+
-    | array         | list              |
-    +---------------+-------------------+
-    | string        | unicode           |
-    +---------------+-------------------+
-    | number (int)  | int, long         |
-    +---------------+-------------------+
-    | number (real) | float             |
-    +---------------+-------------------+
-    | true          | True              |
-    +---------------+-------------------+
-    | false         | False             |
-    +---------------+-------------------+
-    | null          | None              |
-    +---------------+-------------------+
-
-    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
-    their corresponding ``float`` values, which is outside the JSON spec.
-    """
-
-    _scanner = Scanner(ANYTHING)
-    __all__ = ['__init__', 'decode', 'raw_decode']
-
-    def __init__(self, encoding=None, object_hook=None, parse_float=None,
-            parse_int=None, parse_constant=None, strict=True):
-        """
-        ``encoding`` determines the encoding used to interpret any ``str``
-        objects decoded by this instance (utf-8 by default).  It has no
-        effect when decoding ``unicode`` objects.
-        
-        Note that currently only encodings that are a superset of ASCII work,
-        strings of other encodings should be passed in as ``unicode``.
-
-        ``object_hook``, if specified, will be called with the result
-        of every JSON object decoded and its return value will be used in
-        place of the given ``dict``.  This can be used to provide custom
-        deserializations (e.g. to support JSON-RPC class hinting).
-
-        ``parse_float``, if specified, will be called with the string
-        of every JSON float to be decoded. By default this is equivalent to
-        float(num_str). This can be used to use another datatype or parser
-        for JSON floats (e.g. decimal.Decimal).
-
-        ``parse_int``, if specified, will be called with the string
-        of every JSON int to be decoded. By default this is equivalent to
-        int(num_str). This can be used to use another datatype or parser
-        for JSON integers (e.g. float).
-
-        ``parse_constant``, if specified, will be called with one of the
-        following strings: -Infinity, Infinity, NaN, null, true, false.
-        This can be used to raise an exception if invalid JSON numbers
-        are encountered.
-        """
-        self.encoding = encoding
-        self.object_hook = object_hook
-        self.parse_float = parse_float
-        self.parse_int = parse_int
-        self.parse_constant = parse_constant
-        self.strict = strict
-
-    def decode(self, s, _w=WHITESPACE.match):
-        """
-        Return the Python representation of ``s`` (a ``str`` or ``unicode``
-        instance containing a JSON document)
-        """
-        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
-        end = _w(s, end).end()
-        if end != len(s):
-            raise ValueError(errmsg("Extra data", s, end, len(s)))
-        return obj
-
-    def raw_decode(self, s, **kw):
-        """
-        Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
-        with a JSON document) and return a 2-tuple of the Python
-        representation and the index in ``s`` where the document ended.
-
-        This can be used to decode a JSON document from a string that may
-        have extraneous data at the end.
-        """
-        kw.setdefault('context', self)
-        try:
-            obj, end = self._scanner.iterscan(s, **kw).next()
-        except StopIteration:
-            raise ValueError("No JSON object could be decoded")
-        return obj, end
-
-__all__ = ['JSONDecoder']
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/encoder.py
+++ /dev/null
@@ -1,395 +0,0 @@
-"""
-Implementation of JSONEncoder
-"""
-import re
-
-try:
-    from simplejson._speedups import encode_basestring_ascii as c_encode_basestring_ascii
-except ImportError:
-    pass
-
-ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
-ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
-HAS_UTF8 = re.compile(r'[\x80-\xff]')
-ESCAPE_DCT = {
-    '\\': '\\\\',
-    '"': '\\"',
-    '\b': '\\b',
-    '\f': '\\f',
-    '\n': '\\n',
-    '\r': '\\r',
-    '\t': '\\t',
-}
-for i in range(0x20):
-    ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
-
-# Assume this produces an infinity on all machines (probably not guaranteed)
-INFINITY = float('1e66666')
-FLOAT_REPR = repr
-
-def floatstr(o, allow_nan=True):
-    """
-    Check for specials.  Note that this type of test is processor- and/or
-    platform-specific, so do tests which don't depend on the internals.
-    """
-    if o != o:
-        text = 'NaN'
-    elif o == INFINITY:
-        text = 'Infinity'
-    elif o == -INFINITY:
-        text = '-Infinity'
-    else:
-        return FLOAT_REPR(o)
-
-    if not allow_nan:
-        raise ValueError("Out of range float values are not JSON compliant: %r"
-            % (o,))
-
-    return text
-
-
-def encode_basestring(s):
-    """
-    Return a JSON representation of a Python string
-    """
-    def replace(match):
-        return ESCAPE_DCT[match.group(0)]
-    return '"' + ESCAPE.sub(replace, s) + '"'
-
-
-def py_encode_basestring_ascii(s):
-    if isinstance(s, str) and HAS_UTF8.search(s) is not None:
-        s = s.decode('utf-8')
-    def replace(match):
-        s = match.group(0)
-        try:
-            return ESCAPE_DCT[s]
-        except KeyError:
-            n = ord(s)
-            if n < 0x10000:
-                return '\\u%04x' % (n,)
-            else:
-                # surrogate pair
-                n -= 0x10000
-                s1 = 0xd800 | ((n >> 10) & 0x3ff)
-                s2 = 0xdc00 | (n & 0x3ff)
-                return '\\u%04x\\u%04x' % (s1, s2)
-    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
-
-
-try:
-    encode_basestring_ascii = c_encode_basestring_ascii
-except NameError:
-    encode_basestring_ascii = py_encode_basestring_ascii
-
-
-class JSONEncoder(object):
-    """
-    Extensible JSON <http://json.org> encoder for Python data structures.
-
-    Supports the following objects and types by default:
-    
-    +-------------------+---------------+
-    | Python            | JSON          |
-    +===================+===============+
-    | dict              | object        |
-    +-------------------+---------------+
-    | list, tuple       | array         |
-    +-------------------+---------------+
-    | str, unicode      | string        |
-    +-------------------+---------------+
-    | int, long, float  | number        |
-    +-------------------+---------------+
-    | True              | true          |
-    +-------------------+---------------+
-    | False             | false         |
-    +-------------------+---------------+
-    | None              | null          |
-    +-------------------+---------------+
-
-    To extend this to recognize other objects, subclass and implement a
-    ``.default()`` method with another method that returns a serializable
-    object for ``o`` if possible, otherwise it should call the superclass
-    implementation (to raise ``TypeError``).
-    """
-    __all__ = ['__init__', 'default', 'encode', 'iterencode']
-    item_separator = ', '
-    key_separator = ': '
-    def __init__(self, skipkeys=False, ensure_ascii=True,
-            check_circular=True, allow_nan=True, sort_keys=False,
-            indent=None, separators=None, encoding='utf-8', default=None):
-        """
-        Constructor for JSONEncoder, with sensible defaults.
-
-        If skipkeys is False, then it is a TypeError to attempt
-        encoding of keys that are not str, int, long, float or None.  If
-        skipkeys is True, such items are simply skipped.
-
-        If ensure_ascii is True, the output is guaranteed to be str
-        objects with all incoming unicode characters escaped.  If
-        ensure_ascii is false, the output will be unicode object.
-
-        If check_circular is True, then lists, dicts, and custom encoded
-        objects will be checked for circular references during encoding to
-        prevent an infinite recursion (which would cause an OverflowError).
-        Otherwise, no such check takes place.
-
-        If allow_nan is True, then NaN, Infinity, and -Infinity will be
-        encoded as such.  This behavior is not JSON specification compliant,
-        but is consistent with most JavaScript based encoders and decoders.
-        Otherwise, it will be a ValueError to encode such floats.
-
-        If sort_keys is True, then the output of dictionaries will be
-        sorted by key; this is useful for regression tests to ensure
-        that JSON serializations can be compared on a day-to-day basis.
-
-        If indent is a non-negative integer, then JSON array
-        elements and object members will be pretty-printed with that
-        indent level.  An indent level of 0 will only insert newlines.
-        None is the most compact representation.
-
-        If specified, separators should be a (item_separator, key_separator)
-        tuple.  The default is (', ', ': ').  To get the most compact JSON
-        representation you should specify (',', ':') to eliminate whitespace.
-
-        If specified, default is a function that gets called for objects
-        that can't otherwise be serialized.  It should return a JSON encodable
-        version of the object or raise a ``TypeError``.
-
-        If encoding is not None, then all input strings will be
-        transformed into unicode using that encoding prior to JSON-encoding.
-        The default is UTF-8.
-        """
-
-        self.skipkeys = skipkeys
-        self.ensure_ascii = ensure_ascii
-        self.check_circular = check_circular
-        self.allow_nan = allow_nan
-        self.sort_keys = sort_keys
-        self.indent = indent
-        self.current_indent_level = 0
-        if separators is not None:
-            self.item_separator, self.key_separator = separators
-        if default is not None:
-            self.default = default
-        self.encoding = encoding
-
-    def _newline_indent(self):
-        """
-        Indent lines by level
-        """
-        return '\n' + (' ' * (self.indent * self.current_indent_level))
-
-    def _iterencode_list(self, lst, markers=None):
-        """
-        Encoding lists, yielding by level
-        """
-        if not lst:
-            yield '[]'
-            return
-        if markers is not None:
-            markerid = id(lst)
-            if markerid in markers:
-                raise ValueError("Circular reference detected")
-            markers[markerid] = lst
-        yield '['
-        if self.indent is not None:
-            self.current_indent_level += 1
-            newline_indent = self._newline_indent()
-            separator = self.item_separator + newline_indent
-            yield newline_indent
-        else:
-            newline_indent = None
-            separator = self.item_separator
-        first = True
-        for value in lst:
-            if first:
-                first = False
-            else:
-                yield separator
-            for chunk in self._iterencode(value, markers):
-                yield chunk
-        if newline_indent is not None:
-            self.current_indent_level -= 1
-            yield self._newline_indent()
-        yield ']'
-        if markers is not None:
-            del markers[markerid]
-
-    def _iterencode_dict(self, dct, markers=None):
-        """
-        Encoding dictionaries, yielding by level
-        """
-        if not dct:
-            yield '{}'
-            return
-        if markers is not None:
-            markerid = id(dct)
-            if markerid in markers:
-                raise ValueError("Circular reference detected")
-            markers[markerid] = dct
-        yield '{'
-        key_separator = self.key_separator
-        if self.indent is not None:
-            self.current_indent_level += 1
-            newline_indent = self._newline_indent()
-            item_separator = self.item_separator + newline_indent
-            yield newline_indent
-        else:
-            newline_indent = None
-            item_separator = self.item_separator
-        first = True
-        if self.ensure_ascii:
-            encoder = encode_basestring_ascii
-        else:
-            encoder = encode_basestring
-        allow_nan = self.allow_nan
-        if self.sort_keys:
-            keys = dct.keys()
-            keys.sort()
-            items = [(k, dct[k]) for k in keys]
-        else:
-            items = dct.iteritems()
-        _encoding = self.encoding
-        _do_decode = (_encoding is not None
-            and not (_encoding == 'utf-8'))
-        for key, value in items:
-            if isinstance(key, str):
-                if _do_decode:
-                    key = key.decode(_encoding)
-            elif isinstance(key, basestring):
-                pass
-            # JavaScript is weakly typed for these, so it makes sense to
-            # also allow them.  Many encoders seem to do something like this.
-            elif isinstance(key, float):
-                key = floatstr(key, allow_nan)
-            elif isinstance(key, (int, long)):
-                key = str(key)
-            elif key is True:
-                key = 'true'
-            elif key is False:
-                key = 'false'
-            elif key is None:
-                key = 'null'
-            elif self.skipkeys:
-                continue
-            else:
-                raise TypeError("key %r is not a string" % (key,))
-            if first:
-                first = False
-            else:
-                yield item_separator
-            yield encoder(key)
-            yield key_separator
-            for chunk in self._iterencode(value, markers):
-                yield chunk
-        if newline_indent is not None:
-            self.current_indent_level -= 1
-            yield self._newline_indent()
-        yield '}'
-        if markers is not None:
-            del markers[markerid]
-
-    def _iterencode(self, o, markers=None):
-        if isinstance(o, basestring):
-            if self.ensure_ascii:
-                encoder = encode_basestring_ascii
-            else:
-                encoder = encode_basestring
-            _encoding = self.encoding
-            if (_encoding is not None and isinstance(o, str)
-                    and not (_encoding == 'utf-8')):
-                o = o.decode(_encoding)
-            yield encoder(o)
-        elif o is None:
-            yield 'null'
-        elif o is True:
-            yield 'true'
-        elif o is False:
-            yield 'false'
-        elif isinstance(o, (int, long)):
-            yield str(o)
-        elif isinstance(o, float):
-            yield floatstr(o, self.allow_nan)
-        elif isinstance(o, (list, tuple)):
-            for chunk in self._iterencode_list(o, markers):
-                yield chunk
-        elif isinstance(o, dict):
-            for chunk in self._iterencode_dict(o, markers):
-                yield chunk
-        else:
-            if markers is not None:
-                markerid = id(o)
-                if markerid in markers:
-                    raise ValueError("Circular reference detected")
-                markers[markerid] = o
-            for chunk in self._iterencode_default(o, markers):
-                yield chunk
-            if markers is not None:
-                del markers[markerid]
-
-    def _iterencode_default(self, o, markers=None):
-        newobj = self.default(o)
-        return self._iterencode(newobj, markers)
-
-    def default(self, o):
-        """
-        Implement this method in a subclass such that it returns
-        a serializable object for ``o``, or calls the base implementation
-        (to raise a ``TypeError``).
-
-        For example, to support arbitrary iterators, you could
-        implement default like this::
-            
-            def default(self, o):
-                try:
-                    iterable = iter(o)
-                except TypeError:
-                    pass
-                else:
-                    return list(iterable)
-                return JSONEncoder.default(self, o)
-        """
-        raise TypeError("%r is not JSON serializable" % (o,))
-
-    def encode(self, o):
-        """
-        Return a JSON string representation of a Python data structure.
-
-        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
-        '{"foo": ["bar", "baz"]}'
-        """
-        # This is for extremely simple cases and benchmarks.
-        if isinstance(o, basestring):
-            if isinstance(o, str):
-                _encoding = self.encoding
-                if (_encoding is not None 
-                        and not (_encoding == 'utf-8')):
-                    o = o.decode(_encoding)
-            if self.ensure_ascii:
-                return encode_basestring_ascii(o)
-            else:
-                return encode_basestring(o)
-        # This doesn't pass the iterator directly to ''.join() because the
-        # exceptions aren't as detailed.  The list call should be roughly
-        # equivalent to the PySequence_Fast that ''.join() would do.
-        chunks = list(self.iterencode(o))
-        return ''.join(chunks)
-
-    def iterencode(self, o):
-        """
-        Encode the given object and yield each string
-        representation as available.
-        
-        For example::
-            
-            for chunk in JSONEncoder().iterencode(bigobject):
-                mysocket.write(chunk)
-        """
-        if self.check_circular:
-            markers = {}
-        else:
-            markers = None
-        return self._iterencode(o, markers)
-
-__all__ = ['JSONEncoder']
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/scanner.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""
-Iterator based sre token scanner
-"""
-import re
-from re import VERBOSE, MULTILINE, DOTALL
-import sre_parse
-import sre_compile
-import sre_constants
-from sre_constants import BRANCH, SUBPATTERN
-
-__all__ = ['Scanner', 'pattern']
-
-FLAGS = (VERBOSE | MULTILINE | DOTALL)
-
-class Scanner(object):
-    def __init__(self, lexicon, flags=FLAGS):
-        self.actions = [None]
-        # Combine phrases into a compound pattern
-        s = sre_parse.Pattern()
-        s.flags = flags
-        p = []
-        for idx, token in enumerate(lexicon):
-            phrase = token.pattern
-            try:
-                subpattern = sre_parse.SubPattern(s,
-                    [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])
-            except sre_constants.error:
-                raise
-            p.append(subpattern)
-            self.actions.append(token)
-
-        s.groups = len(p) + 1 # NOTE(guido): Added to make SRE validation work
-        p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
-        self.scanner = sre_compile.compile(p)
-
-    def iterscan(self, string, idx=0, context=None):
-        """
-        Yield match, end_idx for each match
-        """
-        match = self.scanner.scanner(string, idx).match
-        actions = self.actions
-        lastend = idx
-        end = len(string)
-        while True:
-            m = match()
-            if m is None:
-                break
-            matchbegin, matchend = m.span()
-            if lastend == matchend:
-                break
-            action = actions[m.lastindex]
-            if action is not None:
-                rval, next_pos = action(m, context)
-                if next_pos is not None and next_pos != matchend:
-                    # "fast forward" the scanner
-                    matchend = next_pos
-                    match = self.scanner.scanner(string, matchend).match
-                yield rval, matchend
-            lastend = matchend
-
-
-def pattern(pattern, flags=FLAGS):
-    def decorator(fn):
-        fn.pattern = pattern
-        fn.regex = re.compile(pattern, flags)
-        return fn
-    return decorator
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/python-lib/simplejson/tool.py
+++ /dev/null
@@ -1,44 +0,0 @@
-r"""
-Using simplejson from the shell to validate and
-pretty-print::
-    
-    $ echo '{"json":"obj"}' | python -msimplejson
-    {
-        "json": "obj"
-    }
-    $ echo '{ 1.2:3.4}' | python -msimplejson
-    Expecting property name: line 1 column 2 (char 2)
-
-Note that the JSON produced by this module's default settings
-is a subset of YAML, so it may be used as a serializer for that as well.
-"""
-import simplejson
-
-#
-# Pretty printer:
-#     curl http://mochikit.com/examples/ajax_tables/domains.json | python -msimplejson.tool
-#
-
-def main():
-    import sys
-    if len(sys.argv) == 1:
-        infile = sys.stdin
-        outfile = sys.stdout
-    elif len(sys.argv) == 2:
-        infile = open(sys.argv[1], 'rb')
-        outfile = sys.stdout
-    elif len(sys.argv) == 3:
-        infile = open(sys.argv[1], 'rb')
-        outfile = open(sys.argv[2], 'wb')
-    else:
-        raise SystemExit("%s [infile [outfile]]" % (sys.argv[0],))
-    try:
-        obj = simplejson.load(infile)
-    except ValueError, e:
-        raise SystemExit(e)
-    simplejson.dump(obj, outfile, sort_keys=True, indent=4)
-    outfile.write('\n')
-
-
-if __name__ == '__main__':
-    main()
deleted file mode 100644
--- a/addon-sdk/source/test/addons/addon-manager/lib/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.exports = require("./test-main.js");
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/addon-manager/lib/test-main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { id } = require("sdk/self");
-const { getAddonByID } = require("sdk/addon/manager");
-
-exports["test getAddonByID"] = function*(assert) {
-  let addon = yield getAddonByID(id);
-  assert.equal(addon.id, id, "getAddonByID works");
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/addon-manager/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "id": "test-addon-manager@jetpack",
-  "main": "./lib/main.js",
-  "name": "test-addon-manager",
-  "version": "0.0.1",
-  "author": "Erik Vold"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/author-email/main.js
+++ /dev/null
@@ -1,14 +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 { id } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testContributors = function*(assert) {
-  let addon = yield getAddonByID(id);
-  assert.equal(addon.creator.name, 'test <test@mozilla.com>', '< and > characters work');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/author-email/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-addon-author-email@jetpack",
-  "author": "test <test@mozilla.com>",
-  "version": "0.0.1",
-  "main": "./main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/child_process/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/**
- * Ensures using child_process and underlying subprocess.jsm
- * works within an addon
- */
-
-const { exec } = require("sdk/system/child_process");
-const { platform, pathFor } = require("sdk/system");
-const PROFILE_DIR = pathFor("ProfD");
-const isWindows = platform.toLowerCase().indexOf("win") === 0;
-const app = require("sdk/system/xul-app");
-
-// Once Bug 903018 is resolved, just move the application testing to
-// module.metadata.engines
-if (app.is("Firefox")) {
-  exports["test child_process in an addon"] = (assert, done) => {
-    exec(isWindows ? "DIR /A-D" : "ls -al", {
-      cwd: PROFILE_DIR
-    }, (err, stdout, stderr) => {
-      assert.equal(err, null, "no errors");
-      assert.equal(stderr, "", "stderr is empty");
-      assert.ok(/extensions\.ini/.test(stdout), "stdout output of `ls -al` finds files");
-
-      if (isWindows)
-        assert.ok(!/<DIR>/.test(stdout), "passing args works");
-      else
-        assert.ok(/d(r[-|w][-|x]){3}/.test(stdout), "passing args works");
-      done();
-    });
-  };
-} else {
-  exports["test unsupported"] = (assert) => assert.pass("This application is unsupported.");
-}
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/child_process/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-child-process@jetpack",
-  "main": "./index.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome.manifest
+++ /dev/null
@@ -1,5 +0,0 @@
-content    test    chrome/content/
-skin       test    classic/1.0 chrome/skin/
-
-locale     test  en-US  chrome/locale/en-US/
-locale     test  ja-JP  chrome/locale/ja-JP/
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome/content/new-window.xul
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0"?>
-<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        windowtype="test:window">
-</dialog>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome/content/panel.html
+++ /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/. -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8">
-  </head>
-  <body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome/locale/en-US/description.properties
+++ /dev/null
@@ -1,1 +0,0 @@
-test=Test
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome/locale/ja-JP/description.properties
+++ /dev/null
@@ -1,1 +0,0 @@
-test=テスト
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/chrome/skin/style.css
+++ /dev/null
@@ -1,4 +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/. */
-test{}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/data/panel.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';
-
-self.port.on('echo', _ => {
-  self.port.emit('echo', '');
-});
-
-self.port.emit('start', '');
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/main.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict'
-
-const { Cu, Cc, Ci } = require('chrome');
-const Request = require('sdk/request').Request;
-const { WindowTracker } = require('sdk/deprecated/window-utils');
-const { close, open } = require('sdk/window/helpers');
-const { data } = require('sdk/self');
-const { Panel } = require('sdk/panel');
-const { getActiveView } = require("sdk/view/core");
-
-const XUL_URL = 'chrome://test/content/new-window.xul'
-
-const { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
-const { NetUtil } = Cu.import('resource://gre/modules/NetUtil.jsm', {});
-
-exports.testChromeSkin = function(assert, done) {
-  let skinURL = 'chrome://test/skin/style.css';
-
-  Request({
-    url: skinURL,
-    overrideMimeType: 'text/plain',
-    onComplete: function (response) {
-      assert.ok(/test\{\}\s*$/.test(response.text), 'chrome.manifest skin folder was registered!');
-      done();
-    }
-  }).get();
-
-  assert.pass('requesting ' + skinURL);
-}
-
-exports.testChromeContent = function(assert, done) {
-  let wt = WindowTracker({
-    onTrack: function(window) {
-      if (window.document.documentElement.getAttribute('windowtype') === 'test:window') {
-      	assert.pass('test xul window was opened');
-        wt.unload();
-
-      	close(window).then(done, assert.fail);
-      }
-    }
-  });
-
-  open(XUL_URL).then(
-    assert.pass.bind(assert, 'opened ' + XUL_URL),
-    assert.fail);
-
-  assert.pass('opening ' + XUL_URL);
-}
-
-exports.testChromeLocale = function(assert) {
-  let jpLocalePath = Cc['@mozilla.org/chrome/chrome-registry;1'].
-                       getService(Ci.nsIChromeRegistry).
-                       convertChromeURL(NetUtil.newURI('chrome://test/locale/description.properties')).
-                       spec.replace(/(en\-US|ja\-JP)/, 'ja-JP');
-  let enLocalePath = jpLocalePath.replace(/ja\-JP/, 'en-US');
-
-  let jpStringBundle = Services.strings.createBundle(jpLocalePath);
-  assert.equal(jpStringBundle.GetStringFromName('test'),
-               'テスト',
-               'locales ja-JP folder was copied correctly');
-
-  let enStringBundle = Services.strings.createBundle(enLocalePath);
-  assert.equal(enStringBundle.GetStringFromName('test'),
-               'Test',
-               'locales en-US folder was copied correctly');
-}
-
-exports.testChromeInPanel = function*(assert) {
-  let panel = Panel({
-    contentURL: 'chrome://test/content/panel.html',
-    contentScriptWhen: 'end',
-    contentScriptFile: data.url('panel.js')
-  });
-
-  getActiveView(panel);
-
-  yield new Promise(resolve => panel.port.once('start', resolve));
-  assert.pass('start was emitted');
-
-  yield new Promise(resolve => {
-    panel.once('show', resolve);
-    panel.show();
-  });
-  assert.pass('panel shown');
-
-  yield new Promise(resolve => {
-    panel.port.once('echo', resolve);
-    panel.port.emit('echo');
-  });
-
-  assert.pass('got echo');
-
-  panel.destroy();
-  assert.pass('panel is destroyed');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/chrome/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-chrome@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-permissions/httpd.js
+++ /dev/null
@@ -1,5205 +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/. */
-
-/*
-*  NOTE: do not edit this file, this is copied from:
-*  https://github.com/mozilla/addon-sdk/blob/master/test/lib/httpd.js
-*/
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { components, CC, Cc, Ci, Cr, Cu } = require("chrome");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
-const PR_UINT32_MAX = Math.pow(2, 32) - 1;
-
-/** True if debugging output is enabled, false otherwise. */
-var DEBUG = false; // non-const *only* so tweakable in server tests
-
-/** True if debugging output should be timestamped. */
-var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests
-
-var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance();
-
-/**
-* Asserts that the given condition holds. If it doesn't, the given message is
-* dumped, a stack trace is printed, and an exception is thrown to attempt to
-* stop execution (which unfortunately must rely upon the exception not being
-* accidentally swallowed by the code that uses it).
-*/
-function NS_ASSERT(cond, msg)
-{
-  if (DEBUG && !cond)
-  {
-    dumpn("###!!!");
-    dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!"));
-    dumpn("###!!! Stack follows:");
-
-    var stack = new Error().stack.split(/\n/);
-    dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n"));
-
-    throw Cr.NS_ERROR_ABORT;
-  }
-}
-
-/** Constructs an HTTP error object. */
-function HttpError(code, description)
-{
-  this.code = code;
-  this.description = description;
-}
-HttpError.prototype =
-{
-  toString: function()
-  {
-    return this.code + " " + this.description;
-  }
-};
-
-/**
-* Errors thrown to trigger specific HTTP server responses.
-*/
-const HTTP_400 = new HttpError(400, "Bad Request");
-const HTTP_401 = new HttpError(401, "Unauthorized");
-const HTTP_402 = new HttpError(402, "Payment Required");
-const HTTP_403 = new HttpError(403, "Forbidden");
-const HTTP_404 = new HttpError(404, "Not Found");
-const HTTP_405 = new HttpError(405, "Method Not Allowed");
-const HTTP_406 = new HttpError(406, "Not Acceptable");
-const HTTP_407 = new HttpError(407, "Proxy Authentication Required");
-const HTTP_408 = new HttpError(408, "Request Timeout");
-const HTTP_409 = new HttpError(409, "Conflict");
-const HTTP_410 = new HttpError(410, "Gone");
-const HTTP_411 = new HttpError(411, "Length Required");
-const HTTP_412 = new HttpError(412, "Precondition Failed");
-const HTTP_413 = new HttpError(413, "Request Entity Too Large");
-const HTTP_414 = new HttpError(414, "Request-URI Too Long");
-const HTTP_415 = new HttpError(415, "Unsupported Media Type");
-const HTTP_417 = new HttpError(417, "Expectation Failed");
-
-const HTTP_500 = new HttpError(500, "Internal Server Error");
-const HTTP_501 = new HttpError(501, "Not Implemented");
-const HTTP_502 = new HttpError(502, "Bad Gateway");
-const HTTP_503 = new HttpError(503, "Service Unavailable");
-const HTTP_504 = new HttpError(504, "Gateway Timeout");
-const HTTP_505 = new HttpError(505, "HTTP Version Not Supported");
-
-/** Creates a hash with fields corresponding to the values in arr. */
-function array2obj(arr)
-{
-  var obj = {};
-  for (var i = 0; i < arr.length; i++)
-    obj[arr[i]] = arr[i];
-  return obj;
-}
-
-/** Returns an array of the integers x through y, inclusive. */
-function range(x, y)
-{
-  var arr = [];
-  for (var i = x; i <= y; i++)
-    arr.push(i);
-  return arr;
-}
-
-/** An object (hash) whose fields are the numbers of all HTTP error codes. */
-const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505)));
-
-
-/**
-* The character used to distinguish hidden files from non-hidden files, a la
-* the leading dot in Apache. Since that mechanism also hides files from
-* easy display in LXR, ls output, etc. however, we choose instead to use a
-* suffix character. If a requested file ends with it, we append another
-* when getting the file on the server. If it doesn't, we just look up that
-* file. Therefore, any file whose name ends with exactly one of the character
-* is "hidden" and available for use by the server.
-*/
-const HIDDEN_CHAR = "^";
-
-/**
-* The file name suffix indicating the file containing overridden headers for
-* a requested file.
-*/
-const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
-
-/** Type used to denote SJS scripts for CGI-like functionality. */
-const SJS_TYPE = "sjs";
-
-/** Base for relative timestamps produced by dumpn(). */
-var firstStamp = 0;
-
-/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */
-function dumpn(str)
-{
-  if (DEBUG)
-  {
-    var prefix = "HTTPD-INFO | ";
-    if (DEBUG_TIMESTAMP)
-    {
-      if (firstStamp === 0)
-        firstStamp = Date.now();
-
-      var elapsed = Date.now() - firstStamp; // milliseconds
-      var min = Math.floor(elapsed / 60000);
-      var sec = (elapsed % 60000) / 1000;
-
-      if (sec < 10)
-        prefix += min + ":0" + sec.toFixed(3) + " | ";
-      else
-        prefix += min + ":" + sec.toFixed(3) + " | ";
-    }
-
-    dump(prefix + str + "\n");
-  }
-}
-
-/** Dumps the current JS stack if DEBUG. */
-function dumpStack()
-{
-  // peel off the frames for dumpStack() and Error()
-  var stack = new Error().stack.split(/\n/).slice(2);
-  stack.forEach(dumpn);
-}
-
-
-/** The XPCOM thread manager. */
-var gThreadManager = null;
-
-/** The XPCOM prefs service. */
-var gRootPrefBranch = null;
-function getRootPrefBranch()
-{
-  if (!gRootPrefBranch)
-  {
-    gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"]
-                        .getService(Ci.nsIPrefBranch);
-  }
-  return gRootPrefBranch;
-}
-
-/**
-* JavaScript constructors for commonly-used classes; precreating these is a
-* speedup over doing the same from base principles. See the docs at
-* http://developer.mozilla.org/en/docs/components.Constructor for details.
-*/
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
-                                 "nsIScriptableInputStream",
-                                 "init");
-const Pipe = CC("@mozilla.org/pipe;1",
-                "nsIPipe",
-                "init");
-const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
-                           "nsIFileInputStream",
-                           "init");
-const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1",
-                                "nsIConverterInputStream",
-                                "init");
-const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
-                               "nsIWritablePropertyBag2");
-const SupportsString = CC("@mozilla.org/supports-string;1",
-                          "nsISupportsString");
-
-/* These two are non-const only so a test can overwrite them. */
-var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
-                            "nsIBinaryOutputStream",
-                            "setOutputStream");
-
-/**
-* Returns the RFC 822/1123 representation of a date.
-*
-* @param date : Number
-* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT
-* @returns string
-* the representation of the given date
-*/
-function toDateString(date)
-{
-  //
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // date1 = 2DIGIT SP month SP 4DIGIT
-  // ; day month year (e.g., 02 Jun 1982)
-  // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  // ; 00:00:00 - 23:59:59
-  // wkday = "Mon" | "Tue" | "Wed"
-  // | "Thu" | "Fri" | "Sat" | "Sun"
-  // month = "Jan" | "Feb" | "Mar" | "Apr"
-  // | "May" | "Jun" | "Jul" | "Aug"
-  // | "Sep" | "Oct" | "Nov" | "Dec"
-  //
-
-  const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-  const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-  /**
-* Processes a date and returns the encoded UTC time as a string according to
-* the format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toTime(date)
-  {
-    var hrs = date.getUTCHours();
-    var rv = (hrs < 10) ? "0" + hrs : hrs;
-
-    var mins = date.getUTCMinutes();
-    rv += ":";
-    rv += (mins < 10) ? "0" + mins : mins;
-
-    var secs = date.getUTCSeconds();
-    rv += ":";
-    rv += (secs < 10) ? "0" + secs : secs;
-
-    return rv;
-  }
-
-  /**
-* Processes a date and returns the encoded UTC date as a string according to
-* the date1 format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toDate1(date)
-  {
-    var day = date.getUTCDate();
-    var month = date.getUTCMonth();
-    var year = date.getUTCFullYear();
-
-    var rv = (day < 10) ? "0" + day : day;
-    rv += " " + monthStrings[month];
-    rv += " " + year;
-
-    return rv;
-  }
-
-  date = new Date(date);
-
-  const fmtString = "%wkday%, %date1% %time% GMT";
-  var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]);
-  rv = rv.replace("%time%", toTime(date));
-  return rv.replace("%date1%", toDate1(date));
-}
-
-/**
-* Prints out a human-readable representation of the object o and its fields,
-* omitting those whose names begin with "_" if showMembers != true (to ignore
-* "private" properties exposed via getters/setters).
-*/
-function printObj(o, showMembers)
-{
-  var s = "******************************\n";
-  s += "o = {\n";
-  for (var i in o)
-  {
-    if (typeof(i) != "string" ||
-        (showMembers || (i.length > 0 && i[0] != "_")))
-      s+= " " + i + ": " + o[i] + ",\n";
-  }
-  s += " };\n";
-  s += "******************************";
-  dumpn(s);
-}
-
-/**
-* Instantiates a new HTTP server.
-*/
-function nsHttpServer()
-{
-  if (!gThreadManager)
-    gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-
-  /** The port on which this server listens. */
-  this._port = undefined;
-
-  /** The socket associated with this. */
-  this._socket = null;
-
-  /** The handler used to process requests to this server. */
-  this._handler = new ServerHandler(this);
-
-  /** Naming information for this server. */
-  this._identity = new ServerIdentity();
-
-  /**
-* Indicates when the server is to be shut down at the end of the request.
-*/
-  this._doQuit = false;
-
-  /**
-* True if the socket in this is closed (and closure notifications have been
-* sent and processed if the socket was ever opened), false otherwise.
-*/
-  this._socketClosed = true;
-
-  /**
-* Used for tracking existing connections and ensuring that all connections
-* are properly cleaned up before server shutdown; increases by 1 for every
-* new incoming connection.
-*/
-  this._connectionGen = 0;
-
-  /**
-* Hash of all open connections, indexed by connection number at time of
-* creation.
-*/
-  this._connections = {};
-}
-nsHttpServer.prototype =
-{
-  classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"),
-
-  // NSISERVERSOCKETLISTENER
-
-  /**
-* Processes an incoming request coming in on the given socket and contained
-* in the given transport.
-*
-* @param socket : nsIServerSocket
-* the socket through which the request was served
-* @param trans : nsISocketTransport
-* the transport for the request/response
-* @see nsIServerSocketListener.onSocketAccepted
-*/
-  onSocketAccepted: function(socket, trans)
-  {
-    dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")");
-
-    dumpn(">>> new connection on " + trans.host + ":" + trans.port);
-
-    const SEGMENT_SIZE = 8192;
-    const SEGMENT_COUNT = 1024;
-    try
-    {
-      var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
-                       .QueryInterface(Ci.nsIAsyncInputStream);
-      var output = trans.openOutputStream(0, 0, 0);
-    }
-    catch (e)
-    {
-      dumpn("*** error opening transport streams: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    var connectionNumber = ++this._connectionGen;
-
-    try
-    {
-      var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
-      var reader = new RequestReader(conn);
-
-      // XXX add request timeout functionality here!
-
-      // Note: must use main thread here, or we might get a GC that will cause
-      // threadsafety assertions. We really need to fix XPConnect so that
-      // you can actually do things in multi-threaded JS. :-(
-      input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
-    }
-    catch (e)
-    {
-      // Assume this connection can't be salvaged and bail on it completely;
-      // don't attempt to close it so that we can assert that any connection
-      // being closed is in this._connections.
-      dumpn("*** error in initial request-processing stages: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    this._connections[connectionNumber] = conn;
-    dumpn("*** starting connection " + connectionNumber);
-  },
-
-  /**
-* Called when the socket associated with this is closed.
-*
-* @param socket : nsIServerSocket
-* the socket being closed
-* @param status : nsresult
-* the reason the socket stopped listening (NS_BINDING_ABORTED if the server
-* was stopped using nsIHttpServer.stop)
-* @see nsIServerSocketListener.onStopListening
-*/
-  onStopListening: function(socket, status)
-  {
-    dumpn(">>> shutting down server on port " + socket.port);
-    this._socketClosed = true;
-    if (!this._hasOpenConnections())
-    {
-      dumpn("*** no open connections, notifying async from onStopListening");
-
-      // Notify asynchronously so that any pending teardown in stop() has a
-      // chance to run first.
-      var self = this;
-      var stopEvent =
-        {
-          run: function()
-          {
-            dumpn("*** _notifyStopped async callback");
-            self._notifyStopped();
-          }
-        };
-      gThreadManager.dispatchToMainThread(stopEvent);
-    }
-  },
-
-  // NSIHTTPSERVER
-
-  //
-  // see nsIHttpServer.start
-  //
-  start: function(port)
-  {
-    this._start(port, "localhost")
-  },
-
-  _start: function(port, host)
-  {
-    if (this._socket)
-      throw Cr.NS_ERROR_ALREADY_INITIALIZED;
-
-    this._port = port;
-    this._doQuit = this._socketClosed = false;
-
-    this._host = host;
-
-    // The listen queue needs to be long enough to handle
-    // network.http.max-persistent-connections-per-server concurrent connections,
-    // plus a safety margin in case some other process is talking to
-    // the server as well.
-    var prefs = getRootPrefBranch();
-    var maxConnections;
-    try {
-      // Bug 776860: The original pref was removed in favor of this new one:
-      maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server") + 5;
-    }
-    catch(e) {
-      maxConnections = prefs.getIntPref("network.http.max-connections-per-server") + 5;
-    }
-
-    try
-    {
-      var loopback = true;
-      if (this._host != "127.0.0.1" && this._host != "localhost") {
-        var loopback = false;
-      }
-
-      var socket = new ServerSocket(this._port,
-                                    loopback, // true = localhost, false = everybody
-                                    maxConnections);
-      dumpn(">>> listening on port " + socket.port + ", " + maxConnections +
-            " pending connections");
-      socket.asyncListen(this);
-      this._identity._initialize(socket.port, host, true);
-      this._socket = socket;
-    }
-    catch (e)
-    {
-      dumpn("!!! could not start server on port " + port + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-  },
-
-  //
-  // see nsIHttpServer.stop
-  //
-  stop: function(callback)
-  {
-    if (!callback)
-      throw Cr.NS_ERROR_NULL_POINTER;
-    if (!this._socket)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    this._stopCallback = typeof callback === "function"
-                       ? callback
-                       : function() { callback.onStopped(); };
-
-    dumpn(">>> stopping listening on port " + this._socket.port);
-    this._socket.close();
-    this._socket = null;
-
-    // We can't have this identity any more, and the port on which we're running
-    // this server now could be meaningless the next time around.
-    this._identity._teardown();
-
-    this._doQuit = false;
-
-    // socket-close notification and pending request completion happen async
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (file && (!file.exists() || file.isDirectory()))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handler.registerFile(path, file);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/" ||
-        path.charAt(path.length - 1) != "/" ||
-        (directory &&
-         (!directory.exists() || !directory.isDirectory())))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping
-    // exists!
-
-    this._handler.registerDirectory(path, directory);
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    this._handler.registerPathHandler(path, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    this._handler.registerPrefixHandler(prefix, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(code, handler)
-  {
-    this._handler.registerErrorHandler(code, handler);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    this._handler.setIndexHandler(handler);
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    this._handler.registerContentType(ext, type);
-  },
-
-  //
-  // see nsIHttpServer.serverIdentity
-  //
-  get identity()
-  {
-    return this._identity;
-  },
-
-  //
-  // see nsIHttpServer.getState
-  //
-  getState: function(path, k)
-  {
-    return this._handler._getState(path, k);
-  },
-
-  //
-  // see nsIHttpServer.setState
-  //
-  setState: function(path, k, v)
-  {
-    return this._handler._setState(path, k, v);
-  },
-
-  //
-  // see nsIHttpServer.getSharedState
-  //
-  getSharedState: function(k)
-  {
-    return this._handler._getSharedState(k);
-  },
-
-  //
-  // see nsIHttpServer.setSharedState
-  //
-  setSharedState: function(k, v)
-  {
-    return this._handler._setSharedState(k, v);
-  },
-
-  //
-  // see nsIHttpServer.getObjectState
-  //
-  getObjectState: function(k)
-  {
-    return this._handler._getObjectState(k);
-  },
-
-  //
-  // see nsIHttpServer.setObjectState
-  //
-  setObjectState: function(k, v)
-  {
-    return this._handler._setObjectState(k, v);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NON-XPCOM PUBLIC API
-
-  /**
-* Returns true iff this server is not running (and is not in the process of
-* serving any requests still to be processed when the server was last
-* stopped after being run).
-*/
-  isStopped: function()
-  {
-    return this._socketClosed && !this._hasOpenConnections();
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /** True if this server has any open connections to it, false otherwise. */
-  _hasOpenConnections: function()
-  {
-    //
-    // If we have any open connections, they're tracked as numeric properties on
-    // |this._connections|. The non-standard __count__ property could be used
-    // to check whether there are any properties, but standard-wise, even
-    // looking forward to ES5, there's no less ugly yet still O(1) way to do
-    // this.
-    //
-    for (var n in this._connections)
-      return true;
-    return false;
-  },
-
-  /** Calls the server-stopped callback provided when stop() was called. */
-  _notifyStopped: function()
-  {
-    NS_ASSERT(this._stopCallback !== null, "double-notifying?");
-    NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now");
-
-    //
-    // NB: We have to grab this now, null out the member, *then* call the
-    // callback here, or otherwise the callback could (indirectly) futz with
-    // this._stopCallback by starting and immediately stopping this, at
-    // which point we'd be nulling out a field we no longer have a right to
-    // modify.
-    //
-    var callback = this._stopCallback;
-    this._stopCallback = null;
-    try
-    {
-      callback();
-    }
-    catch (e)
-    {
-      // not throwing because this is specified as being usually (but not
-      // always) asynchronous
-      dump("!!! error running onStopped callback: " + e + "\n");
-    }
-  },
-
-  /**
-* Notifies this server that the given connection has been closed.
-*
-* @param connection : Connection
-* the connection that was closed
-*/
-  _connectionClosed: function(connection)
-  {
-    NS_ASSERT(connection.number in this._connections,
-              "closing a connection " + this + " that we never added to the " +
-              "set of open connections?");
-    NS_ASSERT(this._connections[connection.number] === connection,
-              "connection number mismatch? " +
-              this._connections[connection.number]);
-    delete this._connections[connection.number];
-
-    // Fire a pending server-stopped notification if it's our responsibility.
-    if (!this._hasOpenConnections() && this._socketClosed)
-      this._notifyStopped();
-  },
-
-  /**
-* Requests that the server be shut down when possible.
-*/
-  _requestQuit: function()
-  {
-    dumpn(">>> requesting a quit");
-    dumpStack();
-    this._doQuit = true;
-  }
-};
-
-
-//
-// RFC 2396 section 3.2.2:
-//
-// host = hostname | IPv4address
-// hostname = *( domainlabel "." ) toplabel [ "." ]
-// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-//
-
-const HOST_REGEX =
-  new RegExp("^(?:" +
-               // *( domainlabel "." )
-               "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
-               // toplabel
-               "[a-z](?:[a-z0-9-]*[a-z0-9])?" +
-             "|" +
-               // IPv4 address
-               "\\d+\\.\\d+\\.\\d+\\.\\d+" +
-             ")$",
-             "i");
-
-
-/**
-* Represents the identity of a server. An identity consists of a set of
-* (scheme, host, port) tuples denoted as locations (allowing a single server to
-* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any
-* host/port). Any incoming request must be to one of these locations, or it
-* will be rejected with an HTTP 400 error. One location, denoted as the
-* primary location, is the location assigned in contexts where a location
-* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests.
-*
-* A single identity may contain at most one location per unique host/port pair;
-* other than that, no restrictions are placed upon what locations may
-* constitute an identity.
-*/
-function ServerIdentity()
-{
-  /** The scheme of the primary location. */
-  this._primaryScheme = "http";
-
-  /** The hostname of the primary location. */
-  this._primaryHost = "127.0.0.1"
-
-  /** The port number of the primary location. */
-  this._primaryPort = -1;
-
-  /**
-* The current port number for the corresponding server, stored so that a new
-* primary location can always be set if the current one is removed.
-*/
-  this._defaultPort = -1;
-
-  /**
-* Maps hosts to maps of ports to schemes, e.g. the following would represent
-* https://example.com:789/ and http://example.org/:
-*
-* {
-* "xexample.com": { 789: "https" },
-* "xexample.org": { 80: "http" }
-* }
-*
-* Note the "x" prefix on hostnames, which prevents collisions with special
-* JS names like "prototype".
-*/
-  this._locations = { "xlocalhost": {} };
-}
-ServerIdentity.prototype =
-{
-  // NSIHTTPSERVERIDENTITY
-
-  //
-  // see nsIHttpServerIdentity.primaryScheme
-  //
-  get primaryScheme()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryScheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryHost
-  //
-  get primaryHost()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryHost;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryPort
-  //
-  get primaryPort()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryPort;
-  },
-
-  //
-  // see nsIHttpServerIdentity.add
-  //
-  add: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      this._locations["x" + host] = entry = {};
-
-    entry[port] = scheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.remove
-  //
-  remove: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return false;
-
-    var present = port in entry;
-    delete entry[port];
-
-    if (this._primaryScheme == scheme &&
-        this._primaryHost == host &&
-        this._primaryPort == port &&
-        this._defaultPort !== -1)
-    {
-      // Always keep at least one identity in existence at any time, unless
-      // we're in the process of shutting down (the last condition above).
-      this._primaryPort = -1;
-      this._initialize(this._defaultPort, host, false);
-    }
-
-    return present;
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  has: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    return "x" + host in this._locations &&
-           scheme === this._locations["x" + host][port];
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  getScheme: function(host, port)
-  {
-    this._validate("http", host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return "";
-
-    return entry[port] || "";
-  },
-
-  //
-  // see nsIHttpServerIdentity.setPrimary
-  //
-  setPrimary: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    this.add(scheme, host, port);
-
-    this._primaryScheme = scheme;
-    this._primaryHost = host;
-    this._primaryPort = port;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Initializes the primary name for the corresponding server, based on the
-* provided port number.
-*/
-  _initialize: function(port, host, addSecondaryDefault)
-  {
-    this._host = host;
-    if (this._primaryPort !== -1)
-      this.add("http", host, port);
-    else
-      this.setPrimary("http", "localhost", port);
-    this._defaultPort = port;
-
-    // Only add this if we're being called at server startup
-    if (addSecondaryDefault && host != "127.0.0.1")
-      this.add("http", "127.0.0.1", port);
-  },
-
-  /**
-* Called at server shutdown time, unsets the primary location only if it was
-* the default-assigned location and removes the default location from the
-* set of locations used.
-*/
-  _teardown: function()
-  {
-    if (this._host != "127.0.0.1") {
-      // Not the default primary location, nothing special to do here
-      this.remove("http", "127.0.0.1", this._defaultPort);
-    }
-
-    // This is a *very* tricky bit of reasoning here; make absolutely sure the
-    // tests for this code pass before you commit changes to it.
-    if (this._primaryScheme == "http" &&
-        this._primaryHost == this._host &&
-        this._primaryPort == this._defaultPort)
-    {
-      // Make sure we don't trigger the readding logic in .remove(), then remove
-      // the default location.
-      var port = this._defaultPort;
-      this._defaultPort = -1;
-      this.remove("http", this._host, port);
-
-      // Ensure a server start triggers the setPrimary() path in ._initialize()
-      this._primaryPort = -1;
-    }
-    else
-    {
-      // No reason not to remove directly as it's not our primary location
-      this.remove("http", this._host, this._defaultPort);
-    }
-  },
-
-  /**
-* Ensures scheme, host, and port are all valid with respect to RFC 2396.
-*
-* @throws NS_ERROR_ILLEGAL_VALUE
-* if any argument doesn't match the corresponding production
-*/
-  _validate: function(scheme, host, port)
-  {
-    if (scheme !== "http" && scheme !== "https")
-    {
-      dumpn("*** server only supports http/https schemes: '" + scheme + "'");
-      dumpStack();
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (!HOST_REGEX.test(host))
-    {
-      dumpn("*** unexpected host: '" + host + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (port < 0 || port > 65535)
-    {
-      dumpn("*** unexpected port: '" + port + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-  }
-};
-
-
-/**
-* Represents a connection to the server (and possibly in the future the thread
-* on which the connection is processed).
-*
-* @param input : nsIInputStream
-* stream from which incoming data on the connection is read
-* @param output : nsIOutputStream
-* stream to write data out the connection
-* @param server : nsHttpServer
-* the server handling the connection
-* @param port : int
-* the port on which the server is running
-* @param outgoingPort : int
-* the outgoing port used by this connection
-* @param number : uint
-* a serial number used to uniquely identify this connection
-*/
-function Connection(input, output, server, port, outgoingPort, number)
-{
-  dumpn("*** opening new connection " + number + " on port " + outgoingPort);
-
-  /** Stream of incoming data. */
-  this.input = input;
-
-  /** Stream for outgoing data. */
-  this.output = output;
-
-  /** The server associated with this request. */
-  this.server = server;
-
-  /** The port on which the server is running. */
-  this.port = port;
-
-  /** The outgoing poort used by this connection. */
-  this._outgoingPort = outgoingPort;
-
-  /** The serial number of this connection. */
-  this.number = number;
-
-  /**
-* The request for which a response is being generated, null if the
-* incoming request has not been fully received or if it had errors.
-*/
-  this.request = null;
-
-  /** State variables for debugging. */
-  this._closed = this._processed = false;
-}
-Connection.prototype =
-{
-  /** Closes this connection's input/output streams. */
-  close: function()
-  {
-    dumpn("*** closing connection " + this.number +
-          " on port " + this._outgoingPort);
-
-    this.input.close();
-    this.output.close();
-    this._closed = true;
-
-    var server = this.server;
-    server._connectionClosed(this);
-
-    // If an error triggered a server shutdown, act on it now
-    if (server._doQuit)
-      server.stop(function() { /* not like we can do anything better */ });
-  },
-
-  /**
-* Initiates processing of this connection, using the data in the given
-* request.
-*
-* @param request : Request
-* the request which should be processed
-*/
-  process: function(request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-
-    this.request = request;
-    this.server._handler.handleResponse(this);
-  },
-
-  /**
-* Initiates processing of this connection, generating a response with the
-* given HTTP error code.
-*
-* @param code : uint
-* an HTTP code, so in the range [0, 1000)
-* @param request : Request
-* incomplete data about the incoming request (since there were errors
-* during its processing
-*/
-  processError: function(code, request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-    this.request = request;
-    this.server._handler.handleError(code, this);
-  },
-
-  /** Converts this to a string for debugging purposes. */
-  toString: function()
-  {
-    return "<Connection(" + this.number +
-           (this.request ? ", " + this.request.path : "") +"): " +
-           (this._closed ? "closed" : "open") + ">";
-  }
-};
-
-
-
-/** Returns an array of count bytes from the given input stream. */
-function readBytes(inputStream, count)
-{
-  return new BinaryInputStream(inputStream).readByteArray(count);
-}
-
-
-
-/** Request reader processing states; see RequestReader for details. */
-const READER_IN_REQUEST_LINE = 0;
-const READER_IN_HEADERS = 1;
-const READER_IN_BODY = 2;
-const READER_FINISHED = 3;
-
-
-/**
-* Reads incoming request data asynchronously, does any necessary preprocessing,
-* and forwards it to the request handler. Processing occurs in three states:
-*
-* READER_IN_REQUEST_LINE Reading the request's status line
-* READER_IN_HEADERS Reading headers in the request
-* READER_IN_BODY Reading the body of the request
-* READER_FINISHED Entire request has been read and processed
-*
-* During the first two stages, initial metadata about the request is gathered
-* into a Request object. Once the status line and headers have been processed,
-* we start processing the body of the request into the Request. Finally, when
-* the entire body has been read, we create a Response and hand it off to the
-* ServerHandler to be given to the appropriate request handler.
-*
-* @param connection : Connection
-* the connection for the request being read
-*/
-function RequestReader(connection)
-{
-  /** Connection metadata for this request. */
-  this._connection = connection;
-
-  /**
-* A container providing line-by-line access to the raw bytes that make up the
-* data which has been read from the connection but has not yet been acted
-* upon (by passing it to the request handler or by extracting request
-* metadata from it).
-*/
-  this._data = new LineData();
-
-  /**
-* The amount of data remaining to be read from the body of this request.
-* After all headers in the request have been read this is the value in the
-* Content-Length header, but as the body is read its value decreases to zero.
-*/
-  this._contentLength = 0;
-
-  /** The current state of parsing the incoming request. */
-  this._state = READER_IN_REQUEST_LINE;
-
-  /** Metadata constructed from the incoming request for the request handler. */
-  this._metadata = new Request(connection.port);
-
-  /**
-* Used to preserve state if we run out of line data midway through a
-* multi-line header. _lastHeaderName stores the name of the header, while
-* _lastHeaderValue stores the value we've seen so far for the header.
-*
-* These fields are always either both undefined or both strings.
-*/
-  this._lastHeaderName = this._lastHeaderValue = undefined;
-}
-RequestReader.prototype =
-{
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Called when more data from the incoming request is available. This method
-* then reads the available data from input and deals with that data as
-* necessary, depending upon the syntax of already-downloaded data.
-*
-* @param input : nsIAsyncInputStream
-* the stream of incoming data from the connection
-*/
-  onInputStreamReady: function(input)
-  {
-    dumpn("*** onInputStreamReady(input=" + input + ") on thread " +
-          gThreadManager.currentThread + " (main is " +
-          gThreadManager.mainThread + ")");
-    dumpn("*** this._state == " + this._state);
-
-    // Handle cases where we get more data after a request error has been
-    // discovered but *before* we can close the connection.
-    var data = this._data;
-    if (!data)
-      return;
-
-    try
-    {
-      data.appendBytes(readBytes(input, input.available()));
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** WARNING: unexpected error when reading from socket; will " +
-              "be treated as if the input stream had been closed");
-        dumpn("*** WARNING: actual error was: " + e);
-      }
-
-      // We've lost a race -- input has been closed, but we're still expecting
-      // to read more data. available() will throw in this case, and since
-      // we're dead in the water now, destroy the connection.
-      dumpn("*** onInputStreamReady called on a closed input, destroying " +
-            "connection");
-      this._connection.close();
-      return;
-    }
-
-    switch (this._state)
-    {
-      default:
-        NS_ASSERT(false, "invalid state: " + this._state);
-        break;
-
-      case READER_IN_REQUEST_LINE:
-        if (!this._processRequestLine())
-          break;
-        /* fall through */
-
-      case READER_IN_HEADERS:
-        if (!this._processHeaders())
-          break;
-        /* fall through */
-
-      case READER_IN_BODY:
-        this._processBody();
-    }
-
-    if (this._state != READER_FINISHED)
-      input.asyncWait(this, 0, 0, gThreadManager.currentThread);
-  },
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(aIID)
-  {
-    if (aIID.equals(Ci.nsIInputStreamCallback) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE API
-
-  /**
-* Processes unprocessed, downloaded data as a request line.
-*
-* @returns boolean
-* true iff the request line has been fully processed
-*/
-  _processRequestLine: function()
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    // Servers SHOULD ignore any empty line(s) received where a Request-Line
-    // is expected (section 4.1).
-    var data = this._data;
-    var line = {};
-    var readSuccess;
-    while ((readSuccess = data.readLine(line)) && line.value == "")
-      dumpn("*** ignoring beginning blank line...");
-
-    // if we don't have a full line, wait until we do
-    if (!readSuccess)
-      return false;
-
-    // we have the first non-blank line
-    try
-    {
-      this._parseRequestLine(line.value);
-      this._state = READER_IN_HEADERS;
-      return true;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing request headers.
-*
-* @returns boolean
-* true iff header data in the request has been fully processed
-*/
-  _processHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    // XXX things to fix here:
-    //
-    // - need to support RFC 2047-encoded non-US-ASCII characters
-
-    try
-    {
-      var done = this._parseHeaders();
-      if (done)
-      {
-        var request = this._metadata;
-
-        // XXX this is wrong for requests with transfer-encodings applied to
-        // them, particularly chunked (which by its nature can have no
-        // meaningful Content-Length header)!
-        this._contentLength = request.hasHeader("Content-Length")
-                            ? parseInt(request.getHeader("Content-Length"), 10)
-                            : 0;
-        dumpn("_processHeaders, Content-length=" + this._contentLength);
-
-        this._state = READER_IN_BODY;
-      }
-      return done;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing the request body.
-*
-* @returns boolean
-* true iff the request body has been fully processed
-*/
-  _processBody: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    // XXX handle chunked transfer-coding request bodies!
-
-    try
-    {
-      if (this._contentLength > 0)
-      {
-        var data = this._data.purge();
-        var count = Math.min(data.length, this._contentLength);
-        dumpn("*** loading data=" + data + " len=" + data.length +
-              " excess=" + (data.length - count));
-
-        var bos = new BinaryOutputStream(this._metadata._bodyOutputStream);
-        bos.writeByteArray(data, count);
-        this._contentLength -= count;
-      }
-
-      dumpn("*** remaining body data len=" + this._contentLength);
-      if (this._contentLength == 0)
-      {
-        this._validateRequest();
-        this._state = READER_FINISHED;
-        this._handleResponse();
-        return true;
-      }
-
-      return false;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Does various post-header checks on the data in this request.
-*
-* @throws : HttpError
-* if the request was malformed in some way
-*/
-  _validateRequest: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    dumpn("*** _validateRequest");
-
-    var metadata = this._metadata;
-    var headers = metadata._headers;
-
-    // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header
-    var identity = this._connection.server.identity;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-    {
-      if (!headers.hasHeader("Host"))
-      {
-        dumpn("*** malformed HTTP/1.1 or greater request with no Host header!");
-        throw HTTP_400;
-      }
-
-      // If the Request-URI wasn't absolute, then we need to determine our host.
-      // We have to determine what scheme was used to access us based on the
-      // server identity data at this point, because the request just doesn't
-      // contain enough data on its own to do this, sadly.
-      if (!metadata._host)
-      {
-        var host, port;
-        var hostPort = headers.getHeader("Host");
-        var colon = hostPort.indexOf(":");
-        if (colon < 0)
-        {
-          host = hostPort;
-          port = "";
-        }
-        else
-        {
-          host = hostPort.substring(0, colon);
-          port = hostPort.substring(colon + 1);
-        }
-
-        // NB: We allow an empty port here because, oddly, a colon may be
-        // present even without a port number, e.g. "example.com:"; in this
-        // case the default port applies.
-        if (!HOST_REGEX.test(host) || !/^\d*$/.test(port))
-        {
-          dumpn("*** malformed hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        // If we're not given a port, we're stuck, because we don't know what
-        // scheme to use to look up the correct port here, in general. Since
-        // the HTTPS case requires a tunnel/proxy and thus requires that the
-        // requested URI be absolute (and thus contain the necessary
-        // information), let's assume HTTP will prevail and use that.
-        port = +port || 80;
-
-        var scheme = identity.getScheme(host, port);
-        if (!scheme)
-        {
-          dumpn("*** unrecognized hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        metadata._scheme = scheme;
-        metadata._host = host;
-        metadata._port = port;
-      }
-    }
-    else
-    {
-      NS_ASSERT(metadata._host === undefined,
-                "HTTP/1.0 doesn't allow absolute paths in the request line!");
-
-      metadata._scheme = identity.primaryScheme;
-      metadata._host = identity.primaryHost;
-      metadata._port = identity.primaryPort;
-    }
-
-    NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port),
-              "must have a location we recognize by now!");
-  },
-
-  /**
-* Handles responses in case of error, either in the server or in the request.
-*
-* @param e
-* the specific error encountered, which is an HttpError in the case where
-* the request is in some way invalid or cannot be fulfilled; if this isn't
-* an HttpError we're going to be paranoid and shut down, because that
-* shouldn't happen, ever
-*/
-  _handleError: function(e)
-  {
-    // Don't fall back into normal processing!
-    this._state = READER_FINISHED;
-
-    var server = this._connection.server;
-    if (e instanceof HttpError)
-    {
-      var code = e.code;
-    }
-    else
-    {
-      dumpn("!!! UNEXPECTED ERROR: " + e +
-            (e.lineNumber ? ", line " + e.lineNumber : ""));
-
-      // no idea what happened -- be paranoid and shut down
-      code = 500;
-      server._requestQuit();
-    }
-
-    // make attempted reuse of data an error
-    this._data = null;
-
-    this._connection.processError(code, this._metadata);
-  },
-
-  /**
-* Now that we've read the request line and headers, we can actually hand off
-* the request to be handled.
-*
-* This method is called once per request, after the request line and all
-* headers and the body, if any, have been received.
-*/
-  _handleResponse: function()
-  {
-    NS_ASSERT(this._state == READER_FINISHED);
-
-    // We don't need the line-based data any more, so make attempted reuse an
-    // error.
-    this._data = null;
-
-    this._connection.process(this._metadata);
-  },
-
-
-  // PARSING
-
-  /**
-* Parses the request line for the HTTP request associated with this.
-*
-* @param line : string
-* the request line
-*/
-  _parseRequestLine: function(line)
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    dumpn("*** _parseRequestLine('" + line + "')");
-
-    var metadata = this._metadata;
-
-    // clients and servers SHOULD accept any amount of SP or HT characters
-    // between fields, even though only a single SP is required (section 19.3)
-    var request = line.split(/[ \t]+/);
-    if (!request || request.length != 3)
-      throw HTTP_400;
-
-    metadata._method = request[0];
-
-    // get the HTTP version
-    var ver = request[2];
-    var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
-    if (!match)
-      throw HTTP_400;
-
-    // determine HTTP version
-    try
-    {
-      metadata._httpVersion = new nsHttpVersion(match[1]);
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
-        throw "unsupported HTTP version";
-    }
-    catch (e)
-    {
-      // we support HTTP/1.0 and HTTP/1.1 only
-      throw HTTP_501;
-    }
-
-
-    var fullPath = request[1];
-    var serverIdentity = this._connection.server.identity;
-
-    var scheme, host, port;
-
-    if (fullPath.charAt(0) != "/")
-    {
-      // No absolute paths in the request line in HTTP prior to 1.1
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-        throw HTTP_400;
-
-      try
-      {
-        var uri = Cc["@mozilla.org/network/io-service;1"]
-                    .getService(Ci.nsIIOService)
-                    .newURI(fullPath);
-        fullPath = uri.pathQueryRef;
-        scheme = uri.scheme;
-        host = metadata._host = uri.asciiHost;
-        port = uri.port;
-        if (port === -1)
-        {
-          if (scheme === "http")
-            port = 80;
-          else if (scheme === "https")
-            port = 443;
-          else
-            throw HTTP_400;
-        }
-      }
-      catch (e)
-      {
-        // If the host is not a valid host on the server, the response MUST be a
-        // 400 (Bad Request) error message (section 5.2). Alternately, the URI
-        // is malformed.
-        throw HTTP_400;
-      }
-
-      if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
-        throw HTTP_400;
-    }
-
-    var splitter = fullPath.indexOf("?");
-    if (splitter < 0)
-    {
-      // _queryString already set in ctor
-      metadata._path = fullPath;
-    }
-    else
-    {
-      metadata._path = fullPath.substring(0, splitter);
-      metadata._queryString = fullPath.substring(splitter + 1);
-    }
-
-    metadata._scheme = scheme;
-    metadata._host = host;
-    metadata._port = port;
-  },
-
-  /**
-* Parses all available HTTP headers in this until the header-ending CRLFCRLF,
-* adding them to the store of headers in the request.
-*
-* @throws
-* HTTP_400 if the headers are malformed
-* @returns boolean
-* true if all headers have now been processed, false otherwise
-*/
-  _parseHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    dumpn("*** _parseHeaders");
-
-    var data = this._data;
-
-    var headers = this._metadata._headers;
-    var lastName = this._lastHeaderName;
-    var lastVal = this._lastHeaderValue;
-
-    var line = {};
-    while (true)
-    {
-      NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
-                lastName === undefined ?
-                  "lastVal without lastName? lastVal: '" + lastVal + "'" :
-                  "lastName without lastVal? lastName: '" + lastName + "'");
-
-      if (!data.readLine(line))
-      {
-        // save any data we have from the header we might still be processing
-        this._lastHeaderName = lastName;
-        this._lastHeaderValue = lastVal;
-        return false;
-      }
-
-      var lineText = line.value;
-      var firstChar = lineText.charAt(0);
-
-      // blank line means end of headers
-      if (lineText == "")
-      {
-        // we're finished with the previous header
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-        else
-        {
-          // no headers in request -- valid for HTTP/1.0 requests
-        }
-
-        // either way, we're done processing headers
-        this._state = READER_IN_BODY;
-        return true;
-      }
-      else if (firstChar == " " || firstChar == "\t")
-      {
-        // multi-line header if we've already seen a header line
-        if (!lastName)
-        {
-          // we don't have a header to continue!
-          throw HTTP_400;
-        }
-
-        // append this line's text to the value; starts with SP/HT, so no need
-        // for separating whitespace
-        lastVal += lineText;
-      }
-      else
-      {
-        // we have a new header, so set the old one (if one existed)
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-
-        var colon = lineText.indexOf(":"); // first colon must be splitter
-        if (colon < 1)
-        {
-          // no colon or missing header field-name
-          throw HTTP_400;
-        }
-
-        // set header name, value (to be set in the next loop, usually)
-        lastName = lineText.substring(0, colon);
-        lastVal = lineText.substring(colon + 1);
-      } // empty, continuation, start of header
-    } // while (true)
-  }
-};
-
-
-/** The character codes for CR and LF. */
-const CR = 0x0D, LF = 0x0A;
-
-/**
-* Calculates the number of characters before the first CRLF pair in array, or
-* -1 if the array contains no CRLF pair.
-*
-* @param array : Array
-* an array of numbers in the range [0, 256), each representing a single
-* character; the first CRLF is the lowest index i where
-* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|,
-* if such an |i| exists, and -1 otherwise
-* @returns int
-* the index of the first CRLF if any were present, -1 otherwise
-*/
-function findCRLF(array)
-{
-  for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1))
-  {
-    if (array[i + 1] == LF)
-      return i;
-  }
-  return -1;
-}
-
-
-/**
-* A container which provides line-by-line access to the arrays of bytes with
-* which it is seeded.
-*/
-function LineData()
-{
-  /** An array of queued bytes from which to get line-based characters. */
-  this._data = [];
-}
-LineData.prototype =
-{
-  /**
-* Appends the bytes in the given array to the internal data cache maintained
-* by this.
-*/
-  appendBytes: function(bytes)
-  {
-    Array.prototype.push.apply(this._data, bytes);
-  },
-
-  /**
-* Removes and returns a line of data, delimited by CRLF, from this.
-*
-* @param out
-* an object whose "value" property will be set to the first line of text
-* present in this, sans CRLF, if this contains a full CRLF-delimited line
-* of text; if this doesn't contain enough data, the value of the property
-* is undefined
-* @returns boolean
-* true if a full line of data could be read from the data in this, false
-* otherwise
-*/
-  readLine: function(out)
-  {
-    var data = this._data;
-    var length = findCRLF(data);
-    if (length < 0)
-      return false;
-
-    //
-    // We have the index of the CR, so remove all the characters, including
-    // CRLF, from the array with splice, and convert the removed array into the
-    // corresponding string, from which we then strip the trailing CRLF.
-    //
-    // Getting the line in this matter acknowledges that substring is an O(1)
-    // operation in SpiderMonkey because strings are immutable, whereas two
-    // splices, both from the beginning of the data, are less likely to be as
-    // cheap as a single splice plus two extra character conversions.
-    //
-    var line = String.fromCharCode.apply(null, data.splice(0, length + 2));
-    out.value = line.substring(0, length);
-
-    return true;
-  },
-
-  /**
-* Removes the bytes currently within this and returns them in an array.
-*
-* @returns Array
-* the bytes within this when this method is called
-*/
-  purge: function()
-  {
-    var data = this._data;
-    this._data = [];
-    return data;
-  }
-};
-
-
-
-/**
-* Creates a request-handling function for an nsIHttpRequestHandler object.
-*/
-function createHandlerFunc(handler)
-{
-  return function(metadata, response) { handler.handle(metadata, response); };
-}
-
-
-/**
-* The default handler for directories; writes an HTML response containing a
-* slightly-formatted directory listing.
-*/
-function defaultIndexHandler(metadata, response)
-{
-  response.setHeader("Content-Type", "text/html", false);
-
-  var path = htmlEscape(decodeURI(metadata.path));
-
-  //
-  // Just do a very basic bit of directory listings -- no need for too much
-  // fanciness, especially since we don't have a style sheet in which we can
-  // stick rules (don't want to pollute the default path-space).
-  //
-
-  var body = '<html>\
-<head>\
-<title>' + path + '</title>\
-</head>\
-<body>\
-<h1>' + path + '</h1>\
-<ol style="list-style-type: none">';
-
-  var directory = metadata.getProperty("directory").QueryInterface(Ci.nsIFile);
-  NS_ASSERT(directory && directory.isDirectory());
-
-  var fileList = [];
-  var files = directory.directoryEntries;
-  while (files.hasMoreElements())
-  {
-    var f = files.getNext().QueryInterface(Ci.nsIFile);
-    var name = f.leafName;
-    if (!f.isHidden() &&
-        (name.charAt(name.length - 1) != HIDDEN_CHAR ||
-         name.charAt(name.length - 2) == HIDDEN_CHAR))
-      fileList.push(f);
-  }
-
-  fileList.sort(fileSort);
-
-  for (var i = 0; i < fileList.length; i++)
-  {
-    var file = fileList[i];
-    try
-    {
-      var name = file.leafName;
-      if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-        name = name.substring(0, name.length - 1);
-      var sep = file.isDirectory() ? "/" : "";
-
-      // Note: using " to delimit the attribute here because encodeURIComponent
-      // passes through '.
-      var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' +
-                   htmlEscape(name) + sep +
-                 '</a></li>';
-
-      body += item;
-    }
-    catch (e) { /* some file system error, ignore the file */ }
-  }
-
-  body += ' </ol>\
-</body>\
-</html>';
-
-  response.bodyOutputStream.write(body, body.length);
-}
-
-/**
-* Sorts a and b (nsIFile objects) into an aesthetically pleasing order.
-*/
-function fileSort(a, b)
-{
-  var dira = a.isDirectory(), dirb = b.isDirectory();
-
-  if (dira && !dirb)
-    return -1;
-  if (dirb && !dira)
-    return 1;
-
-  var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase();
-  return nameb > namea ? -1 : 1;
-}
-
-
-/**
-* Converts an externally-provided path into an internal path for use in
-* determining file mappings.
-*
-* @param path
-* the path to convert
-* @param encoded
-* true if the given path should be passed through decodeURI prior to
-* conversion
-* @throws URIError
-* if path is incorrectly encoded
-*/
-function toInternalPath(path, encoded)
-{
-  if (encoded)
-    path = decodeURI(path);
-
-  var comps = path.split("/");
-  for (var i = 0, sz = comps.length; i < sz; i++)
-  {
-    var comp = comps[i];
-    if (comp.charAt(comp.length - 1) == HIDDEN_CHAR)
-      comps[i] = comp + HIDDEN_CHAR;
-  }
-  return comps.join("/");
-}
-
-
-/**
-* Adds custom-specified headers for the given file to the given response, if
-* any such headers are specified.
-*
-* @param file
-* the file on the disk which is to be written
-* @param metadata
-* metadata about the incoming request
-* @param response
-* the Response to which any specified headers/data should be written
-* @throws HTTP_500
-* if an error occurred while processing custom-specified headers
-*/
-function maybeAddHeaders(file, metadata, response)
-{
-  var name = file.leafName;
-  if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-    name = name.substring(0, name.length - 1);
-
-  var headerFile = file.parent;
-  headerFile.append(name + HEADERS_SUFFIX);
-
-  if (!headerFile.exists())
-    return;
-
-  const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(headerFile, PR_RDONLY, 0o444,
-                                Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-  try
-  {
-    var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0);
-    lis.QueryInterface(Ci.nsIUnicharLineInputStream);
-
-    var line = {value: ""};
-    var more = lis.readLine(line);
-
-    if (!more && line.value == "")
-      return;
-
-
-    // request line
-
-    var status = line.value;
-    if (status.indexOf("HTTP ") == 0)
-    {
-      status = status.substring(5);
-      var space = status.indexOf(" ");
-      var code, description;
-      if (space < 0)
-      {
-        code = status;
-        description = "";
-      }
-      else
-      {
-        code = status.substring(0, space);
-        description = status.substring(space + 1, status.length);
-      }
-
-      response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description);
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-
-    // headers
-    while (more || line.value != "")
-    {
-      var header = line.value;
-      var colon = header.indexOf(":");
-
-      response.setHeader(header.substring(0, colon),
-                         header.substring(colon + 1, header.length),
-                         false); // allow overriding server-set headers
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-  }
-  catch (e)
-  {
-    dumpn("WARNING: error in headers for " + metadata.path + ": " + e);
-    throw HTTP_500;
-  }
-  finally
-  {
-    fis.close();
-  }
-}
-
-
-/**
-* An object which handles requests for a server, executing default and
-* overridden behaviors as instructed by the code which uses and manipulates it.
-* Default behavior includes the paths / and /trace (diagnostics), with some
-* support for HTTP error pages for various codes and fallback to HTTP 500 if
-* those codes fail for any reason.
-*
-* @param server : nsHttpServer
-* the server in which this handler is being used
-*/
-function ServerHandler(server)
-{
-  // FIELDS
-
-  /**
-* The nsHttpServer instance associated with this handler.
-*/
-  this._server = server;
-
-  /**
-* A FileMap object containing the set of path->nsIFile mappings for
-* all directory mappings set in the server (e.g., "/" for /var/www/html/,
-* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2).
-*
-* Note carefully: the leading and trailing "/" in each path (not file) are
-* removed before insertion to simplify the code which uses this. You have
-* been warned!
-*/
-  this._pathDirectoryMap = new FileMap();
-
-  /**
-* Custom request handlers for the server in which this resides. Path-handler
-* pairs are stored as property-value pairs in this property.
-*
-* @see ServerHandler.prototype._defaultPaths
-*/
-  this._overridePaths = {};
-
-  /**
-* Custom request handlers for the server in which this resides. Prefix-handler
-* pairs are stored as property-value pairs in this property.
-*/
-  this._overridePrefixes = {};
-
-  /**
-* Custom request handlers for the error handlers in the server in which this
-* resides. Path-handler pairs are stored as property-value pairs in this
-* property.
-*
-* @see ServerHandler.prototype._defaultErrors
-*/
-  this._overrideErrors = {};
-
-  /**
-* Maps file extensions to their MIME types in the server, overriding any
-* mapping that might or might not exist in the MIME service.
-*/
-  this._mimeMappings = {};
-
-  /**
-* The default handler for requests for directories, used to serve directories
-* when no index file is present.
-*/
-  this._indexHandler = defaultIndexHandler;
-
-  /** Per-path state storage for the server. */
-  this._state = {};
-
-  /** Entire-server state storage. */
-  this._sharedState = {};
-
-  /** Entire-server state storage for nsISupports values. */
-  this._objectState = {};
-}
-ServerHandler.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Handles a request to this server, responding to the request appropriately
-* and initiating server shutdown if necessary.
-*
-* This method never throws an exception.
-*
-* @param connection : Connection
-* the connection for this request
-*/
-  handleResponse: function(connection)
-  {
-    var request = connection.request;
-    var response = new Response(connection);
-
-    var path = request.path;
-    dumpn("*** path == " + path);
-
-    try
-    {
-      try
-      {
-        if (path in this._overridePaths)
-        {
-          // explicit paths first, then files based on existing directory mappings,
-          // then (if the file doesn't exist) built-in server default paths
-          dumpn("calling override for " + path);
-          this._overridePaths[path](request, response);
-        }
-        else
-        {
-          let longestPrefix = "";
-          for (let prefix in this._overridePrefixes)
-          {
-            if (prefix.length > longestPrefix.length && path.startsWith(prefix))
-            {
-              longestPrefix = prefix;
-            }
-          }
-          if (longestPrefix.length > 0)
-          {
-            dumpn("calling prefix override for " + longestPrefix);
-            this._overridePrefixes[longestPrefix](request, response);
-          }
-          else
-          {
-            this._handleDefault(request, response);
-          }
-        }
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        if (!(e instanceof HttpError))
-        {
-          dumpn("*** unexpected error: e == " + e);
-          throw HTTP_500;
-        }
-        if (e.code !== 404)
-          throw e;
-
-        dumpn("*** default: " + (path in this._defaultPaths));
-
-        response = new Response(connection);
-        if (path in this._defaultPaths)
-          this._defaultPaths[path](request, response);
-        else
-          throw HTTP_404;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort(e);
-        return;
-      }
-
-      var errorCode = "internal";
-
-      try
-      {
-        if (!(e instanceof HttpError))
-          throw e;
-
-        errorCode = e.code;
-        dumpn("*** errorCode == " + errorCode);
-
-        response = new Response(connection);
-        if (e.customErrorHandling)
-          e.customErrorHandling(response);
-        this._handleError(errorCode, request, response);
-        return;
-      }
-      catch (e2)
-      {
-        dumpn("*** error handling " + errorCode + " error: " +
-              "e2 == " + e2 + ", shutting down server");
-
-        connection.server._requestQuit();
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (!file)
-    {
-      dumpn("*** unregistering '" + path + "' mapping");
-      delete this._overridePaths[path];
-      return;
-    }
-
-    dumpn("*** registering '" + path + "' as mapping to " + file.path);
-    file = file.clone();
-
-    var self = this;
-    this._overridePaths[path] =
-      function(request, response)
-      {
-        if (!file.exists())
-          throw HTTP_404;
-
-        response.setStatusLine(request.httpVersion, 200, "OK");
-        self._writeFileResponse(request, file, response, 0, file.fileSize);
-      };
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePaths, path);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    // XXX true prefix validation!
-    if (!(prefix.startsWith("/") && prefix.endsWith("/")))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePrefixes, prefix);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // strip off leading and trailing '/' so that we can use lastIndexOf when
-    // determining exactly how a path maps onto a mapped directory --
-    // conditional is required here to deal with "/".substring(1, 0) being
-    // converted to "/".substring(0, 1) per the JS specification
-    var key = path.length == 1 ? "" : path.substring(1, path.length - 1);
-
-    // the path-to-directory mapping code requires that the first character not
-    // be "/", or it will go into an infinite loop
-    if (key.charAt(0) == "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    key = toInternalPath(key, false);
-
-    if (directory)
-    {
-      dumpn("*** mapping '" + path + "' to the location " + directory.path);
-      this._pathDirectoryMap.put(key, directory);
-    }
-    else
-    {
-      dumpn("*** removing mapping for '" + path + "'");
-      this._pathDirectoryMap.put(key, null);
-    }
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(err, handler)
-  {
-    if (!(err in HTTP_ERROR_CODES))
-      dumpn("*** WARNING: registering non-HTTP/1.1 error code " +
-            "(" + err + ") handler -- was this intentional?");
-
-    this._handlerToField(handler, this._overrideErrors, err);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    if (!handler)
-      handler = defaultIndexHandler;
-    else if (typeof(handler) != "function")
-      handler = createHandlerFunc(handler);
-
-    this._indexHandler = handler;
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    if (!type)
-      delete this._mimeMappings[ext];
-    else
-      this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type);
-  },
-
-  // PRIVATE API
-
-  /**
-* Sets or remove (if handler is null) a handler in an object with a key.
-*
-* @param handler
-* a handler, either function or an nsIHttpRequestHandler
-* @param dict
-* The object to attach the handler to.
-* @param key
-* The field name of the handler.
-*/
-  _handlerToField: function(handler, dict, key)
-  {
-    // for convenience, handler can be a function if this is run from xpcshell
-    if (typeof(handler) == "function")
-      dict[key] = handler;
-    else if (handler)
-      dict[key] = createHandlerFunc(handler);
-    else
-      delete dict[key];
-  },
-
-  /**
-* Handles a request which maps to a file in the local filesystem (if a base
-* path has already been set; otherwise the 404 error is thrown).
-*
-* @param metadata : Request
-* metadata for the incoming request
-* @param response : Response
-* an uninitialized Response to the given request, to be initialized by a
-* request handler
-* @throws HTTP_###
-* if an HTTP error occurred (usually HTTP_404); note that in this case the
-* calling code must handle post-processing of the response
-*/
-  _handleDefault: function(metadata, response)
-  {
-    dumpn("*** _handleDefault()");
-
-    response.setStatusLine(metadata.httpVersion, 200, "OK");
-
-    var path = metadata.path;
-    NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">");
-
-    // determine the actual on-disk file; this requires finding the deepest
-    // path-to-directory mapping in the requested URL
-    var file = this._getFileForPath(path);
-
-    // the "file" might be a directory, in which case we either serve the
-    // contained index.html or make the index handler write the response
-    if (file.exists() && file.isDirectory())
-    {
-      file.append("index.html"); // make configurable?
-      if (!file.exists() || file.isDirectory())
-      {
-        metadata._ensurePropertyBag();
-        metadata._bag.setPropertyAsInterface("directory", file.parent);
-        this._indexHandler(metadata, response);
-        return;
-      }
-    }
-
-    // alternately, the file might not exist
-    if (!file.exists())
-      throw HTTP_404;
-
-    var start, end;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
-        metadata.hasHeader("Range") &&
-        this._getTypeFromFile(file) !== SJS_TYPE)
-    {
-      var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
-      if (!rangeMatch)
-        throw HTTP_400;
-
-      if (rangeMatch[1] !== undefined)
-        start = parseInt(rangeMatch[1], 10);
-
-      if (rangeMatch[2] !== undefined)
-        end = parseInt(rangeMatch[2], 10);
-
-      if (start === undefined && end === undefined)
-        throw HTTP_400;
-
-      // No start given, so the end is really the count of bytes from the
-      // end of the file.
-      if (start === undefined)
-      {
-        start = Math.max(0, file.fileSize - end);
-        end = file.fileSize - 1;
-      }
-
-      // start and end are inclusive
-      if (end === undefined || end >= file.fileSize)
-        end = file.fileSize - 1;
-
-      if (start !== undefined && start >= file.fileSize) {
-        var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
-        HTTP_416.customErrorHandling = function(errorResponse)
-        {
-          maybeAddHeaders(file, metadata, errorResponse);
-        };
-        throw HTTP_416;
-      }
-
-      if (end < start)
-      {
-        response.setStatusLine(metadata.httpVersion, 200, "OK");
-        start = 0;
-        end = file.fileSize - 1;
-      }
-      else
-      {
-        response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
-        var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize;
-        response.setHeader("Content-Range", contentRange);
-      }
-    }
-    else
-    {
-      start = 0;
-      end = file.fileSize - 1;
-    }
-
-    // finally...
-    dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " +
-          start + " to " + end + " inclusive");
-    this._writeFileResponse(metadata, file, response, start, end - start + 1);
-  },
-
-  /**
-* Writes an HTTP response for the given file, including setting headers for
-* file metadata.
-*
-* @param metadata : Request
-* the Request for which a response is being generated
-* @param file : nsIFile
-* the file which is to be sent in the response
-* @param response : Response
-* the response to which the file should be written
-* @param offset: uint
-* the byte offset to skip to when writing
-* @param count: uint
-* the number of bytes to write
-*/
-  _writeFileResponse: function(metadata, file, response, offset, count)
-  {
-    const PR_RDONLY = 0x01;
-
-    var type = this._getTypeFromFile(file);
-    if (type === SJS_TYPE)
-    {
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      try
-      {
-        var sis = new ScriptableInputStream(fis);
-        var s = Cu.Sandbox(gGlobalObject);
-        s.importFunction(dump, "dump");
-
-        // Define a basic key-value state-preservation API across requests, with
-        // keys initially corresponding to the empty string.
-        var self = this;
-        var path = metadata.path;
-        s.importFunction(function getState(k)
-        {
-          return self._getState(path, k);
-        });
-        s.importFunction(function setState(k, v)
-        {
-          self._setState(path, k, v);
-        });
-        s.importFunction(function getSharedState(k)
-        {
-          return self._getSharedState(k);
-        });
-        s.importFunction(function setSharedState(k, v)
-        {
-          self._setSharedState(k, v);
-        });
-        s.importFunction(function getObjectState(k, callback)
-        {
-          callback(self._getObjectState(k));
-        });
-        s.importFunction(function setObjectState(k, v)
-        {
-          self._setObjectState(k, v);
-        });
-        s.importFunction(function registerPathHandler(p, h)
-        {
-          self.registerPathHandler(p, h);
-        });
-
-        // Make it possible for sjs files to access their location
-        this._setState(path, "__LOCATION__", file.path);
-
-        try
-        {
-          // Alas, the line number in errors dumped to console when calling the
-          // request handler is simply an offset from where we load the SJS file.
-          // Work around this in a reasonably non-fragile way by dynamically
-          // getting the line number where we evaluate the SJS file. Don't
-          // separate these two lines!
-          var line = new Error().lineNumber;
-          Cu.evalInSandbox(sis.read(file.fileSize), s);
-        }
-        catch (e)
-        {
-          dumpn("*** syntax error in SJS at " + file.path + ": " + e);
-          throw HTTP_500;
-        }
-
-        try
-        {
-          s.handleRequest(metadata, response);
-        }
-        catch (e)
-        {
-          dump("*** error running SJS at " + file.path + ": " +
-               e + " on line " +
-               (e instanceof Error
-               ? e.lineNumber + " in httpd.js"
-               : (e.lineNumber - line)) + "\n");
-          throw HTTP_500;
-        }
-      }
-      finally
-      {
-        fis.close();
-      }
-    }
-    else
-    {
-      try
-      {
-        response.setHeader("Last-Modified",
-                           toDateString(file.lastModifiedTime),
-                           false);
-      }
-      catch (e) { /* lastModifiedTime threw, ignore */ }
-
-      response.setHeader("Content-Type", type, false);
-      maybeAddHeaders(file, metadata, response);
-      response.setHeader("Content-Length", "" + count, false);
-
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      offset = offset || 0;
-      count = count || file.fileSize;
-      NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset");
-      NS_ASSERT(count >= 0, "bad count");
-      NS_ASSERT(offset + count <= file.fileSize, "bad total data size");
-
-      try
-      {
-        if (offset !== 0)
-        {
-          // Seek (or read, if seeking isn't supported) to the correct offset so
-          // the data sent to the client matches the requested range.
-          if (fis instanceof Ci.nsISeekableStream)
-            fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset);
-          else
-            new ScriptableInputStream(fis).read(offset);
-        }
-      }
-      catch (e)
-      {
-        fis.close();
-        throw e;
-      }
-
-      let writeMore = function writeMore()
-      {
-        gThreadManager.dispatchToMainThread(writeData);
-      }
-
-      var input = new BinaryInputStream(fis);
-      var output = new BinaryOutputStream(response.bodyOutputStream);
-      var writeData =
-        {
-          run: function()
-          {
-            var chunkSize = Math.min(65536, count);
-            count -= chunkSize;
-            NS_ASSERT(count >= 0, "underflow");
-
-            try
-            {
-              var data = input.readByteArray(chunkSize);
-              NS_ASSERT(data.length === chunkSize,
-                        "incorrect data returned? got " + data.length +
-                        ", expected " + chunkSize);
-              output.writeByteArray(data, data.length);
-              if (count === 0)
-              {
-                fis.close();
-                response.finish();
-              }
-              else
-              {
-                writeMore();
-              }
-            }
-            catch (e)
-            {
-              try
-              {
-                fis.close();
-              }
-              finally
-              {
-                response.finish();
-              }
-              throw e;
-            }
-          }
-        };
-
-      writeMore();
-
-      // Now that we know copying will start, flag the response as async.
-      response.processAsync();
-    }
-  },
-
-  /**
-* Get the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getState: function(path, k)
-  {
-    var state = this._state;
-    if (path in state && k in state[path])
-      return state[path][k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setState: function(path, k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    var state = this._state;
-    if (!(path in state))
-      state[path] = {};
-    state[path][k] = v;
-  },
-
-  /**
-* Get the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getSharedState: function(k)
-  {
-    var state = this._sharedState;
-    if (k in state)
-      return state[k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setSharedState: function(k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    this._sharedState[k] = v;
-  },
-
-  /**
-* Returns the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be returned
-* @returns nsISupports
-* the corresponding object, or null if none was present
-*/
-  _getObjectState: function(k)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    return this._objectState[k] || null;
-  },
-
-  /**
-* Sets the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be set
-* @param v : nsISupports
-* the object to be associated with the given key; may be null
-*/
-  _setObjectState: function(k, v)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    if (typeof v !== "object")
-      throw new Error("non-object value passed");
-    if (v && !("QueryInterface" in v))
-    {
-      throw new Error("must pass an nsISupports; use wrappedJSObject to ease " +
-                      "pain when using the server from JS");
-    }
-
-    this._objectState[k] = v;
-  },
-
-  /**
-* Gets a content-type for the given file, first by checking for any custom
-* MIME-types registered with this handler for the file's extension, second by
-* asking the global MIME service for a content-type, and finally by failing
-* over to application/octet-stream.
-*
-* @param file : nsIFile
-* the nsIFile for which to get a file type
-* @returns string
-* the best content-type which can be determined for the file
-*/
-  _getTypeFromFile: function(file)
-  {
-    try
-    {
-      var name = file.leafName;
-      var dot = name.lastIndexOf(".");
-      if (dot > 0)
-      {
-        var ext = name.slice(dot + 1);
-        if (ext in this._mimeMappings)
-          return this._mimeMappings[ext];
-      }
-      return Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
-               .getService(Ci.nsIMIMEService)
-               .getTypeFromFile(file);
-    }
-    catch (e)
-    {
-      return "application/octet-stream";
-    }
-  },
-
-  /**
-* Returns the nsIFile which corresponds to the path, as determined using
-* all registered path->directory mappings and any paths which are explicitly
-* overridden.
-*
-* @param path : string
-* the server path for which a file should be retrieved, e.g. "/foo/bar"
-* @throws HttpError
-* when the correct action is the corresponding HTTP error (i.e., because no
-* mapping was found for a directory in path, the referenced file doesn't
-* exist, etc.)
-* @returns nsIFile
-* the file to be sent as the response to a request for the path
-*/
-  _getFileForPath: function(path)
-  {
-    // decode and add underscores as necessary
-    try
-    {
-      path = toInternalPath(path, true);
-    }
-    catch (e)
-    {
-      throw HTTP_400; // malformed path
-    }
-
-    // next, get the directory which contains this path
-    var pathMap = this._pathDirectoryMap;
-
-    // An example progression of tmp for a path "/foo/bar/baz/" might be:
-    // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
-    var tmp = path.substring(1);
-    while (true)
-    {
-      // do we have a match for current head of the path?
-      var file = pathMap.get(tmp);
-      if (file)
-      {
-        // XXX hack; basically disable showing mapping for /foo/bar/ when the
-        // requested path was /foo/bar, because relative links on the page
-        // will all be incorrect -- we really need the ability to easily
-        // redirect here instead
-        if (tmp == path.substring(1) &&
-            tmp.length != 0 &&
-            tmp.charAt(tmp.length - 1) != "/")
-          file = null;
-        else
-          break;
-      }
-
-      // if we've finished trying all prefixes, exit
-      if (tmp == "")
-        break;
-
-      tmp = tmp.substring(0, tmp.lastIndexOf("/"));
-    }
-
-    // no mapping applies, so 404
-    if (!file)
-      throw HTTP_404;
-
-
-    // last, get the file for the path within the determined directory
-    var parentFolder = file.parent;
-    var dirIsRoot = (parentFolder == null);
-
-    // Strategy here is to append components individually, making sure we
-    // never move above the given directory; this allows paths such as
-    // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling";
-    // this component-wise approach also means the code works even on platforms
-    // which don't use "/" as the directory separator, such as Windows
-    var leafPath = path.substring(tmp.length + 1);
-    var comps = leafPath.split("/");
-    for (var i = 0, sz = comps.length; i < sz; i++)
-    {
-      var comp = comps[i];
-
-      if (comp == "..")
-        file = file.parent;
-      else if (comp == "." || comp == "")
-        continue;
-      else
-        file.append(comp);
-
-      if (!dirIsRoot && file.equals(parentFolder))
-        throw HTTP_403;
-    }
-
-    return file;
-  },
-
-  /**
-* Writes the error page for the given HTTP error code over the given
-* connection.
-*
-* @param errorCode : uint
-* the HTTP error code to be used
-* @param connection : Connection
-* the connection on which the error occurred
-*/
-  handleError: function(errorCode, connection)
-  {
-    var response = new Response(connection);
-
-    dumpn("*** error in request: " + errorCode);
-
-    this._handleError(errorCode, new Request(connection.port), response);
-  },
-
-  /**
-* Handles a request which generates the given error code, using the
-* user-defined error handler if one has been set, gracefully falling back to
-* the x00 status code if the code has no handler, and failing to status code
-* 500 if all else fails.
-*
-* @param errorCode : uint
-* the HTTP error which is to be returned
-* @param metadata : Request
-* metadata for the request, which will often be incomplete since this is an
-* error
-* @param response : Response
-* an uninitialized Response should be initialized when this method
-* completes with information which represents the desired error code in the
-* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a
-* fallback for 505, per HTTP specs)
-*/
-  _handleError: function(errorCode, metadata, response)
-  {
-    if (!metadata)
-      throw Cr.NS_ERROR_NULL_POINTER;
-
-    var errorX00 = errorCode - (errorCode % 100);
-
-    try
-    {
-      if (!(errorCode in HTTP_ERROR_CODES))
-        dumpn("*** WARNING: requested invalid error: " + errorCode);
-
-      // RFC 2616 says that we should try to handle an error by its class if we
-      // can't otherwise handle it -- if that fails, we revert to handling it as
-      // a 500 internal server error, and if that fails we throw and shut down
-      // the server
-
-      // actually handle the error
-      try
-      {
-        if (errorCode in this._overrideErrors)
-          this._overrideErrors[errorCode](metadata, response);
-        else
-          this._defaultErrors[errorCode](metadata, response);
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        // don't retry the handler that threw
-        if (errorX00 == errorCode)
-          throw HTTP_500;
-
-        dumpn("*** error in handling for error code " + errorCode + ", " +
-              "falling back to " + errorX00 + "...");
-        response = new Response(response._connection);
-        if (errorX00 in this._overrideErrors)
-          this._overrideErrors[errorX00](metadata, response);
-        else if (errorX00 in this._defaultErrors)
-          this._defaultErrors[errorX00](metadata, response);
-        else
-          throw HTTP_500;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort();
-        return;
-      }
-
-      // we've tried everything possible for a meaningful error -- now try 500
-      dumpn("*** error in handling for error code " + errorX00 + ", falling " +
-            "back to 500...");
-
-      try
-      {
-        response = new Response(response._connection);
-        if (500 in this._overrideErrors)
-          this._overrideErrors[500](metadata, response);
-        else
-          this._defaultErrors[500](metadata, response);
-      }
-      catch (e2)
-      {
-        dumpn("*** multiple errors in default error handlers!");
-        dumpn("*** e == " + e + ", e2 == " + e2);
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  // FIELDS
-
-  /**
-* This object contains the default handlers for the various HTTP error codes.
-*/
-  _defaultErrors:
-  {
-    400: function(metadata, response)
-    {
-      // none of the data in metadata is reliable, so hard-code everything here
-      response.setStatusLine("1.1", 400, "Bad Request");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Bad request\n";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    403: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 403, "Forbidden");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>403 Forbidden</title></head>\
-<body>\
-<h1>403 Forbidden</h1>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    404: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 404, "Not Found");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>404 Not Found</title></head>\
-<body>\
-<h1>404 Not Found</h1>\
-<p>\
-<span style='font-family: monospace;'>" +
-                          htmlEscape(metadata.path) +
-                       "</span> was not found.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    416: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                            416,
-                            "Requested Range Not Satisfiable");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head>\
-<title>416 Requested Range Not Satisfiable</title></head>\
-<body>\
-<h1>416 Requested Range Not Satisfiable</h1>\
-<p>The byte range was not valid for the\
-requested resource.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    500: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                             500,
-                             "Internal Server Error");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>500 Internal Server Error</title></head>\
-<body>\
-<h1>500 Internal Server Error</h1>\
-<p>Something's broken in this server and\
-needs to be fixed.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    501: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 501, "Not Implemented");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>501 Not Implemented</title></head>\
-<body>\
-<h1>501 Not Implemented</h1>\
-<p>This server is not (yet) Apache.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    505: function(metadata, response)
-    {
-      response.setStatusLine("1.1", 505, "HTTP Version Not Supported");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>505 HTTP Version Not Supported</title></head>\
-<body>\
-<h1>505 HTTP Version Not Supported</h1>\
-<p>This server only supports HTTP/1.0 and HTTP/1.1\
-connections.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    }
-  },
-
-  /**
-* Contains handlers for the default set of URIs contained in this server.
-*/
-  _defaultPaths:
-  {
-    "/": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>httpd.js</title></head>\
-<body>\
-<h1>httpd.js</h1>\
-<p>If you're seeing this page, httpd.js is up and\
-serving requests! Now set a base path and serve some\
-files!</p>\
-</body>\
-</html>";
-
-      response.bodyOutputStream.write(body, body.length);
-    },
-
-    "/trace": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Request-URI: " +
-                 metadata.scheme + "://" + metadata.host + ":" + metadata.port +
-                 metadata.path + "\n\n";
-      body += "Request (semantically equivalent, slightly reformatted):\n\n";
-      body += metadata.method + " " + metadata.path;
-
-      if (metadata.queryString)
-        body += "?" + metadata.queryString;
-
-      body += " HTTP/" + metadata.httpVersion + "\r\n";
-
-      var headEnum = metadata.headers;
-      while (headEnum.hasMoreElements())
-      {
-        var fieldName = headEnum.getNext()
-                                .QueryInterface(Ci.nsISupportsString)
-                                .data;
-        body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n";
-      }
-
-      response.bodyOutputStream.write(body, body.length);
-    }
-  }
-};
-
-
-/**
-* Maps absolute paths to files on the local file system (as nsILocalFiles).
-*/
-function FileMap()
-{
-  /** Hash which will map paths to nsILocalFiles. */
-  this._map = {};
-}
-FileMap.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Maps key to a clone of the nsIFile value if value is non-null;
-* otherwise, removes any extant mapping for key.
-*
-* @param key : string
-* string to which a clone of value is mapped
-* @param value : nsIFile
-* the file to map to key, or null to remove a mapping
-*/
-  put: function(key, value)
-  {
-    if (value)
-      this._map[key] = value.clone();
-    else
-      delete this._map[key];
-  },
-
-  /**
-* Returns a clone of the nsIFile mapped to key, or null if no such
-* mapping exists.
-*
-* @param key : string
-* key to which the returned file maps
-* @returns nsIFile
-* a clone of the mapped file, or null if no mapping exists
-*/
-  get: function(key)
-  {
-    var val = this._map[key];
-    return val ? val.clone() : null;
-  }
-};
-
-
-// Response CONSTANTS
-
-// token = *<any CHAR except CTLs or separators>
-// CHAR = <any US-ASCII character (0-127)>
-// CTL = <any US-ASCII control character (0-31) and DEL (127)>
-// separators = "(" | ")" | "<" | ">" | "@"
-// | "," | ";" | ":" | "\" | <">
-// | "/" | "[" | "]" | "?" | "="
-// | "{" | "}" | SP | HT
-const IS_TOKEN_ARRAY =
-  [0, 0, 0, 0, 0, 0, 0, 0, // 0
-   0, 0, 0, 0, 0, 0, 0, 0, // 8
-   0, 0, 0, 0, 0, 0, 0, 0, // 16
-   0, 0, 0, 0, 0, 0, 0, 0, // 24
-
-   0, 1, 0, 1, 1, 1, 1, 1, // 32
-   0, 0, 1, 1, 0, 1, 1, 0, // 40
-   1, 1, 1, 1, 1, 1, 1, 1, // 48
-   1, 1, 0, 0, 0, 0, 0, 0, // 56
-
-   0, 1, 1, 1, 1, 1, 1, 1, // 64
-   1, 1, 1, 1, 1, 1, 1, 1, // 72
-   1, 1, 1, 1, 1, 1, 1, 1, // 80
-   1, 1, 1, 0, 0, 0, 1, 1, // 88
-
-   1, 1, 1, 1, 1, 1, 1, 1, // 96
-   1, 1, 1, 1, 1, 1, 1, 1, // 104
-   1, 1, 1, 1, 1, 1, 1, 1, // 112
-   1, 1, 1, 0, 1, 0, 1]; // 120
-
-
-/**
-* Determines whether the given character code is a CTL.
-*
-* @param code : uint
-* the character code
-* @returns boolean
-* true if code is a CTL, false otherwise
-*/
-function isCTL(code)
-{
-  return (code >= 0 && code <= 31) || (code == 127);
-}
-
-/**
-* Represents a response to an HTTP request, encapsulating all details of that
-* response. This includes all headers, the HTTP version, status code and
-* explanation, and the entity itself.
-*
-* @param connection : Connection
-* the connection over which this response is to be written
-*/
-function Response(connection)
-{
-  /** The connection over which this response will be written. */
-  this._connection = connection;
-
-  /**
-* The HTTP version of this response; defaults to 1.1 if not set by the
-* handler.
-*/
-  this._httpVersion = nsHttpVersion.HTTP_1_1;
-
-  /**
-* The HTTP code of this response; defaults to 200.
-*/
-  this._httpCode = 200;
-
-  /**
-* The description of the HTTP code in this response; defaults to "OK".
-*/
-  this._httpDescription = "OK";
-
-  /**
-* An nsIHttpHeaders object in which the headers in this response should be
-* stored. This property is null after the status line and headers have been
-* written to the network, and it may be modified up until it is cleared,
-* except if this._finished is set first (in which case headers are written
-* asynchronously in response to a finish() call not preceded by
-* flushHeaders()).
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* Set to true when this response is ended (completely constructed if possible
-* and the connection closed); further actions on this will then fail.
-*/
-  this._ended = false;
-
-  /**
-* A stream used to hold data written to the body of this response.
-*/
-  this._bodyOutputStream = null;
-
-  /**
-* A stream containing all data that has been written to the body of this
-* response so far. (Async handlers make the data contained in this
-* unreliable as a way of determining content length in general, but auxiliary
-* saved information can sometimes be used to guarantee reliability.)
-*/
-  this._bodyInputStream = null;
-
-  /**
-* A stream copier which copies data to the network. It is initially null
-* until replaced with a copier for response headers; when headers have been
-* fully sent it is replaced with a copier for the response body, remaining
-* so for the duration of response processing.
-*/
-  this._asyncCopier = null;
-
-  /**
-* True if this response has been designated as being processed
-* asynchronously rather than for the duration of a single call to
-* nsIHttpRequestHandler.handle.
-*/
-  this._processAsync = false;
-
-  /**
-* True iff finish() has been called on this, signaling that no more changes
-* to this may be made.
-*/
-  this._finished = false;
-
-  /**
-* True iff powerSeized() has been called on this, signaling that this
-* response is to be handled manually by the response handler (which may then
-* send arbitrary data in response, even non-HTTP responses).
-*/
-  this._powerSeized = false;
-}
-Response.prototype =
-{
-  // PUBLIC CONSTRUCTION API
-
-  //
-  // see nsIHttpResponse.bodyOutputStream
-  //
-  get bodyOutputStream()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    if (!this._bodyOutputStream)
-    {
-      var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX,
-                          null);
-      this._bodyOutputStream = pipe.outputStream;
-      this._bodyInputStream = pipe.inputStream;
-      if (this._processAsync || this._powerSeized)
-        this._startAsyncProcessor();
-    }
-
-    return this._bodyOutputStream;
-  },
-
-  //
-  // see nsIHttpResponse.write
-  //
-  write: function(data)
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    var dataAsString = String(data);
-    this.bodyOutputStream.write(dataAsString, dataAsString.length);
-  },
-
-  //
-  // see nsIHttpResponse.setStatusLine
-  //
-  setStatusLine: function(httpVersion, code, description)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    if (!(code >= 0 && code < 1000))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    try
-    {
-      var httpVer;
-      // avoid version construction for the most common cases
-      if (!httpVersion || httpVersion == "1.1")
-        httpVer = nsHttpVersion.HTTP_1_1;
-      else if (httpVersion == "1.0")
-        httpVer = nsHttpVersion.HTTP_1_0;
-      else
-        httpVer = new nsHttpVersion(httpVersion);
-    }
-    catch (e)
-    {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    // Reason-Phrase = *<TEXT, excluding CR, LF>
-    // TEXT = <any OCTET except CTLs, but including LWS>
-    //
-    // XXX this ends up disallowing octets which aren't Unicode, I think -- not
-    // much to do if description is IDL'd as string
-    if (!description)
-      description = "";
-    for (var i = 0; i < description.length; i++)
-      if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t")
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // set the values only after validation to preserve atomicity
-    this._httpDescription = description;
-    this._httpCode = code;
-    this._httpVersion = httpVer;
-  },
-
-  //
-  // see nsIHttpResponse.setHeader
-  //
-  setHeader: function(name, value, merge)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    this._headers.setHeader(name, value, merge);
-  },
-
-  //
-  // see nsIHttpResponse.processAsync
-  //
-  processAsync: function()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._processAsync)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** processing connection " + this._connection.number + " async");
-    this._processAsync = true;
-
-    /*
-* Either the bodyOutputStream getter or this method is responsible for
-* starting the asynchronous processor and catching writes of data to the
-* response body of async responses as they happen, for the purpose of
-* forwarding those writes to the actual connection's output stream.
-* If bodyOutputStream is accessed first, calling this method will create
-* the processor (when it first is clear that body data is to be written
-* immediately, not buffered). If this method is called first, accessing
-* bodyOutputStream will create the processor. If only this method is
-* called, we'll write nothing, neither headers nor the nonexistent body,
-* until finish() is called. Since that delay is easily avoided by simply
-* getting bodyOutputStream or calling write(""), we don't worry about it.
-*/
-    if (this._bodyOutputStream && !this._asyncCopier)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.seizePower
-  //
-  seizePower: function()
-  {
-    if (this._processAsync)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** forcefully seizing power over connection " +
-          this._connection.number + "...");
-
-    // Purge any already-written data without sending it. We could as easily
-    // swap out the streams entirely, but that makes it possible to acquire and
-    // unknowingly use a stale reference, so we require there only be one of
-    // each stream ever for any response to avoid this complication.
-    if (this._asyncCopier)
-      this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED);
-    this._asyncCopier = null;
-    if (this._bodyOutputStream)
-    {
-      var input = new BinaryInputStream(this._bodyInputStream);
-      var avail;
-      while ((avail = input.available()) > 0)
-        input.readByteArray(avail);
-    }
-
-    this._powerSeized = true;
-    if (this._bodyOutputStream)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.finish
-  //
-  finish: function()
-  {
-    if (!this._processAsync && !this._powerSeized)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._finished)
-      return;
-
-    dumpn("*** finishing connection " + this._connection.number);
-    this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-    this._finished = true;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // POST-CONSTRUCTION API (not exposed externally)
-
-  /**
-* The HTTP version number of this, as a string (e.g. "1.1").
-*/
-  get httpVersion()
-  {
-    this._ensureAlive();
-    return this._httpVersion.toString();
-  },
-
-  /**
-* The HTTP status code of this response, as a string of three characters per
-* RFC 2616.
-*/
-  get httpCode()
-  {
-    this._ensureAlive();
-
-    var codeString = (this._httpCode < 10 ? "0" : "") +
-                     (this._httpCode < 100 ? "0" : "") +
-                     this._httpCode;
-    return codeString;
-  },
-
-  /**
-* The description of the HTTP status code of this response, or "" if none is
-* set.
-*/
-  get httpDescription()
-  {
-    this._ensureAlive();
-
-    return this._httpDescription;
-  },
-
-  /**
-* The headers in this response, as an nsHttpHeaders object.
-*/
-  get headers()
-  {
-    this._ensureAlive();
-
-    return this._headers;
-  },
-
-  //
-  // see nsHttpHeaders.getHeader
-  //
-  getHeader: function(name)
-  {
-    this._ensureAlive();
-
-    return this._headers.getHeader(name);
-  },
-
-  /**
-* Determines whether this response may be abandoned in favor of a newly
-* constructed response. A response may be abandoned only if it is not being
-* sent asynchronously and if raw control over it has not been taken from the
-* server.
-*
-* @returns boolean
-* true iff no data has been written to the network
-*/
-  partiallySent: function()
-  {
-    dumpn("*** partiallySent()");
-    return this._processAsync || this._powerSeized;
-  },
-
-  /**
-* If necessary, kicks off the remaining request processing needed to be done
-* after a request handler performs its initial work upon this response.
-*/
-  complete: function()
-  {
-    dumpn("*** complete()");
-    if (this._processAsync || this._powerSeized)
-    {
-      NS_ASSERT(this._processAsync ^ this._powerSeized,
-                "can't both send async and relinquish power");
-      return;
-    }
-
-    NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?");
-
-    this._startAsyncProcessor();
-
-    // Now make sure we finish processing this request!
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-  },
-
-  /**
-* Abruptly ends processing of this response, usually due to an error in an
-* incoming request but potentially due to a bad error handler. Since we
-* cannot handle the error in the usual way (giving an HTTP error page in
-* response) because data may already have been sent (or because the response
-* might be expected to have been generated asynchronously or completely from
-* scratch by the handler), we stop processing this response and abruptly
-* close the connection.
-*
-* @param e : Error
-* the exception which precipitated this abort, or null if no such exception
-* was generated
-*/
-  abort: function(e)
-  {
-    dumpn("*** abort(<" + e + ">)");
-
-    // This response will be ended by the processor if one was created.
-    var copier = this._asyncCopier;
-    if (copier)
-    {
-      // We dispatch asynchronously here so that any pending writes of data to
-      // the connection will be deterministically written. This makes it easier
-      // to specify exact behavior, and it makes observable behavior more
-      // predictable for clients. Note that the correctness of this depends on
-      // callbacks in response to _waitToReadData in WriteThroughCopier
-      // happening asynchronously with respect to the actual writing of data to
-      // bodyOutputStream, as they currently do; if they happened synchronously,
-      // an event which ran before this one could write more data to the
-      // response body before we get around to canceling the copier. We have
-      // tests for this in test_seizepower.js, however, and I can't think of a
-      // way to handle both cases without removing bodyOutputStream access and
-      // moving its effective write(data, length) method onto Response, which
-      // would be slower and require more code than this anyway.
-      gThreadManager.dispatchToMainThread({
-        run: function()
-        {
-          dumpn("*** canceling copy asynchronously...");
-          copier.cancel(Cr.NS_ERROR_UNEXPECTED);
-        }
-      });
-    }
-    else
-    {
-      this.end();
-    }
-  },
-
-  /**
-* Closes this response's network connection, marks the response as finished,
-* and notifies the server handler that the request is done being processed.
-*/
-  end: function()
-  {
-    NS_ASSERT(!this._ended, "ending this response twice?!?!");
-
-    this._connection.close();
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-
-    this._finished = true;
-    this._ended = true;
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Sends the status line and headers of this response if they haven't been
-* sent and initiates the process of copying data written to this response's
-* body to the network.
-*/
-  _startAsyncProcessor: function()
-  {
-    dumpn("*** _startAsyncProcessor()");
-
-    // Handle cases where we're being called a second time. The former case
-    // happens when this is triggered both by complete() and by processAsync(),
-    // while the latter happens when processAsync() in conjunction with sent
-    // data causes abort() to be called.
-    if (this._asyncCopier || this._ended)
-    {
-      dumpn("*** ignoring second call to _startAsyncProcessor");
-      return;
-    }
-
-    // Send headers if they haven't been sent already and should be sent, then
-    // asynchronously continue to send the body.
-    if (this._headers && !this._powerSeized)
-    {
-      this._sendHeaders();
-      return;
-    }
-
-    this._headers = null;
-    this._sendBody();
-  },
-
-  /**
-* Signals that all modifications to the response status line and headers are
-* complete and then sends that data over the network to the client. Once
-* this method completes, a different response to the request that resulted
-* in this response cannot be sent -- the only possible action in case of
-* error is to abort the response and close the connection.
-*/
-  _sendHeaders: function()
-  {
-    dumpn("*** _sendHeaders()");
-
-    NS_ASSERT(this._headers);
-    NS_ASSERT(!this._powerSeized);
-
-    // request-line
-    var statusLine = "HTTP/" + this.httpVersion + " " +
-                     this.httpCode + " " +
-                     this.httpDescription + "\r\n";
-
-    // header post-processing
-
-    var headers = this._headers;
-    headers.setHeader("Connection", "close", false);
-    headers.setHeader("Server", "httpd.js", false);
-    if (!headers.hasHeader("Date"))
-      headers.setHeader("Date", toDateString(Date.now()), false);
-
-    // Any response not being processed asynchronously must have an associated
-    // Content-Length header for reasons of backwards compatibility with the
-    // initial server, which fully buffered every response before sending it.
-    // Beyond that, however, it's good to do this anyway because otherwise it's
-    // impossible to test behaviors that depend on the presence or absence of a
-    // Content-Length header.
-    if (!this._processAsync)
-    {
-      dumpn("*** non-async response, set Content-Length");
-
-      var bodyStream = this._bodyInputStream;
-      var avail = bodyStream ? bodyStream.available() : 0;
-
-      // XXX assumes stream will always report the full amount of data available
-      headers.setHeader("Content-Length", "" + avail, false);
-    }
-
-
-    // construct and send response
-    dumpn("*** header post-processing completed, sending response head...");
-
-    // request-line
-    var preambleData = [statusLine];
-
-    // headers
-    var headEnum = headers.enumerator;
-    while (headEnum.hasMoreElements())
-    {
-      var fieldName = headEnum.getNext()
-                              .QueryInterface(Ci.nsISupportsString)
-                              .data;
-      var values = headers.getHeaderValues(fieldName);
-      for (var i = 0, sz = values.length; i < sz; i++)
-        preambleData.push(fieldName + ": " + values[i] + "\r\n");
-    }
-
-    // end request-line/headers
-    preambleData.push("\r\n");
-
-    var preamble = preambleData.join("");
-
-    var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null);
-    responseHeadPipe.outputStream.write(preamble, preamble.length);
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, cx)
-        {
-          dumpn("*** preamble copying started");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** preamble copying complete " +
-                "[status=0x" + statusCode.toString(16) + "]");
-
-          if (!components.isSuccessCode(statusCode))
-          {
-            dumpn("!!! header copying problems: non-success statusCode, " +
-                  "ending response");
-
-            response.end();
-          }
-          else
-          {
-            response._sendBody();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    var headerCopier = this._asyncCopier =
-      new WriteThroughCopier(responseHeadPipe.inputStream,
-                             this._connection.output,
-                             copyObserver, null);
-
-    responseHeadPipe.outputStream.close();
-
-    // Forbid setting any more headers or modifying the request line.
-    this._headers = null;
-  },
-
-  /**
-* Asynchronously writes the body of the response (or the entire response, if
-* seizePower() has been called) to the network.
-*/
-  _sendBody: function()
-  {
-    dumpn("*** _sendBody");
-
-    NS_ASSERT(!this._headers, "still have headers around but sending body?");
-
-    // If no body data was written, we're done
-    if (!this._bodyInputStream)
-    {
-      dumpn("*** empty body, response finished");
-      this.end();
-      return;
-    }
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, context)
-        {
-          dumpn("*** onStartRequest");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]");
-
-          if (statusCode === Cr.NS_BINDING_ABORTED)
-          {
-            dumpn("*** terminating copy observer without ending the response");
-          }
-          else
-          {
-            if (!components.isSuccessCode(statusCode))
-              dumpn("*** WARNING: non-success statusCode in onStopRequest");
-
-            response.end();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    dumpn("*** starting async copier of body data...");
-    this._asyncCopier =
-      new WriteThroughCopier(this._bodyInputStream, this._connection.output,
-                            copyObserver, null);
-  },
-
-  /** Ensures that this hasn't been ended. */
-  _ensureAlive: function()
-  {
-    NS_ASSERT(!this._ended, "not handling response lifetime correctly");
-  }
-};
-
-/**
-* Size of the segments in the buffer used in storing response data and writing
-* it to the socket.
-*/
-Response.SEGMENT_SIZE = 8192;
-
-/** Serves double duty in WriteThroughCopier implementation. */
-function notImplemented()
-{
-  throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/** Returns true iff the given exception represents stream closure. */
-function streamClosed(e)
-{
-  return e === Cr.NS_BASE_STREAM_CLOSED ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED);
-}
-
-/** Returns true iff the given exception represents a blocked stream. */
-function wouldBlock(e)
-{
-  return e === Cr.NS_BASE_STREAM_WOULD_BLOCK ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK);
-}
-
-/**
-* Copies data from source to sink as it becomes available, when that data can
-* be written to sink without blocking.
-*
-* @param source : nsIAsyncInputStream
-* the stream from which data is to be read
-* @param sink : nsIAsyncOutputStream
-* the stream to which data is to be copied
-* @param observer : nsIRequestObserver
-* an observer which will be notified when the copy starts and finishes
-* @param context : nsISupports
-* context passed to observer when notified of start/stop
-* @throws NS_ERROR_NULL_POINTER
-* if source, sink, or observer are null
-*/
-function WriteThroughCopier(source, sink, observer, context)
-{
-  if (!source || !sink || !observer)
-    throw Cr.NS_ERROR_NULL_POINTER;
-
-  /** Stream from which data is being read. */
-  this._source = source;
-
-  /** Stream to which data is being written. */
-  this._sink = sink;
-
-  /** Observer watching this copy. */
-  this._observer = observer;
-
-  /** Context for the observer watching this. */
-  this._context = context;
-
-  /**
-* True iff this is currently being canceled (cancel has been called, the
-* callback may not yet have been made).
-*/
-  this._canceled = false;
-
-  /**
-* False until all data has been read from input and written to output, at
-* which point this copy is completed and cancel() is asynchronously called.
-*/
-  this._completed = false;
-
-  /** Required by nsIRequest, meaningless. */
-  this.loadFlags = 0;
-  /** Required by nsIRequest, meaningless. */
-  this.loadGroup = null;
-  /** Required by nsIRequest, meaningless. */
-  this.name = "response-body-copy";
-
-  /** Status of this request. */
-  this.status = Cr.NS_OK;
-
-  /** Arrays of byte strings waiting to be written to output. */
-  this._pendingData = [];
-
-  // start copying
-  try
-  {
-    observer.onStartRequest(this, context);
-    this._waitToReadData();
-    this._waitForSinkClosure();
-  }
-  catch (e)
-  {
-    dumpn("!!! error starting copy: " + e +
-          ("lineNumber" in e ? ", line " + e.lineNumber : ""));
-    dumpn(e.stack);
-    this.cancel(Cr.NS_ERROR_UNEXPECTED);
-  }
-}
-WriteThroughCopier.prototype =
-{
-  /* nsISupports implementation */
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIInputStreamCallback) ||
-        iid.equals(Ci.nsIOutputStreamCallback) ||
-        iid.equals(Ci.nsIRequest) ||
-        iid.equals(Ci.nsISupports))
-    {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Receives a more-data-in-input notification and writes the corresponding
-* data to the output.
-*
-* @param input : nsIAsyncInputStream
-* the input stream on whose data we have been waiting
-*/
-  onInputStreamReady: function(input)
-  {
-    if (this._source === null)
-      return;
-
-    dumpn("*** onInputStreamReady");
-
-    //
-    // Ordinarily we'll read a non-zero amount of data from input, queue it up
-    // to be written and then wait for further callbacks. The complications in
-    // this method are the cases where we deviate from that behavior when errors
-    // occur or when copying is drawing to a finish.
-    //
-    // The edge cases when reading data are:
-    //
-    // Zero data is read
-    // If zero data was read, we're at the end of available data, so we can
-    // should stop reading and move on to writing out what we have (or, if
-    // we've already done that, onto notifying of completion).
-    // A stream-closed exception is thrown
-    // This is effectively a less kind version of zero data being read; the
-    // only difference is that we notify of completion with that result
-    // rather than with NS_OK.
-    // Some other exception is thrown
-    // This is the least kind result. We don't know what happened, so we
-    // act as though the stream closed except that we notify of completion
-    // with the result NS_ERROR_UNEXPECTED.
-    //
-
-    var bytesWanted = 0, bytesConsumed = -1;
-    try
-    {
-      input = new BinaryInputStream(input);
-
-      bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE);
-      dumpn("*** input wanted: " + bytesWanted);
-
-      if (bytesWanted > 0)
-      {
-        var data = input.readByteArray(bytesWanted);
-        bytesConsumed = data.length;
-        this._pendingData.push(String.fromCharCode.apply(String, data));
-      }
-
-      dumpn("*** " + bytesConsumed + " bytes read");
-
-      // Handle the zero-data edge case in the same place as all other edge
-      // cases are handled.
-      if (bytesWanted === 0)
-        throw Cr.NS_BASE_STREAM_CLOSED;
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** input stream closed");
-        e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED;
-      }
-      else
-      {
-        dumpn("!!! unexpected error reading from input, canceling: " + e);
-        e = Cr.NS_ERROR_UNEXPECTED;
-      }
-
-      this._doneReadingSource(e);
-      return;
-    }
-
-    var pendingData = this._pendingData;
-
-    NS_ASSERT(bytesConsumed > 0);
-    NS_ASSERT(pendingData.length > 0, "no pending data somehow?");
-    NS_ASSERT(pendingData[pendingData.length - 1].length > 0,
-              "buffered zero bytes of data?");
-
-    NS_ASSERT(this._source !== null);
-
-    // Reading has gone great, and we've gotten data to write now. What if we
-    // don't have a place to write that data, because output went away just
-    // before this read? Drop everything on the floor, including new data, and
-    // cancel at this point.
-    if (this._sink === null)
-    {
-      pendingData.length = 0;
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we've read the data, and we know we have a place to write it. We
-    // need to queue up the data to be written, but *only* if none is queued
-    // already -- if data's already queued, the code that actually writes the
-    // data will make sure to wait on unconsumed pending data.
-    try
-    {
-      if (pendingData.length === 1)
-        this._waitToWriteData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to write data just read, swallowing and " +
-            "writing only what we already have: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Whee! We successfully read some data, and it's successfully queued up to
-    // be written. All that remains now is to wait for more data to read.
-    try
-    {
-      this._waitToReadData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to read more data: " + e);
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-    }
-  },
-
-
-  // NSIOUTPUTSTREAMCALLBACK
-
-  /**
-* Callback when data may be written to the output stream without blocking, or
-* when the output stream has been closed.
-*
-* @param output : nsIAsyncOutputStream
-* the output stream on whose writability we've been waiting, also known as
-* this._sink
-*/
-  onOutputStreamReady: function(output)
-  {
-    if (this._sink === null)
-      return;
-
-    dumpn("*** onOutputStreamReady");
-
-    var pendingData = this._pendingData;
-    if (pendingData.length === 0)
-    {
-      // There's no pending data to write. The only way this can happen is if
-      // we're waiting on the output stream's closure, so we can respond to a
-      // copying failure as quickly as possible (rather than waiting for data to
-      // be available to read and then fail to be copied). Therefore, we must
-      // be done now -- don't bother to attempt to write anything and wrap
-      // things up.
-      dumpn("!!! output stream closed prematurely, ending copy");
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-
-    NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?");
-
-    //
-    // Write out the first pending quantum of data. The possible errors here
-    // are:
-    //
-    // The write might fail because we can't write that much data
-    // Okay, we've written what we can now, so re-queue what's left and
-    // finish writing it out later.
-    // The write failed because the stream was closed
-    // Discard pending data that we can no longer write, stop reading, and
-    // signal that copying finished.
-    // Some other error occurred.
-    // Same as if the stream were closed, but notify with the status
-    // NS_ERROR_UNEXPECTED so the observer knows something was wonky.
-    //
-
-    try
-    {
-      var quantum = pendingData[0];
-
-      // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on
-      // undefined behavior! We're only using this because writeByteArray
-      // is unusably broken for asynchronous output streams; see bug 532834
-      // for details.
-      var bytesWritten = output.write(quantum, quantum.length);
-      if (bytesWritten === quantum.length)
-        pendingData.shift();
-      else
-        pendingData[0] = quantum.substring(bytesWritten);
-
-      dumpn("*** wrote " + bytesWritten + " bytes of data");
-    }
-    catch (e)
-    {
-      if (wouldBlock(e))
-      {
-        NS_ASSERT(pendingData.length > 0,
-                  "stream-blocking exception with no data to write?");
-        NS_ASSERT(pendingData[0].length > 0,
-                  "stream-blocking exception with empty quantum?");
-        this._waitToWriteData();
-        return;
-      }
-
-      if (streamClosed(e))
-        dumpn("!!! output stream prematurely closed, signaling error...");
-      else
-        dumpn("!!! unknown error: " + e + ", quantum=" + quantum);
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // The day is ours! Quantum written, now let's see if we have more data
-    // still to write.
-    try
-    {
-      if (pendingData.length > 0)
-      {
-        this._waitToWriteData();
-        return;
-      }
-    }
-    catch (e)
-    {
-      dumpn("!!! unexpected error waiting to write pending data: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we have no more pending data to write -- but might we get more in
-    // the future?
-    if (this._source !== null)
-    {
-      /*
-* If we might, then wait for the output stream to be closed. (We wait
-* only for closure because we have no data to write -- and if we waited
-* for a specific amount of data, we would get repeatedly notified for no
-* reason if over time the output stream permitted more and more data to
-* be written to it without blocking.)
-*/
-       this._waitForSinkClosure();
-    }
-    else
-    {
-      /*
-* On the other hand, if we can't have more data because the input
-* stream's gone away, then it's time to notify of copy completion.
-* Victory!
-*/
-      this._sink = null;
-      this._cancelOrDispatchCancelCallback(Cr.NS_OK);
-    }
-  },
-
-
-  // NSIREQUEST
-
-  /** Returns true if the cancel observer hasn't been notified yet. */
-  isPending: function()
-  {
-    return !this._completed;
-  },
-
-  /** Not implemented, don't use! */
-  suspend: notImplemented,
-  /** Not implemented, don't use! */
-  resume: notImplemented,
-
-  /**
-* Cancels data reading from input, asynchronously writes out any pending
-* data, and causes the observer to be notified with the given error code when
-* all writing has finished.
-*
-* @param status : nsresult
-* the status to pass to the observer when data copying has been canceled
-*/
-  cancel: function(status)
-  {
-    dumpn("*** cancel(" + status.toString(16) + ")");
-
-    if (this._canceled)
-    {
-      dumpn("*** suppressing a late cancel");
-      return;
-    }
-
-    this._canceled = true;
-    this.status = status;
-
-    // We could be in the middle of absolutely anything at this point. Both
-    // input and output might still be around, we might have pending data to
-    // write, and in general we know nothing about the state of the world. We
-    // therefore must assume everything's in progress and take everything to its
-    // final steady state (or so far as it can go before we need to finish
-    // writing out remaining data).
-
-    this._doneReadingSource(status);
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Stop reading input if we haven't already done so, passing e as the status
-* when closing the stream, and kick off a copy-completion notice if no more
-* data remains to be written.
-*
-* @param e : nsresult
-* the status to be used when closing the input stream
-*/
-  _doneReadingSource: function(e)
-  {
-    dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
-
-    this._finishSource(e);
-    if (this._pendingData.length === 0)
-      this._sink = null;
-    else
-      NS_ASSERT(this._sink !== null, "null output?");
-
-    // If we've written out all data read up to this point, then it's time to
-    // signal completion.
-    if (this._sink === null)
-    {
-      NS_ASSERT(this._pendingData.length === 0, "pending data still?");
-      this._cancelOrDispatchCancelCallback(e);
-    }
-  },
-
-  /**
-* Stop writing output if we haven't already done so, discard any data that
-* remained to be sent, close off input if it wasn't already closed, and kick
-* off a copy-completion notice.
-*
-* @param e : nsresult
-* the status to be used when closing input if it wasn't already closed
-*/
-  _doneWritingToSink: function(e)
-  {
-    dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")");
-
-    this._pendingData.length = 0;
-    this._sink = null;
-    this._doneReadingSource(e);
-  },
-
-  /**
-* Completes processing of this copy: either by canceling the copy if it
-* hasn't already been canceled using the provided status, or by dispatching
-* the cancel callback event (with the originally provided status, of course)
-* if it already has been canceled.
-*
-* @param status : nsresult
-* the status code to use to cancel this, if this hasn't already been
-* canceled
-*/
-  _cancelOrDispatchCancelCallback: function(status)
-  {
-    dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")");
-
-    NS_ASSERT(this._source === null, "should have finished input");
-    NS_ASSERT(this._sink === null, "should have finished output");
-    NS_ASSERT(this._pendingData.length === 0, "should have no pending data");
-
-    if (!this._canceled)
-    {
-      this.cancel(status);
-      return;
-    }
-
-    var self = this;
-    var event =
-      {
-        run: function()
-        {
-          dumpn("*** onStopRequest async callback");
-
-          self._completed = true;
-          try
-          {
-            self._observer.onStopRequest(self, self._context, self.status);
-          }
-          catch (e)
-          {
-            NS_ASSERT(false,
-                      "how are we throwing an exception here? we control " +
-                      "all the callers! " + e);
-          }
-        }
-      };
-
-    gThreadManager.dispatchToMainThread(event);
-  },
-
-  /**
-* Kicks off another wait for more data to be available from the input stream.
-*/
-  _waitToReadData: function()
-  {
-    dumpn("*** _waitToReadData");
-    this._source.asyncWait(this, 0, Response.SEGMENT_SIZE,
-                           gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off another wait until data can be written to the output stream.
-*/
-  _waitToWriteData: function()
-  {
-    dumpn("*** _waitToWriteData");
-
-    var pendingData = this._pendingData;
-    NS_ASSERT(pendingData.length > 0, "no pending data to write?");
-    NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?");
-
-    this._sink.asyncWait(this, 0, pendingData[0].length,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off a wait for the sink to which data is being copied to be closed.
-* We wait for stream closure when we don't have any data to be copied, rather
-* than waiting to write a specific amount of data. We can't wait to write
-* data because the sink might be infinitely writable, and if no data appears
-* in the source for a long time we might have to spin quite a bit waiting to
-* write, waiting to write again, &c. Waiting on stream closure instead means
-* we'll get just one notification if the sink dies. Note that when data
-* starts arriving from the sink we'll resume waiting for data to be written,
-* dropping this closure-only callback entirely.
-*/
-  _waitForSinkClosure: function()
-  {
-    dumpn("*** _waitForSinkClosure");
-
-    this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Closes input with the given status, if it hasn't already been closed;
-* otherwise a no-op.
-*
-* @param status : nsresult
-* status code use to close the source stream if necessary
-*/
-  _finishSource: function(status)
-  {
-    dumpn("*** _finishSource(" + status.toString(16) + ")");
-
-    if (this._source !== null)
-    {
-      this._source.closeWithStatus(status);
-      this._source = null;
-    }
-  }
-};
-
-
-/**
-* A container for utility functions used with HTTP headers.
-*/
-const headerUtils =
-{
-  /**
-* Normalizes fieldName (by converting it to lowercase) and ensures it is a
-* valid header field name (although not necessarily one specified in RFC
-* 2616).
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not match the field-name production in RFC 2616
-* @returns string
-* fieldName converted to lowercase if it is a valid header, for characters
-* where case conversion is possible
-*/
-  normalizeFieldName: function(fieldName)
-  {
-    if (fieldName == "")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    for (var i = 0, sz = fieldName.length; i < sz; i++)
-    {
-      if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
-      {
-        dumpn(fieldName + " is not a valid header field name!");
-        throw Cr.NS_ERROR_INVALID_ARG;
-      }
-    }
-
-    return fieldName.toLowerCase();
-  },
-
-  /**
-* Ensures that fieldValue is a valid header field value (although not
-* necessarily as specified in RFC 2616 if the corresponding field name is
-* part of the HTTP protocol), normalizes the value if it is, and
-* returns the normalized value.
-*
-* @param fieldValue : string
-* a value to be normalized as an HTTP header field value
-* @throws NS_ERROR_INVALID_ARG
-* if fieldValue does not match the field-value production in RFC 2616
-* @returns string
-* fieldValue as a normalized HTTP header field value
-*/
-  normalizeFieldValue: function(fieldValue)
-  {
-    // field-value = *( field-content | LWS )
-    // field-content = <the OCTETs making up the field-value
-    // and consisting of either *TEXT or combinations
-    // of token, separators, and quoted-string>
-    // TEXT = <any OCTET except CTLs,
-    // but including LWS>
-    // LWS = [CRLF] 1*( SP | HT )
-    //
-    // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-    // qdtext = <any TEXT except <">>
-    // quoted-pair = "\" CHAR
-    // CHAR = <any US-ASCII character (octets 0 - 127)>
-
-    // Any LWS that occurs between field-content MAY be replaced with a single
-    // SP before interpreting the field value or forwarding the message
-    // downstream (section 4.2); we replace 1*LWS with a single SP
-    var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
-
-    // remove leading/trailing LWS (which has been converted to SP)
-    val = val.replace(/^ +/, "").replace(/ +$/, "");
-
-    // that should have taken care of all CTLs, so val should contain no CTLs
-    for (var i = 0, len = val.length; i < len; i++)
-      if (isCTL(val.charCodeAt(i)))
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
-    // normalize, however, so this can be construed as a tightening of the
-    // spec and not entirely as a bug
-    return val;
-  }
-};
-
-
-
-/**
-* Converts the given string into a string which is safe for use in an HTML
-* context.
-*
-* @param str : string
-* the string to make HTML-safe
-* @returns string
-* an HTML-safe version of str
-*/
-function htmlEscape(str)
-{
-  // this is naive, but it'll work
-  var s = "";
-  for (var i = 0; i < str.length; i++)
-    s += "&#" + str.charCodeAt(i) + ";";
-  return s;
-}
-
-
-/**
-* Constructs an object representing an HTTP version (see section 3.1).
-*
-* @param versionString
-* a string of the form "#.#", where # is an non-negative decimal integer with
-* or without leading zeros
-* @throws
-* if versionString does not specify a valid HTTP version number
-*/
-function nsHttpVersion(versionString)
-{
-  var matches = /^(\d+)\.(\d+)$/.exec(versionString);
-  if (!matches)
-    throw "Not a valid HTTP version!";
-
-  /** The major version number of this, as a number. */
-  this.major = parseInt(matches[1], 10);
-
-  /** The minor version number of this, as a number. */
-  this.minor = parseInt(matches[2], 10);
-
-  if (isNaN(this.major) || isNaN(this.minor) ||
-      this.major < 0 || this.minor < 0)
-    throw "Not a valid HTTP version!";
-}
-nsHttpVersion.prototype =
-{
-  /**
-* Returns the standard string representation of the HTTP version represented
-* by this (e.g., "1.1").
-*/
-  toString: function ()
-  {
-    return this.major + "." + this.minor;
-  },
-
-  /**
-* Returns true if this represents the same HTTP version as otherVersion,
-* false otherwise.
-*
-* @param otherVersion : nsHttpVersion
-* the version to compare against this
-*/
-  equals: function (otherVersion)
-  {
-    return this.major == otherVersion.major &&
-           this.minor == otherVersion.minor;
-  },
-
-  /** True if this >= otherVersion, false otherwise. */
-  atLeast: function(otherVersion)
-  {
-    return this.major > otherVersion.major ||
-           (this.major == otherVersion.major &&
-            this.minor >= otherVersion.minor);
-  }
-};
-
-nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0");
-nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1");
-
-
-/**
-* An object which stores HTTP headers for a request or response.
-*
-* Note that since headers are case-insensitive, this object converts headers to
-* lowercase before storing them. This allows the getHeader and hasHeader
-* methods to work correctly for any case of a header, but it means that the
-* values returned by .enumerator may not be equal case-sensitively to the
-* values passed to setHeader when adding headers to this.
-*/
-function nsHttpHeaders()
-{
-  /**
-* A hash of headers, with header field names as the keys and header field
-* values as the values. Header field names are case-insensitive, but upon
-* insertion here they are converted to lowercase. Header field values are
-* normalized upon insertion to contain no leading or trailing whitespace.
-*
-* Note also that per RFC 2616, section 4.2, two headers with the same name in
-* a message may be treated as one header with the same field name and a field
-* value consisting of the separate field values joined together with a "," in
-* their original order. This hash stores multiple headers with the same name
-* in this manner.
-*/
-  this._headers = {};
-}
-nsHttpHeaders.prototype =
-{
-  /**
-* Sets the header represented by name and value in this.
-*
-* @param name : string
-* the header name
-* @param value : string
-* the header value
-* @throws NS_ERROR_INVALID_ARG
-* if name or value is not a valid header component
-*/
-  setHeader: function(fieldName, fieldValue, merge)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    var value = headerUtils.normalizeFieldValue(fieldValue);
-
-    // The following three headers are stored as arrays because their real-world
-    // syntax prevents joining individual headers into a single header using
-    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
-    if (merge && name in this._headers)
-    {
-      if (name === "www-authenticate" ||
-          name === "proxy-authenticate" ||
-          name === "set-cookie")
-      {
-        this._headers[name].push(value);
-      }
-      else
-      {
-        this._headers[name][0] += "," + value;
-        NS_ASSERT(this._headers[name].length === 1,
-            "how'd a non-special header have multiple values?")
-      }
-    }
-    else
-    {
-      this._headers[name] = [value];
-    }
-  },
-
-  /**
-* Returns the value for the header specified by this.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns string
-* the field value for the given header, possibly with non-semantic changes
-* (i.e., leading/trailing whitespace stripped, whitespace runs replaced
-* with spaces, etc.) at the option of the implementation; multiple
-* instances of the header will be combined with a comma, except for
-* the three headers noted in the description of getHeaderValues
-*/
-  getHeader: function(fieldName)
-  {
-    return this.getHeaderValues(fieldName).join("\n");
-  },
-
-  /**
-* Returns the value for the header specified by fieldName as an array.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns [string]
-* an array of all the header values in this for the given
-* header name. Header values will generally be collapsed
-* into a single header by joining all header values together
-* with commas, but certain headers (Proxy-Authenticate,
-* WWW-Authenticate, and Set-Cookie) violate the HTTP spec
-* and cannot be collapsed in this manner. For these headers
-* only, the returned array may contain multiple elements if
-* that header has been added more than once.
-*/
-  getHeaderValues: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-
-    if (name in this._headers)
-      return this._headers[name];
-    else
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-  },
-
-  /**
-* Returns true if a header with the given field name exists in this, false
-* otherwise.
-*
-* @param fieldName : string
-* the field name whose existence is to be determined in this
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @returns boolean
-* true if the header's present, false otherwise
-*/
-  hasHeader: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    return (name in this._headers);
-  },
-
-  /**
-* Returns a new enumerator over the field names of the headers in this, as
-* nsISupportsStrings. The names returned will be in lowercase, regardless of
-* how they were input using setHeader (header names are case-insensitive per
-* RFC 2616).
-*/
-  get enumerator()
-  {
-    var headers = [];
-    for (var i in this._headers)
-    {
-      var supports = new SupportsString();
-      supports.data = i;
-      headers.push(supports);
-    }
-
-    return new nsSimpleEnumerator(headers);
-  }
-};
-
-
-/**
-* Constructs an nsISimpleEnumerator for the given array of items.
-*
-* @param items : Array
-* the items, which must all implement nsISupports
-*/
-function nsSimpleEnumerator(items)
-{
-  this._items = items;
-  this._nextIndex = 0;
-}
-nsSimpleEnumerator.prototype =
-{
-  hasMoreElements: function()
-  {
-    return this._nextIndex < this._items.length;
-  },
-  getNext: function()
-  {
-    if (!this.hasMoreElements())
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    return this._items[this._nextIndex++];
-  },
-  QueryInterface: function(aIID)
-  {
-    if (Ci.nsISimpleEnumerator.equals(aIID) ||
-        Ci.nsISupports.equals(aIID))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-
-/**
-* A representation of the data in an HTTP request.
-*
-* @param port : uint
-* the port on which the server receiving this request runs
-*/
-function Request(port)
-{
-  /** Method of this request, e.g. GET or POST. */
-  this._method = "";
-
-  /** Path of the requested resource; empty paths are converted to '/'. */
-  this._path = "";
-
-  /** Query string, if any, associated with this request (not including '?'). */
-  this._queryString = "";
-
-  /** Scheme of requested resource, usually http, always lowercase. */
-  this._scheme = "http";
-
-  /** Hostname on which the requested resource resides. */
-  this._host = undefined;
-
-  /** Port number over which the request was received. */
-  this._port = port;
-
-  var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null);
-
-  /** Stream from which data in this request's body may be read. */
-  this._bodyInputStream = bodyPipe.inputStream;
-
-  /** Stream to which data in this request's body is written. */
-  this._bodyOutputStream = bodyPipe.outputStream;
-
-  /**
-* The headers in this request.
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* For the addition of ad-hoc properties and new functionality without having
-* to change nsIHttpRequest every time; currently lazily created, as its only
-* use is in directory listings.
-*/
-  this._bag = null;
-}
-Request.prototype =
-{
-  // SERVER METADATA
-
-  //
-  // see nsIHttpRequest.scheme
-  //
-  get scheme()
-  {
-    return this._scheme;
-  },
-
-  //
-  // see nsIHttpRequest.host
-  //
-  get host()
-  {
-    return this._host;
-  },
-
-  //
-  // see nsIHttpRequest.port
-  //
-  get port()
-  {
-    return this._port;
-  },
-
-  // REQUEST LINE
-
-  //
-  // see nsIHttpRequest.method
-  //
-  get method()
-  {
-    return this._method;
-  },
-
-  //
-  // see nsIHttpRequest.httpVersion
-  //
-  get httpVersion()
-  {
-    return this._httpVersion.toString();
-  },
-
-  //
-  // see nsIHttpRequest.path
-  //
-  get path()
-  {
-    return this._path;
-  },
-
-  //
-  // see nsIHttpRequest.queryString
-  //
-  get queryString()
-  {
-    return this._queryString;
-  },
-
-  // HEADERS
-
-  //
-  // see nsIHttpRequest.getHeader
-  //
-  getHeader: function(name)
-  {
-    return this._headers.getHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.hasHeader
-  //
-  hasHeader: function(name)
-  {
-    return this._headers.hasHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get headers()
-  {
-    return this._headers.enumerator;
-  },
-
-  //
-  // see nsIPropertyBag.enumerator
-  //
-  get enumerator()
-  {
-    this._ensurePropertyBag();
-    return this._bag.enumerator;
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get bodyInputStream()
-  {
-    return this._bodyInputStream;
-  },
-
-  //
-  // see nsIPropertyBag.getProperty
-  //
-  getProperty: function(name)
-  {
-    this._ensurePropertyBag();
-    return this._bag.getProperty(name);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /** Ensures a property bag has been created for ad-hoc behaviors. */
-  _ensurePropertyBag: function()
-  {
-    if (!this._bag)
-      this._bag = new WritablePropertyBag();
-  }
-};
-
-
-// XPCOM trappings
-if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason...
-    "generateNSGetFactory" in XPCOMUtils) {
-  var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]);
-}
-
-
-
-/**
-* Creates a new HTTP server listening for loopback traffic on the given port,
-* starts it, and runs the server until the server processes a shutdown request,
-* spinning an event loop so that events posted by the server's socket are
-* processed.
-*
-* This method is primarily intended for use in running this script from within
-* xpcshell and running a functional HTTP server without having to deal with
-* non-essential details.
-*
-* Note that running multiple servers using variants of this method probably
-* doesn't work, simply due to how the internal event loop is spun and stopped.
-*
-* @note
-* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code);
-* you should use this server as a component in Mozilla 1.8.
-* @param port
-* the port on which the server will run, or -1 if there exists no preference
-* for a specific port; note that attempting to use some values for this
-* parameter (particularly those below 1024) may cause this method to throw or
-* may result in the server being prematurely shut down
-* @param basePath
-* a local directory from which requests will be served (i.e., if this is
-* "/home/jwalden/" then a request to /index.html will load
-* /home/jwalden/index.html); if this is omitted, only the default URLs in
-* this server implementation will be functional
-*/
-function server(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  // if you're running this, you probably want to see debugging info
-  DEBUG = true;
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", SJS_TYPE);
-  srv.start(port);
-
-  gThreadManager.spinEventLoopUntil(() => srv.isStopped());
-
-  gThreadManager.spinEventLoopUntilEmpty();
-
-  DEBUG = false;
-}
-
-function startServerAsync(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", "sjs");
-  srv.start(port);
-  return srv;
-}
-
-exports.nsHttpServer = nsHttpServer;
-exports.ScriptableInputStream = ScriptableInputStream;
-exports.server = server;
-exports.startServerAsync = startServerAsync;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-permissions/main.js
+++ /dev/null
@@ -1,88 +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 { PageMod } = require("sdk/page-mod");
-const tabs = require("sdk/tabs");
-const { startServerAsync } = require("./httpd");
-
-const serverPort = 8099;
-const TEST_TAB_URL = "about:mozilla";
-
-exports.testCrossDomainIframe = function(assert, done) {
-  let server = startServerAsync(serverPort);
-  server.registerPathHandler("/iframe", function handle(request, response) {
-    response.write("<html><body>foo</body></html>");
-  });
-
-  let pageMod = PageMod({
-    include: TEST_TAB_URL,
-    contentScript: "new " + function ContentScriptScope() {
-      self.on("message", function (url) {
-        let iframe = document.createElement("iframe");
-        iframe.addEventListener("load", function() {
-          self.postMessage(iframe.contentWindow.document.body.innerHTML);
-        }, {once: true});
-        iframe.setAttribute("src", url);
-        document.documentElement.appendChild(iframe);
-      });
-    },
-    onAttach: function(w) {
-      w.on("message", function (body) {
-        assert.equal(body, "foo", "received iframe html content");
-        pageMod.destroy();
-        w.tab.close(function() {
-          server.stop(done);
-        });
-      });
-
-      w.postMessage("http://localhost:" + serverPort + "/iframe");
-    }
-  });
-
-  tabs.open({
-    url: TEST_TAB_URL,
-    inBackground: true
-  });
-};
-
-exports.testCrossDomainXHR = function(assert, done) {
-  let server = startServerAsync(serverPort);
-  server.registerPathHandler("/xhr", function handle(request, response) {
-    response.write("foo");
-  });
-
-  let pageMod = PageMod({
-    include: TEST_TAB_URL,
-    contentScript: "new " + function ContentScriptScope() {
-      self.on("message", function (url) {
-        let request = new XMLHttpRequest();
-        request.overrideMimeType("text/plain");
-        request.open("GET", url, true);
-        request.onload = function () {
-          self.postMessage(request.responseText);
-        };
-        request.send(null);
-      });
-    },
-    onAttach: function(w) {
-      w.on("message", function (body) {
-        assert.equal(body, "foo", "received XHR content");
-        pageMod.destroy();
-        w.tab.close(function() {
-          server.stop(done);
-        });
-      });
-
-      w.postMessage("http://localhost:" + serverPort + "/xhr");
-    }
-  });
-
-  tabs.open({
-    url: TEST_TAB_URL,
-    inBackground: true
-  });
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-permissions/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "content-permissions@jetpack",
-  "permissions": {
-    "cross-domain-content": ["http://localhost:8099"]
-  },
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
+++ /dev/null
@@ -1,5205 +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/. */
-
-/*
-*  NOTE: do not edit this file, this is copied from:
-*  https://github.com/mozilla/addon-sdk/blob/master/test/lib/httpd.js
-*/
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { components, CC, Cc, Ci, Cr, Cu } = require("chrome");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
-const PR_UINT32_MAX = Math.pow(2, 32) - 1;
-
-/** True if debugging output is enabled, false otherwise. */
-var DEBUG = false; // non-const *only* so tweakable in server tests
-
-/** True if debugging output should be timestamped. */
-var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests
-
-var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance();
-
-/**
-* Asserts that the given condition holds. If it doesn't, the given message is
-* dumped, a stack trace is printed, and an exception is thrown to attempt to
-* stop execution (which unfortunately must rely upon the exception not being
-* accidentally swallowed by the code that uses it).
-*/
-function NS_ASSERT(cond, msg)
-{
-  if (DEBUG && !cond)
-  {
-    dumpn("###!!!");
-    dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!"));
-    dumpn("###!!! Stack follows:");
-
-    var stack = new Error().stack.split(/\n/);
-    dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n"));
-
-    throw Cr.NS_ERROR_ABORT;
-  }
-}
-
-/** Constructs an HTTP error object. */
-function HttpError(code, description)
-{
-  this.code = code;
-  this.description = description;
-}
-HttpError.prototype =
-{
-  toString: function()
-  {
-    return this.code + " " + this.description;
-  }
-};
-
-/**
-* Errors thrown to trigger specific HTTP server responses.
-*/
-const HTTP_400 = new HttpError(400, "Bad Request");
-const HTTP_401 = new HttpError(401, "Unauthorized");
-const HTTP_402 = new HttpError(402, "Payment Required");
-const HTTP_403 = new HttpError(403, "Forbidden");
-const HTTP_404 = new HttpError(404, "Not Found");
-const HTTP_405 = new HttpError(405, "Method Not Allowed");
-const HTTP_406 = new HttpError(406, "Not Acceptable");
-const HTTP_407 = new HttpError(407, "Proxy Authentication Required");
-const HTTP_408 = new HttpError(408, "Request Timeout");
-const HTTP_409 = new HttpError(409, "Conflict");
-const HTTP_410 = new HttpError(410, "Gone");
-const HTTP_411 = new HttpError(411, "Length Required");
-const HTTP_412 = new HttpError(412, "Precondition Failed");
-const HTTP_413 = new HttpError(413, "Request Entity Too Large");
-const HTTP_414 = new HttpError(414, "Request-URI Too Long");
-const HTTP_415 = new HttpError(415, "Unsupported Media Type");
-const HTTP_417 = new HttpError(417, "Expectation Failed");
-
-const HTTP_500 = new HttpError(500, "Internal Server Error");
-const HTTP_501 = new HttpError(501, "Not Implemented");
-const HTTP_502 = new HttpError(502, "Bad Gateway");
-const HTTP_503 = new HttpError(503, "Service Unavailable");
-const HTTP_504 = new HttpError(504, "Gateway Timeout");
-const HTTP_505 = new HttpError(505, "HTTP Version Not Supported");
-
-/** Creates a hash with fields corresponding to the values in arr. */
-function array2obj(arr)
-{
-  var obj = {};
-  for (var i = 0; i < arr.length; i++)
-    obj[arr[i]] = arr[i];
-  return obj;
-}
-
-/** Returns an array of the integers x through y, inclusive. */
-function range(x, y)
-{
-  var arr = [];
-  for (var i = x; i <= y; i++)
-    arr.push(i);
-  return arr;
-}
-
-/** An object (hash) whose fields are the numbers of all HTTP error codes. */
-const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505)));
-
-
-/**
-* The character used to distinguish hidden files from non-hidden files, a la
-* the leading dot in Apache. Since that mechanism also hides files from
-* easy display in LXR, ls output, etc. however, we choose instead to use a
-* suffix character. If a requested file ends with it, we append another
-* when getting the file on the server. If it doesn't, we just look up that
-* file. Therefore, any file whose name ends with exactly one of the character
-* is "hidden" and available for use by the server.
-*/
-const HIDDEN_CHAR = "^";
-
-/**
-* The file name suffix indicating the file containing overridden headers for
-* a requested file.
-*/
-const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
-
-/** Type used to denote SJS scripts for CGI-like functionality. */
-const SJS_TYPE = "sjs";
-
-/** Base for relative timestamps produced by dumpn(). */
-var firstStamp = 0;
-
-/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */
-function dumpn(str)
-{
-  if (DEBUG)
-  {
-    var prefix = "HTTPD-INFO | ";
-    if (DEBUG_TIMESTAMP)
-    {
-      if (firstStamp === 0)
-        firstStamp = Date.now();
-
-      var elapsed = Date.now() - firstStamp; // milliseconds
-      var min = Math.floor(elapsed / 60000);
-      var sec = (elapsed % 60000) / 1000;
-
-      if (sec < 10)
-        prefix += min + ":0" + sec.toFixed(3) + " | ";
-      else
-        prefix += min + ":" + sec.toFixed(3) + " | ";
-    }
-
-    dump(prefix + str + "\n");
-  }
-}
-
-/** Dumps the current JS stack if DEBUG. */
-function dumpStack()
-{
-  // peel off the frames for dumpStack() and Error()
-  var stack = new Error().stack.split(/\n/).slice(2);
-  stack.forEach(dumpn);
-}
-
-
-/** The XPCOM thread manager. */
-var gThreadManager = null;
-
-/** The XPCOM prefs service. */
-var gRootPrefBranch = null;
-function getRootPrefBranch()
-{
-  if (!gRootPrefBranch)
-  {
-    gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"]
-                        .getService(Ci.nsIPrefBranch);
-  }
-  return gRootPrefBranch;
-}
-
-/**
-* JavaScript constructors for commonly-used classes; precreating these is a
-* speedup over doing the same from base principles. See the docs at
-* http://developer.mozilla.org/en/docs/components.Constructor for details.
-*/
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
-                                 "nsIScriptableInputStream",
-                                 "init");
-const Pipe = CC("@mozilla.org/pipe;1",
-                "nsIPipe",
-                "init");
-const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
-                           "nsIFileInputStream",
-                           "init");
-const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1",
-                                "nsIConverterInputStream",
-                                "init");
-const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
-                               "nsIWritablePropertyBag2");
-const SupportsString = CC("@mozilla.org/supports-string;1",
-                          "nsISupportsString");
-
-/* These two are non-const only so a test can overwrite them. */
-var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
-                            "nsIBinaryOutputStream",
-                            "setOutputStream");
-
-/**
-* Returns the RFC 822/1123 representation of a date.
-*
-* @param date : Number
-* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT
-* @returns string
-* the representation of the given date
-*/
-function toDateString(date)
-{
-  //
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // date1 = 2DIGIT SP month SP 4DIGIT
-  // ; day month year (e.g., 02 Jun 1982)
-  // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  // ; 00:00:00 - 23:59:59
-  // wkday = "Mon" | "Tue" | "Wed"
-  // | "Thu" | "Fri" | "Sat" | "Sun"
-  // month = "Jan" | "Feb" | "Mar" | "Apr"
-  // | "May" | "Jun" | "Jul" | "Aug"
-  // | "Sep" | "Oct" | "Nov" | "Dec"
-  //
-
-  const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-  const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-  /**
-* Processes a date and returns the encoded UTC time as a string according to
-* the format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toTime(date)
-  {
-    var hrs = date.getUTCHours();
-    var rv = (hrs < 10) ? "0" + hrs : hrs;
-
-    var mins = date.getUTCMinutes();
-    rv += ":";
-    rv += (mins < 10) ? "0" + mins : mins;
-
-    var secs = date.getUTCSeconds();
-    rv += ":";
-    rv += (secs < 10) ? "0" + secs : secs;
-
-    return rv;
-  }
-
-  /**
-* Processes a date and returns the encoded UTC date as a string according to
-* the date1 format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toDate1(date)
-  {
-    var day = date.getUTCDate();
-    var month = date.getUTCMonth();
-    var year = date.getUTCFullYear();
-
-    var rv = (day < 10) ? "0" + day : day;
-    rv += " " + monthStrings[month];
-    rv += " " + year;
-
-    return rv;
-  }
-
-  date = new Date(date);
-
-  const fmtString = "%wkday%, %date1% %time% GMT";
-  var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]);
-  rv = rv.replace("%time%", toTime(date));
-  return rv.replace("%date1%", toDate1(date));
-}
-
-/**
-* Prints out a human-readable representation of the object o and its fields,
-* omitting those whose names begin with "_" if showMembers != true (to ignore
-* "private" properties exposed via getters/setters).
-*/
-function printObj(o, showMembers)
-{
-  var s = "******************************\n";
-  s += "o = {\n";
-  for (var i in o)
-  {
-    if (typeof(i) != "string" ||
-        (showMembers || (i.length > 0 && i[0] != "_")))
-      s+= " " + i + ": " + o[i] + ",\n";
-  }
-  s += " };\n";
-  s += "******************************";
-  dumpn(s);
-}
-
-/**
-* Instantiates a new HTTP server.
-*/
-function nsHttpServer()
-{
-  if (!gThreadManager)
-    gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-
-  /** The port on which this server listens. */
-  this._port = undefined;
-
-  /** The socket associated with this. */
-  this._socket = null;
-
-  /** The handler used to process requests to this server. */
-  this._handler = new ServerHandler(this);
-
-  /** Naming information for this server. */
-  this._identity = new ServerIdentity();
-
-  /**
-* Indicates when the server is to be shut down at the end of the request.
-*/
-  this._doQuit = false;
-
-  /**
-* True if the socket in this is closed (and closure notifications have been
-* sent and processed if the socket was ever opened), false otherwise.
-*/
-  this._socketClosed = true;
-
-  /**
-* Used for tracking existing connections and ensuring that all connections
-* are properly cleaned up before server shutdown; increases by 1 for every
-* new incoming connection.
-*/
-  this._connectionGen = 0;
-
-  /**
-* Hash of all open connections, indexed by connection number at time of
-* creation.
-*/
-  this._connections = {};
-}
-nsHttpServer.prototype =
-{
-  classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"),
-
-  // NSISERVERSOCKETLISTENER
-
-  /**
-* Processes an incoming request coming in on the given socket and contained
-* in the given transport.
-*
-* @param socket : nsIServerSocket
-* the socket through which the request was served
-* @param trans : nsISocketTransport
-* the transport for the request/response
-* @see nsIServerSocketListener.onSocketAccepted
-*/
-  onSocketAccepted: function(socket, trans)
-  {
-    dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")");
-
-    dumpn(">>> new connection on " + trans.host + ":" + trans.port);
-
-    const SEGMENT_SIZE = 8192;
-    const SEGMENT_COUNT = 1024;
-    try
-    {
-      var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
-                       .QueryInterface(Ci.nsIAsyncInputStream);
-      var output = trans.openOutputStream(0, 0, 0);
-    }
-    catch (e)
-    {
-      dumpn("*** error opening transport streams: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    var connectionNumber = ++this._connectionGen;
-
-    try
-    {
-      var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
-      var reader = new RequestReader(conn);
-
-      // XXX add request timeout functionality here!
-
-      // Note: must use main thread here, or we might get a GC that will cause
-      // threadsafety assertions. We really need to fix XPConnect so that
-      // you can actually do things in multi-threaded JS. :-(
-      input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
-    }
-    catch (e)
-    {
-      // Assume this connection can't be salvaged and bail on it completely;
-      // don't attempt to close it so that we can assert that any connection
-      // being closed is in this._connections.
-      dumpn("*** error in initial request-processing stages: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    this._connections[connectionNumber] = conn;
-    dumpn("*** starting connection " + connectionNumber);
-  },
-
-  /**
-* Called when the socket associated with this is closed.
-*
-* @param socket : nsIServerSocket
-* the socket being closed
-* @param status : nsresult
-* the reason the socket stopped listening (NS_BINDING_ABORTED if the server
-* was stopped using nsIHttpServer.stop)
-* @see nsIServerSocketListener.onStopListening
-*/
-  onStopListening: function(socket, status)
-  {
-    dumpn(">>> shutting down server on port " + socket.port);
-    this._socketClosed = true;
-    if (!this._hasOpenConnections())
-    {
-      dumpn("*** no open connections, notifying async from onStopListening");
-
-      // Notify asynchronously so that any pending teardown in stop() has a
-      // chance to run first.
-      var self = this;
-      var stopEvent =
-        {
-          run: function()
-          {
-            dumpn("*** _notifyStopped async callback");
-            self._notifyStopped();
-          }
-        };
-      gThreadManager.dispatchToMainThread(stopEvent);
-    }
-  },
-
-  // NSIHTTPSERVER
-
-  //
-  // see nsIHttpServer.start
-  //
-  start: function(port)
-  {
-    this._start(port, "localhost")
-  },
-
-  _start: function(port, host)
-  {
-    if (this._socket)
-      throw Cr.NS_ERROR_ALREADY_INITIALIZED;
-
-    this._port = port;
-    this._doQuit = this._socketClosed = false;
-
-    this._host = host;
-
-    // The listen queue needs to be long enough to handle
-    // network.http.max-persistent-connections-per-server concurrent connections,
-    // plus a safety margin in case some other process is talking to
-    // the server as well.
-    var prefs = getRootPrefBranch();
-    var maxConnections;
-    try {
-      // Bug 776860: The original pref was removed in favor of this new one:
-      maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server") + 5;
-    }
-    catch(e) {
-      maxConnections = prefs.getIntPref("network.http.max-connections-per-server") + 5;
-    }
-
-    try
-    {
-      var loopback = true;
-      if (this._host != "127.0.0.1" && this._host != "localhost") {
-        var loopback = false;
-      }
-
-      var socket = new ServerSocket(this._port,
-                                    loopback, // true = localhost, false = everybody
-                                    maxConnections);
-      dumpn(">>> listening on port " + socket.port + ", " + maxConnections +
-            " pending connections");
-      socket.asyncListen(this);
-      this._identity._initialize(socket.port, host, true);
-      this._socket = socket;
-    }
-    catch (e)
-    {
-      dumpn("!!! could not start server on port " + port + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-  },
-
-  //
-  // see nsIHttpServer.stop
-  //
-  stop: function(callback)
-  {
-    if (!callback)
-      throw Cr.NS_ERROR_NULL_POINTER;
-    if (!this._socket)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    this._stopCallback = typeof callback === "function"
-                       ? callback
-                       : function() { callback.onStopped(); };
-
-    dumpn(">>> stopping listening on port " + this._socket.port);
-    this._socket.close();
-    this._socket = null;
-
-    // We can't have this identity any more, and the port on which we're running
-    // this server now could be meaningless the next time around.
-    this._identity._teardown();
-
-    this._doQuit = false;
-
-    // socket-close notification and pending request completion happen async
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (file && (!file.exists() || file.isDirectory()))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handler.registerFile(path, file);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/" ||
-        path.charAt(path.length - 1) != "/" ||
-        (directory &&
-         (!directory.exists() || !directory.isDirectory())))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping
-    // exists!
-
-    this._handler.registerDirectory(path, directory);
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    this._handler.registerPathHandler(path, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    this._handler.registerPrefixHandler(prefix, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(code, handler)
-  {
-    this._handler.registerErrorHandler(code, handler);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    this._handler.setIndexHandler(handler);
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    this._handler.registerContentType(ext, type);
-  },
-
-  //
-  // see nsIHttpServer.serverIdentity
-  //
-  get identity()
-  {
-    return this._identity;
-  },
-
-  //
-  // see nsIHttpServer.getState
-  //
-  getState: function(path, k)
-  {
-    return this._handler._getState(path, k);
-  },
-
-  //
-  // see nsIHttpServer.setState
-  //
-  setState: function(path, k, v)
-  {
-    return this._handler._setState(path, k, v);
-  },
-
-  //
-  // see nsIHttpServer.getSharedState
-  //
-  getSharedState: function(k)
-  {
-    return this._handler._getSharedState(k);
-  },
-
-  //
-  // see nsIHttpServer.setSharedState
-  //
-  setSharedState: function(k, v)
-  {
-    return this._handler._setSharedState(k, v);
-  },
-
-  //
-  // see nsIHttpServer.getObjectState
-  //
-  getObjectState: function(k)
-  {
-    return this._handler._getObjectState(k);
-  },
-
-  //
-  // see nsIHttpServer.setObjectState
-  //
-  setObjectState: function(k, v)
-  {
-    return this._handler._setObjectState(k, v);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NON-XPCOM PUBLIC API
-
-  /**
-* Returns true iff this server is not running (and is not in the process of
-* serving any requests still to be processed when the server was last
-* stopped after being run).
-*/
-  isStopped: function()
-  {
-    return this._socketClosed && !this._hasOpenConnections();
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /** True if this server has any open connections to it, false otherwise. */
-  _hasOpenConnections: function()
-  {
-    //
-    // If we have any open connections, they're tracked as numeric properties on
-    // |this._connections|. The non-standard __count__ property could be used
-    // to check whether there are any properties, but standard-wise, even
-    // looking forward to ES5, there's no less ugly yet still O(1) way to do
-    // this.
-    //
-    for (var n in this._connections)
-      return true;
-    return false;
-  },
-
-  /** Calls the server-stopped callback provided when stop() was called. */
-  _notifyStopped: function()
-  {
-    NS_ASSERT(this._stopCallback !== null, "double-notifying?");
-    NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now");
-
-    //
-    // NB: We have to grab this now, null out the member, *then* call the
-    // callback here, or otherwise the callback could (indirectly) futz with
-    // this._stopCallback by starting and immediately stopping this, at
-    // which point we'd be nulling out a field we no longer have a right to
-    // modify.
-    //
-    var callback = this._stopCallback;
-    this._stopCallback = null;
-    try
-    {
-      callback();
-    }
-    catch (e)
-    {
-      // not throwing because this is specified as being usually (but not
-      // always) asynchronous
-      dump("!!! error running onStopped callback: " + e + "\n");
-    }
-  },
-
-  /**
-* Notifies this server that the given connection has been closed.
-*
-* @param connection : Connection
-* the connection that was closed
-*/
-  _connectionClosed: function(connection)
-  {
-    NS_ASSERT(connection.number in this._connections,
-              "closing a connection " + this + " that we never added to the " +
-              "set of open connections?");
-    NS_ASSERT(this._connections[connection.number] === connection,
-              "connection number mismatch? " +
-              this._connections[connection.number]);
-    delete this._connections[connection.number];
-
-    // Fire a pending server-stopped notification if it's our responsibility.
-    if (!this._hasOpenConnections() && this._socketClosed)
-      this._notifyStopped();
-  },
-
-  /**
-* Requests that the server be shut down when possible.
-*/
-  _requestQuit: function()
-  {
-    dumpn(">>> requesting a quit");
-    dumpStack();
-    this._doQuit = true;
-  }
-};
-
-
-//
-// RFC 2396 section 3.2.2:
-//
-// host = hostname | IPv4address
-// hostname = *( domainlabel "." ) toplabel [ "." ]
-// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-//
-
-const HOST_REGEX =
-  new RegExp("^(?:" +
-               // *( domainlabel "." )
-               "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
-               // toplabel
-               "[a-z](?:[a-z0-9-]*[a-z0-9])?" +
-             "|" +
-               // IPv4 address
-               "\\d+\\.\\d+\\.\\d+\\.\\d+" +
-             ")$",
-             "i");
-
-
-/**
-* Represents the identity of a server. An identity consists of a set of
-* (scheme, host, port) tuples denoted as locations (allowing a single server to
-* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any
-* host/port). Any incoming request must be to one of these locations, or it
-* will be rejected with an HTTP 400 error. One location, denoted as the
-* primary location, is the location assigned in contexts where a location
-* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests.
-*
-* A single identity may contain at most one location per unique host/port pair;
-* other than that, no restrictions are placed upon what locations may
-* constitute an identity.
-*/
-function ServerIdentity()
-{
-  /** The scheme of the primary location. */
-  this._primaryScheme = "http";
-
-  /** The hostname of the primary location. */
-  this._primaryHost = "127.0.0.1"
-
-  /** The port number of the primary location. */
-  this._primaryPort = -1;
-
-  /**
-* The current port number for the corresponding server, stored so that a new
-* primary location can always be set if the current one is removed.
-*/
-  this._defaultPort = -1;
-
-  /**
-* Maps hosts to maps of ports to schemes, e.g. the following would represent
-* https://example.com:789/ and http://example.org/:
-*
-* {
-* "xexample.com": { 789: "https" },
-* "xexample.org": { 80: "http" }
-* }
-*
-* Note the "x" prefix on hostnames, which prevents collisions with special
-* JS names like "prototype".
-*/
-  this._locations = { "xlocalhost": {} };
-}
-ServerIdentity.prototype =
-{
-  // NSIHTTPSERVERIDENTITY
-
-  //
-  // see nsIHttpServerIdentity.primaryScheme
-  //
-  get primaryScheme()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryScheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryHost
-  //
-  get primaryHost()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryHost;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryPort
-  //
-  get primaryPort()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryPort;
-  },
-
-  //
-  // see nsIHttpServerIdentity.add
-  //
-  add: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      this._locations["x" + host] = entry = {};
-
-    entry[port] = scheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.remove
-  //
-  remove: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return false;
-
-    var present = port in entry;
-    delete entry[port];
-
-    if (this._primaryScheme == scheme &&
-        this._primaryHost == host &&
-        this._primaryPort == port &&
-        this._defaultPort !== -1)
-    {
-      // Always keep at least one identity in existence at any time, unless
-      // we're in the process of shutting down (the last condition above).
-      this._primaryPort = -1;
-      this._initialize(this._defaultPort, host, false);
-    }
-
-    return present;
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  has: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    return "x" + host in this._locations &&
-           scheme === this._locations["x" + host][port];
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  getScheme: function(host, port)
-  {
-    this._validate("http", host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return "";
-
-    return entry[port] || "";
-  },
-
-  //
-  // see nsIHttpServerIdentity.setPrimary
-  //
-  setPrimary: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    this.add(scheme, host, port);
-
-    this._primaryScheme = scheme;
-    this._primaryHost = host;
-    this._primaryPort = port;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Initializes the primary name for the corresponding server, based on the
-* provided port number.
-*/
-  _initialize: function(port, host, addSecondaryDefault)
-  {
-    this._host = host;
-    if (this._primaryPort !== -1)
-      this.add("http", host, port);
-    else
-      this.setPrimary("http", "localhost", port);
-    this._defaultPort = port;
-
-    // Only add this if we're being called at server startup
-    if (addSecondaryDefault && host != "127.0.0.1")
-      this.add("http", "127.0.0.1", port);
-  },
-
-  /**
-* Called at server shutdown time, unsets the primary location only if it was
-* the default-assigned location and removes the default location from the
-* set of locations used.
-*/
-  _teardown: function()
-  {
-    if (this._host != "127.0.0.1") {
-      // Not the default primary location, nothing special to do here
-      this.remove("http", "127.0.0.1", this._defaultPort);
-    }
-
-    // This is a *very* tricky bit of reasoning here; make absolutely sure the
-    // tests for this code pass before you commit changes to it.
-    if (this._primaryScheme == "http" &&
-        this._primaryHost == this._host &&
-        this._primaryPort == this._defaultPort)
-    {
-      // Make sure we don't trigger the readding logic in .remove(), then remove
-      // the default location.
-      var port = this._defaultPort;
-      this._defaultPort = -1;
-      this.remove("http", this._host, port);
-
-      // Ensure a server start triggers the setPrimary() path in ._initialize()
-      this._primaryPort = -1;
-    }
-    else
-    {
-      // No reason not to remove directly as it's not our primary location
-      this.remove("http", this._host, this._defaultPort);
-    }
-  },
-
-  /**
-* Ensures scheme, host, and port are all valid with respect to RFC 2396.
-*
-* @throws NS_ERROR_ILLEGAL_VALUE
-* if any argument doesn't match the corresponding production
-*/
-  _validate: function(scheme, host, port)
-  {
-    if (scheme !== "http" && scheme !== "https")
-    {
-      dumpn("*** server only supports http/https schemes: '" + scheme + "'");
-      dumpStack();
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (!HOST_REGEX.test(host))
-    {
-      dumpn("*** unexpected host: '" + host + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (port < 0 || port > 65535)
-    {
-      dumpn("*** unexpected port: '" + port + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-  }
-};
-
-
-/**
-* Represents a connection to the server (and possibly in the future the thread
-* on which the connection is processed).
-*
-* @param input : nsIInputStream
-* stream from which incoming data on the connection is read
-* @param output : nsIOutputStream
-* stream to write data out the connection
-* @param server : nsHttpServer
-* the server handling the connection
-* @param port : int
-* the port on which the server is running
-* @param outgoingPort : int
-* the outgoing port used by this connection
-* @param number : uint
-* a serial number used to uniquely identify this connection
-*/
-function Connection(input, output, server, port, outgoingPort, number)
-{
-  dumpn("*** opening new connection " + number + " on port " + outgoingPort);
-
-  /** Stream of incoming data. */
-  this.input = input;
-
-  /** Stream for outgoing data. */
-  this.output = output;
-
-  /** The server associated with this request. */
-  this.server = server;
-
-  /** The port on which the server is running. */
-  this.port = port;
-
-  /** The outgoing poort used by this connection. */
-  this._outgoingPort = outgoingPort;
-
-  /** The serial number of this connection. */
-  this.number = number;
-
-  /**
-* The request for which a response is being generated, null if the
-* incoming request has not been fully received or if it had errors.
-*/
-  this.request = null;
-
-  /** State variables for debugging. */
-  this._closed = this._processed = false;
-}
-Connection.prototype =
-{
-  /** Closes this connection's input/output streams. */
-  close: function()
-  {
-    dumpn("*** closing connection " + this.number +
-          " on port " + this._outgoingPort);
-
-    this.input.close();
-    this.output.close();
-    this._closed = true;
-
-    var server = this.server;
-    server._connectionClosed(this);
-
-    // If an error triggered a server shutdown, act on it now
-    if (server._doQuit)
-      server.stop(function() { /* not like we can do anything better */ });
-  },
-
-  /**
-* Initiates processing of this connection, using the data in the given
-* request.
-*
-* @param request : Request
-* the request which should be processed
-*/
-  process: function(request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-
-    this.request = request;
-    this.server._handler.handleResponse(this);
-  },
-
-  /**
-* Initiates processing of this connection, generating a response with the
-* given HTTP error code.
-*
-* @param code : uint
-* an HTTP code, so in the range [0, 1000)
-* @param request : Request
-* incomplete data about the incoming request (since there were errors
-* during its processing
-*/
-  processError: function(code, request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-    this.request = request;
-    this.server._handler.handleError(code, this);
-  },
-
-  /** Converts this to a string for debugging purposes. */
-  toString: function()
-  {
-    return "<Connection(" + this.number +
-           (this.request ? ", " + this.request.path : "") +"): " +
-           (this._closed ? "closed" : "open") + ">";
-  }
-};
-
-
-
-/** Returns an array of count bytes from the given input stream. */
-function readBytes(inputStream, count)
-{
-  return new BinaryInputStream(inputStream).readByteArray(count);
-}
-
-
-
-/** Request reader processing states; see RequestReader for details. */
-const READER_IN_REQUEST_LINE = 0;
-const READER_IN_HEADERS = 1;
-const READER_IN_BODY = 2;
-const READER_FINISHED = 3;
-
-
-/**
-* Reads incoming request data asynchronously, does any necessary preprocessing,
-* and forwards it to the request handler. Processing occurs in three states:
-*
-* READER_IN_REQUEST_LINE Reading the request's status line
-* READER_IN_HEADERS Reading headers in the request
-* READER_IN_BODY Reading the body of the request
-* READER_FINISHED Entire request has been read and processed
-*
-* During the first two stages, initial metadata about the request is gathered
-* into a Request object. Once the status line and headers have been processed,
-* we start processing the body of the request into the Request. Finally, when
-* the entire body has been read, we create a Response and hand it off to the
-* ServerHandler to be given to the appropriate request handler.
-*
-* @param connection : Connection
-* the connection for the request being read
-*/
-function RequestReader(connection)
-{
-  /** Connection metadata for this request. */
-  this._connection = connection;
-
-  /**
-* A container providing line-by-line access to the raw bytes that make up the
-* data which has been read from the connection but has not yet been acted
-* upon (by passing it to the request handler or by extracting request
-* metadata from it).
-*/
-  this._data = new LineData();
-
-  /**
-* The amount of data remaining to be read from the body of this request.
-* After all headers in the request have been read this is the value in the
-* Content-Length header, but as the body is read its value decreases to zero.
-*/
-  this._contentLength = 0;
-
-  /** The current state of parsing the incoming request. */
-  this._state = READER_IN_REQUEST_LINE;
-
-  /** Metadata constructed from the incoming request for the request handler. */
-  this._metadata = new Request(connection.port);
-
-  /**
-* Used to preserve state if we run out of line data midway through a
-* multi-line header. _lastHeaderName stores the name of the header, while
-* _lastHeaderValue stores the value we've seen so far for the header.
-*
-* These fields are always either both undefined or both strings.
-*/
-  this._lastHeaderName = this._lastHeaderValue = undefined;
-}
-RequestReader.prototype =
-{
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Called when more data from the incoming request is available. This method
-* then reads the available data from input and deals with that data as
-* necessary, depending upon the syntax of already-downloaded data.
-*
-* @param input : nsIAsyncInputStream
-* the stream of incoming data from the connection
-*/
-  onInputStreamReady: function(input)
-  {
-    dumpn("*** onInputStreamReady(input=" + input + ") on thread " +
-          gThreadManager.currentThread + " (main is " +
-          gThreadManager.mainThread + ")");
-    dumpn("*** this._state == " + this._state);
-
-    // Handle cases where we get more data after a request error has been
-    // discovered but *before* we can close the connection.
-    var data = this._data;
-    if (!data)
-      return;
-
-    try
-    {
-      data.appendBytes(readBytes(input, input.available()));
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** WARNING: unexpected error when reading from socket; will " +
-              "be treated as if the input stream had been closed");
-        dumpn("*** WARNING: actual error was: " + e);
-      }
-
-      // We've lost a race -- input has been closed, but we're still expecting
-      // to read more data. available() will throw in this case, and since
-      // we're dead in the water now, destroy the connection.
-      dumpn("*** onInputStreamReady called on a closed input, destroying " +
-            "connection");
-      this._connection.close();
-      return;
-    }
-
-    switch (this._state)
-    {
-      default:
-        NS_ASSERT(false, "invalid state: " + this._state);
-        break;
-
-      case READER_IN_REQUEST_LINE:
-        if (!this._processRequestLine())
-          break;
-        /* fall through */
-
-      case READER_IN_HEADERS:
-        if (!this._processHeaders())
-          break;
-        /* fall through */
-
-      case READER_IN_BODY:
-        this._processBody();
-    }
-
-    if (this._state != READER_FINISHED)
-      input.asyncWait(this, 0, 0, gThreadManager.currentThread);
-  },
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(aIID)
-  {
-    if (aIID.equals(Ci.nsIInputStreamCallback) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE API
-
-  /**
-* Processes unprocessed, downloaded data as a request line.
-*
-* @returns boolean
-* true iff the request line has been fully processed
-*/
-  _processRequestLine: function()
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    // Servers SHOULD ignore any empty line(s) received where a Request-Line
-    // is expected (section 4.1).
-    var data = this._data;
-    var line = {};
-    var readSuccess;
-    while ((readSuccess = data.readLine(line)) && line.value == "")
-      dumpn("*** ignoring beginning blank line...");
-
-    // if we don't have a full line, wait until we do
-    if (!readSuccess)
-      return false;
-
-    // we have the first non-blank line
-    try
-    {
-      this._parseRequestLine(line.value);
-      this._state = READER_IN_HEADERS;
-      return true;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing request headers.
-*
-* @returns boolean
-* true iff header data in the request has been fully processed
-*/
-  _processHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    // XXX things to fix here:
-    //
-    // - need to support RFC 2047-encoded non-US-ASCII characters
-
-    try
-    {
-      var done = this._parseHeaders();
-      if (done)
-      {
-        var request = this._metadata;
-
-        // XXX this is wrong for requests with transfer-encodings applied to
-        // them, particularly chunked (which by its nature can have no
-        // meaningful Content-Length header)!
-        this._contentLength = request.hasHeader("Content-Length")
-                            ? parseInt(request.getHeader("Content-Length"), 10)
-                            : 0;
-        dumpn("_processHeaders, Content-length=" + this._contentLength);
-
-        this._state = READER_IN_BODY;
-      }
-      return done;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing the request body.
-*
-* @returns boolean
-* true iff the request body has been fully processed
-*/
-  _processBody: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    // XXX handle chunked transfer-coding request bodies!
-
-    try
-    {
-      if (this._contentLength > 0)
-      {
-        var data = this._data.purge();
-        var count = Math.min(data.length, this._contentLength);
-        dumpn("*** loading data=" + data + " len=" + data.length +
-              " excess=" + (data.length - count));
-
-        var bos = new BinaryOutputStream(this._metadata._bodyOutputStream);
-        bos.writeByteArray(data, count);
-        this._contentLength -= count;
-      }
-
-      dumpn("*** remaining body data len=" + this._contentLength);
-      if (this._contentLength == 0)
-      {
-        this._validateRequest();
-        this._state = READER_FINISHED;
-        this._handleResponse();
-        return true;
-      }
-
-      return false;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Does various post-header checks on the data in this request.
-*
-* @throws : HttpError
-* if the request was malformed in some way
-*/
-  _validateRequest: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    dumpn("*** _validateRequest");
-
-    var metadata = this._metadata;
-    var headers = metadata._headers;
-
-    // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header
-    var identity = this._connection.server.identity;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-    {
-      if (!headers.hasHeader("Host"))
-      {
-        dumpn("*** malformed HTTP/1.1 or greater request with no Host header!");
-        throw HTTP_400;
-      }
-
-      // If the Request-URI wasn't absolute, then we need to determine our host.
-      // We have to determine what scheme was used to access us based on the
-      // server identity data at this point, because the request just doesn't
-      // contain enough data on its own to do this, sadly.
-      if (!metadata._host)
-      {
-        var host, port;
-        var hostPort = headers.getHeader("Host");
-        var colon = hostPort.indexOf(":");
-        if (colon < 0)
-        {
-          host = hostPort;
-          port = "";
-        }
-        else
-        {
-          host = hostPort.substring(0, colon);
-          port = hostPort.substring(colon + 1);
-        }
-
-        // NB: We allow an empty port here because, oddly, a colon may be
-        // present even without a port number, e.g. "example.com:"; in this
-        // case the default port applies.
-        if (!HOST_REGEX.test(host) || !/^\d*$/.test(port))
-        {
-          dumpn("*** malformed hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        // If we're not given a port, we're stuck, because we don't know what
-        // scheme to use to look up the correct port here, in general. Since
-        // the HTTPS case requires a tunnel/proxy and thus requires that the
-        // requested URI be absolute (and thus contain the necessary
-        // information), let's assume HTTP will prevail and use that.
-        port = +port || 80;
-
-        var scheme = identity.getScheme(host, port);
-        if (!scheme)
-        {
-          dumpn("*** unrecognized hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        metadata._scheme = scheme;
-        metadata._host = host;
-        metadata._port = port;
-      }
-    }
-    else
-    {
-      NS_ASSERT(metadata._host === undefined,
-                "HTTP/1.0 doesn't allow absolute paths in the request line!");
-
-      metadata._scheme = identity.primaryScheme;
-      metadata._host = identity.primaryHost;
-      metadata._port = identity.primaryPort;
-    }
-
-    NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port),
-              "must have a location we recognize by now!");
-  },
-
-  /**
-* Handles responses in case of error, either in the server or in the request.
-*
-* @param e
-* the specific error encountered, which is an HttpError in the case where
-* the request is in some way invalid or cannot be fulfilled; if this isn't
-* an HttpError we're going to be paranoid and shut down, because that
-* shouldn't happen, ever
-*/
-  _handleError: function(e)
-  {
-    // Don't fall back into normal processing!
-    this._state = READER_FINISHED;
-
-    var server = this._connection.server;
-    if (e instanceof HttpError)
-    {
-      var code = e.code;
-    }
-    else
-    {
-      dumpn("!!! UNEXPECTED ERROR: " + e +
-            (e.lineNumber ? ", line " + e.lineNumber : ""));
-
-      // no idea what happened -- be paranoid and shut down
-      code = 500;
-      server._requestQuit();
-    }
-
-    // make attempted reuse of data an error
-    this._data = null;
-
-    this._connection.processError(code, this._metadata);
-  },
-
-  /**
-* Now that we've read the request line and headers, we can actually hand off
-* the request to be handled.
-*
-* This method is called once per request, after the request line and all
-* headers and the body, if any, have been received.
-*/
-  _handleResponse: function()
-  {
-    NS_ASSERT(this._state == READER_FINISHED);
-
-    // We don't need the line-based data any more, so make attempted reuse an
-    // error.
-    this._data = null;
-
-    this._connection.process(this._metadata);
-  },
-
-
-  // PARSING
-
-  /**
-* Parses the request line for the HTTP request associated with this.
-*
-* @param line : string
-* the request line
-*/
-  _parseRequestLine: function(line)
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    dumpn("*** _parseRequestLine('" + line + "')");
-
-    var metadata = this._metadata;
-
-    // clients and servers SHOULD accept any amount of SP or HT characters
-    // between fields, even though only a single SP is required (section 19.3)
-    var request = line.split(/[ \t]+/);
-    if (!request || request.length != 3)
-      throw HTTP_400;
-
-    metadata._method = request[0];
-
-    // get the HTTP version
-    var ver = request[2];
-    var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
-    if (!match)
-      throw HTTP_400;
-
-    // determine HTTP version
-    try
-    {
-      metadata._httpVersion = new nsHttpVersion(match[1]);
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
-        throw "unsupported HTTP version";
-    }
-    catch (e)
-    {
-      // we support HTTP/1.0 and HTTP/1.1 only
-      throw HTTP_501;
-    }
-
-
-    var fullPath = request[1];
-    var serverIdentity = this._connection.server.identity;
-
-    var scheme, host, port;
-
-    if (fullPath.charAt(0) != "/")
-    {
-      // No absolute paths in the request line in HTTP prior to 1.1
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-        throw HTTP_400;
-
-      try
-      {
-        var uri = Cc["@mozilla.org/network/io-service;1"]
-                    .getService(Ci.nsIIOService)
-                    .newURI(fullPath);
-        fullPath = uri.pathQueryRef;
-        scheme = uri.scheme;
-        host = metadata._host = uri.asciiHost;
-        port = uri.port;
-        if (port === -1)
-        {
-          if (scheme === "http")
-            port = 80;
-          else if (scheme === "https")
-            port = 443;
-          else
-            throw HTTP_400;
-        }
-      }
-      catch (e)
-      {
-        // If the host is not a valid host on the server, the response MUST be a
-        // 400 (Bad Request) error message (section 5.2). Alternately, the URI
-        // is malformed.
-        throw HTTP_400;
-      }
-
-      if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
-        throw HTTP_400;
-    }
-
-    var splitter = fullPath.indexOf("?");
-    if (splitter < 0)
-    {
-      // _queryString already set in ctor
-      metadata._path = fullPath;
-    }
-    else
-    {
-      metadata._path = fullPath.substring(0, splitter);
-      metadata._queryString = fullPath.substring(splitter + 1);
-    }
-
-    metadata._scheme = scheme;
-    metadata._host = host;
-    metadata._port = port;
-  },
-
-  /**
-* Parses all available HTTP headers in this until the header-ending CRLFCRLF,
-* adding them to the store of headers in the request.
-*
-* @throws
-* HTTP_400 if the headers are malformed
-* @returns boolean
-* true if all headers have now been processed, false otherwise
-*/
-  _parseHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    dumpn("*** _parseHeaders");
-
-    var data = this._data;
-
-    var headers = this._metadata._headers;
-    var lastName = this._lastHeaderName;
-    var lastVal = this._lastHeaderValue;
-
-    var line = {};
-    while (true)
-    {
-      NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
-                lastName === undefined ?
-                  "lastVal without lastName? lastVal: '" + lastVal + "'" :
-                  "lastName without lastVal? lastName: '" + lastName + "'");
-
-      if (!data.readLine(line))
-      {
-        // save any data we have from the header we might still be processing
-        this._lastHeaderName = lastName;
-        this._lastHeaderValue = lastVal;
-        return false;
-      }
-
-      var lineText = line.value;
-      var firstChar = lineText.charAt(0);
-
-      // blank line means end of headers
-      if (lineText == "")
-      {
-        // we're finished with the previous header
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-        else
-        {
-          // no headers in request -- valid for HTTP/1.0 requests
-        }
-
-        // either way, we're done processing headers
-        this._state = READER_IN_BODY;
-        return true;
-      }
-      else if (firstChar == " " || firstChar == "\t")
-      {
-        // multi-line header if we've already seen a header line
-        if (!lastName)
-        {
-          // we don't have a header to continue!
-          throw HTTP_400;
-        }
-
-        // append this line's text to the value; starts with SP/HT, so no need
-        // for separating whitespace
-        lastVal += lineText;
-      }
-      else
-      {
-        // we have a new header, so set the old one (if one existed)
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-
-        var colon = lineText.indexOf(":"); // first colon must be splitter
-        if (colon < 1)
-        {
-          // no colon or missing header field-name
-          throw HTTP_400;
-        }
-
-        // set header name, value (to be set in the next loop, usually)
-        lastName = lineText.substring(0, colon);
-        lastVal = lineText.substring(colon + 1);
-      } // empty, continuation, start of header
-    } // while (true)
-  }
-};
-
-
-/** The character codes for CR and LF. */
-const CR = 0x0D, LF = 0x0A;
-
-/**
-* Calculates the number of characters before the first CRLF pair in array, or
-* -1 if the array contains no CRLF pair.
-*
-* @param array : Array
-* an array of numbers in the range [0, 256), each representing a single
-* character; the first CRLF is the lowest index i where
-* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|,
-* if such an |i| exists, and -1 otherwise
-* @returns int
-* the index of the first CRLF if any were present, -1 otherwise
-*/
-function findCRLF(array)
-{
-  for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1))
-  {
-    if (array[i + 1] == LF)
-      return i;
-  }
-  return -1;
-}
-
-
-/**
-* A container which provides line-by-line access to the arrays of bytes with
-* which it is seeded.
-*/
-function LineData()
-{
-  /** An array of queued bytes from which to get line-based characters. */
-  this._data = [];
-}
-LineData.prototype =
-{
-  /**
-* Appends the bytes in the given array to the internal data cache maintained
-* by this.
-*/
-  appendBytes: function(bytes)
-  {
-    Array.prototype.push.apply(this._data, bytes);
-  },
-
-  /**
-* Removes and returns a line of data, delimited by CRLF, from this.
-*
-* @param out
-* an object whose "value" property will be set to the first line of text
-* present in this, sans CRLF, if this contains a full CRLF-delimited line
-* of text; if this doesn't contain enough data, the value of the property
-* is undefined
-* @returns boolean
-* true if a full line of data could be read from the data in this, false
-* otherwise
-*/
-  readLine: function(out)
-  {
-    var data = this._data;
-    var length = findCRLF(data);
-    if (length < 0)
-      return false;
-
-    //
-    // We have the index of the CR, so remove all the characters, including
-    // CRLF, from the array with splice, and convert the removed array into the
-    // corresponding string, from which we then strip the trailing CRLF.
-    //
-    // Getting the line in this matter acknowledges that substring is an O(1)
-    // operation in SpiderMonkey because strings are immutable, whereas two
-    // splices, both from the beginning of the data, are less likely to be as
-    // cheap as a single splice plus two extra character conversions.
-    //
-    var line = String.fromCharCode.apply(null, data.splice(0, length + 2));
-    out.value = line.substring(0, length);
-
-    return true;
-  },
-
-  /**
-* Removes the bytes currently within this and returns them in an array.
-*
-* @returns Array
-* the bytes within this when this method is called
-*/
-  purge: function()
-  {
-    var data = this._data;
-    this._data = [];
-    return data;
-  }
-};
-
-
-
-/**
-* Creates a request-handling function for an nsIHttpRequestHandler object.
-*/
-function createHandlerFunc(handler)
-{
-  return function(metadata, response) { handler.handle(metadata, response); };
-}
-
-
-/**
-* The default handler for directories; writes an HTML response containing a
-* slightly-formatted directory listing.
-*/
-function defaultIndexHandler(metadata, response)
-{
-  response.setHeader("Content-Type", "text/html", false);
-
-  var path = htmlEscape(decodeURI(metadata.path));
-
-  //
-  // Just do a very basic bit of directory listings -- no need for too much
-  // fanciness, especially since we don't have a style sheet in which we can
-  // stick rules (don't want to pollute the default path-space).
-  //
-
-  var body = '<html>\
-<head>\
-<title>' + path + '</title>\
-</head>\
-<body>\
-<h1>' + path + '</h1>\
-<ol style="list-style-type: none">';
-
-  var directory = metadata.getProperty("directory").QueryInterface(Ci.nsIFile);
-  NS_ASSERT(directory && directory.isDirectory());
-
-  var fileList = [];
-  var files = directory.directoryEntries;
-  while (files.hasMoreElements())
-  {
-    var f = files.getNext().QueryInterface(Ci.nsIFile);
-    var name = f.leafName;
-    if (!f.isHidden() &&
-        (name.charAt(name.length - 1) != HIDDEN_CHAR ||
-         name.charAt(name.length - 2) == HIDDEN_CHAR))
-      fileList.push(f);
-  }
-
-  fileList.sort(fileSort);
-
-  for (var i = 0; i < fileList.length; i++)
-  {
-    var file = fileList[i];
-    try
-    {
-      var name = file.leafName;
-      if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-        name = name.substring(0, name.length - 1);
-      var sep = file.isDirectory() ? "/" : "";
-
-      // Note: using " to delimit the attribute here because encodeURIComponent
-      // passes through '.
-      var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' +
-                   htmlEscape(name) + sep +
-                 '</a></li>';
-
-      body += item;
-    }
-    catch (e) { /* some file system error, ignore the file */ }
-  }
-
-  body += ' </ol>\
-</body>\
-</html>';
-
-  response.bodyOutputStream.write(body, body.length);
-}
-
-/**
-* Sorts a and b (nsIFile objects) into an aesthetically pleasing order.
-*/
-function fileSort(a, b)
-{
-  var dira = a.isDirectory(), dirb = b.isDirectory();
-
-  if (dira && !dirb)
-    return -1;
-  if (dirb && !dira)
-    return 1;
-
-  var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase();
-  return nameb > namea ? -1 : 1;
-}
-
-
-/**
-* Converts an externally-provided path into an internal path for use in
-* determining file mappings.
-*
-* @param path
-* the path to convert
-* @param encoded
-* true if the given path should be passed through decodeURI prior to
-* conversion
-* @throws URIError
-* if path is incorrectly encoded
-*/
-function toInternalPath(path, encoded)
-{
-  if (encoded)
-    path = decodeURI(path);
-
-  var comps = path.split("/");
-  for (var i = 0, sz = comps.length; i < sz; i++)
-  {
-    var comp = comps[i];
-    if (comp.charAt(comp.length - 1) == HIDDEN_CHAR)
-      comps[i] = comp + HIDDEN_CHAR;
-  }
-  return comps.join("/");
-}
-
-
-/**
-* Adds custom-specified headers for the given file to the given response, if
-* any such headers are specified.
-*
-* @param file
-* the file on the disk which is to be written
-* @param metadata
-* metadata about the incoming request
-* @param response
-* the Response to which any specified headers/data should be written
-* @throws HTTP_500
-* if an error occurred while processing custom-specified headers
-*/
-function maybeAddHeaders(file, metadata, response)
-{
-  var name = file.leafName;
-  if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-    name = name.substring(0, name.length - 1);
-
-  var headerFile = file.parent;
-  headerFile.append(name + HEADERS_SUFFIX);
-
-  if (!headerFile.exists())
-    return;
-
-  const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(headerFile, PR_RDONLY, 0o444,
-                                Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-  try
-  {
-    var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0);
-    lis.QueryInterface(Ci.nsIUnicharLineInputStream);
-
-    var line = {value: ""};
-    var more = lis.readLine(line);
-
-    if (!more && line.value == "")
-      return;
-
-
-    // request line
-
-    var status = line.value;
-    if (status.indexOf("HTTP ") == 0)
-    {
-      status = status.substring(5);
-      var space = status.indexOf(" ");
-      var code, description;
-      if (space < 0)
-      {
-        code = status;
-        description = "";
-      }
-      else
-      {
-        code = status.substring(0, space);
-        description = status.substring(space + 1, status.length);
-      }
-
-      response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description);
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-
-    // headers
-    while (more || line.value != "")
-    {
-      var header = line.value;
-      var colon = header.indexOf(":");
-
-      response.setHeader(header.substring(0, colon),
-                         header.substring(colon + 1, header.length),
-                         false); // allow overriding server-set headers
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-  }
-  catch (e)
-  {
-    dumpn("WARNING: error in headers for " + metadata.path + ": " + e);
-    throw HTTP_500;
-  }
-  finally
-  {
-    fis.close();
-  }
-}
-
-
-/**
-* An object which handles requests for a server, executing default and
-* overridden behaviors as instructed by the code which uses and manipulates it.
-* Default behavior includes the paths / and /trace (diagnostics), with some
-* support for HTTP error pages for various codes and fallback to HTTP 500 if
-* those codes fail for any reason.
-*
-* @param server : nsHttpServer
-* the server in which this handler is being used
-*/
-function ServerHandler(server)
-{
-  // FIELDS
-
-  /**
-* The nsHttpServer instance associated with this handler.
-*/
-  this._server = server;
-
-  /**
-* A FileMap object containing the set of path->nsIFile mappings for
-* all directory mappings set in the server (e.g., "/" for /var/www/html/,
-* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2).
-*
-* Note carefully: the leading and trailing "/" in each path (not file) are
-* removed before insertion to simplify the code which uses this. You have
-* been warned!
-*/
-  this._pathDirectoryMap = new FileMap();
-
-  /**
-* Custom request handlers for the server in which this resides. Path-handler
-* pairs are stored as property-value pairs in this property.
-*
-* @see ServerHandler.prototype._defaultPaths
-*/
-  this._overridePaths = {};
-
-  /**
-* Custom request handlers for the server in which this resides. Prefix-handler
-* pairs are stored as property-value pairs in this property.
-*/
-  this._overridePrefixes = {};
-
-  /**
-* Custom request handlers for the error handlers in the server in which this
-* resides. Path-handler pairs are stored as property-value pairs in this
-* property.
-*
-* @see ServerHandler.prototype._defaultErrors
-*/
-  this._overrideErrors = {};
-
-  /**
-* Maps file extensions to their MIME types in the server, overriding any
-* mapping that might or might not exist in the MIME service.
-*/
-  this._mimeMappings = {};
-
-  /**
-* The default handler for requests for directories, used to serve directories
-* when no index file is present.
-*/
-  this._indexHandler = defaultIndexHandler;
-
-  /** Per-path state storage for the server. */
-  this._state = {};
-
-  /** Entire-server state storage. */
-  this._sharedState = {};
-
-  /** Entire-server state storage for nsISupports values. */
-  this._objectState = {};
-}
-ServerHandler.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Handles a request to this server, responding to the request appropriately
-* and initiating server shutdown if necessary.
-*
-* This method never throws an exception.
-*
-* @param connection : Connection
-* the connection for this request
-*/
-  handleResponse: function(connection)
-  {
-    var request = connection.request;
-    var response = new Response(connection);
-
-    var path = request.path;
-    dumpn("*** path == " + path);
-
-    try
-    {
-      try
-      {
-        if (path in this._overridePaths)
-        {
-          // explicit paths first, then files based on existing directory mappings,
-          // then (if the file doesn't exist) built-in server default paths
-          dumpn("calling override for " + path);
-          this._overridePaths[path](request, response);
-        }
-        else
-        {
-          let longestPrefix = "";
-          for (let prefix in this._overridePrefixes)
-          {
-            if (prefix.length > longestPrefix.length && path.startsWith(prefix))
-            {
-              longestPrefix = prefix;
-            }
-          }
-          if (longestPrefix.length > 0)
-          {
-            dumpn("calling prefix override for " + longestPrefix);
-            this._overridePrefixes[longestPrefix](request, response);
-          }
-          else
-          {
-            this._handleDefault(request, response);
-          }
-        }
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        if (!(e instanceof HttpError))
-        {
-          dumpn("*** unexpected error: e == " + e);
-          throw HTTP_500;
-        }
-        if (e.code !== 404)
-          throw e;
-
-        dumpn("*** default: " + (path in this._defaultPaths));
-
-        response = new Response(connection);
-        if (path in this._defaultPaths)
-          this._defaultPaths[path](request, response);
-        else
-          throw HTTP_404;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort(e);
-        return;
-      }
-
-      var errorCode = "internal";
-
-      try
-      {
-        if (!(e instanceof HttpError))
-          throw e;
-
-        errorCode = e.code;
-        dumpn("*** errorCode == " + errorCode);
-
-        response = new Response(connection);
-        if (e.customErrorHandling)
-          e.customErrorHandling(response);
-        this._handleError(errorCode, request, response);
-        return;
-      }
-      catch (e2)
-      {
-        dumpn("*** error handling " + errorCode + " error: " +
-              "e2 == " + e2 + ", shutting down server");
-
-        connection.server._requestQuit();
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (!file)
-    {
-      dumpn("*** unregistering '" + path + "' mapping");
-      delete this._overridePaths[path];
-      return;
-    }
-
-    dumpn("*** registering '" + path + "' as mapping to " + file.path);
-    file = file.clone();
-
-    var self = this;
-    this._overridePaths[path] =
-      function(request, response)
-      {
-        if (!file.exists())
-          throw HTTP_404;
-
-        response.setStatusLine(request.httpVersion, 200, "OK");
-        self._writeFileResponse(request, file, response, 0, file.fileSize);
-      };
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePaths, path);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    // XXX true prefix validation!
-    if (!(prefix.startsWith("/") && prefix.endsWith("/")))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePrefixes, prefix);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // strip off leading and trailing '/' so that we can use lastIndexOf when
-    // determining exactly how a path maps onto a mapped directory --
-    // conditional is required here to deal with "/".substring(1, 0) being
-    // converted to "/".substring(0, 1) per the JS specification
-    var key = path.length == 1 ? "" : path.substring(1, path.length - 1);
-
-    // the path-to-directory mapping code requires that the first character not
-    // be "/", or it will go into an infinite loop
-    if (key.charAt(0) == "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    key = toInternalPath(key, false);
-
-    if (directory)
-    {
-      dumpn("*** mapping '" + path + "' to the location " + directory.path);
-      this._pathDirectoryMap.put(key, directory);
-    }
-    else
-    {
-      dumpn("*** removing mapping for '" + path + "'");
-      this._pathDirectoryMap.put(key, null);
-    }
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(err, handler)
-  {
-    if (!(err in HTTP_ERROR_CODES))
-      dumpn("*** WARNING: registering non-HTTP/1.1 error code " +
-            "(" + err + ") handler -- was this intentional?");
-
-    this._handlerToField(handler, this._overrideErrors, err);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    if (!handler)
-      handler = defaultIndexHandler;
-    else if (typeof(handler) != "function")
-      handler = createHandlerFunc(handler);
-
-    this._indexHandler = handler;
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    if (!type)
-      delete this._mimeMappings[ext];
-    else
-      this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type);
-  },
-
-  // PRIVATE API
-
-  /**
-* Sets or remove (if handler is null) a handler in an object with a key.
-*
-* @param handler
-* a handler, either function or an nsIHttpRequestHandler
-* @param dict
-* The object to attach the handler to.
-* @param key
-* The field name of the handler.
-*/
-  _handlerToField: function(handler, dict, key)
-  {
-    // for convenience, handler can be a function if this is run from xpcshell
-    if (typeof(handler) == "function")
-      dict[key] = handler;
-    else if (handler)
-      dict[key] = createHandlerFunc(handler);
-    else
-      delete dict[key];
-  },
-
-  /**
-* Handles a request which maps to a file in the local filesystem (if a base
-* path has already been set; otherwise the 404 error is thrown).
-*
-* @param metadata : Request
-* metadata for the incoming request
-* @param response : Response
-* an uninitialized Response to the given request, to be initialized by a
-* request handler
-* @throws HTTP_###
-* if an HTTP error occurred (usually HTTP_404); note that in this case the
-* calling code must handle post-processing of the response
-*/
-  _handleDefault: function(metadata, response)
-  {
-    dumpn("*** _handleDefault()");
-
-    response.setStatusLine(metadata.httpVersion, 200, "OK");
-
-    var path = metadata.path;
-    NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">");
-
-    // determine the actual on-disk file; this requires finding the deepest
-    // path-to-directory mapping in the requested URL
-    var file = this._getFileForPath(path);
-
-    // the "file" might be a directory, in which case we either serve the
-    // contained index.html or make the index handler write the response
-    if (file.exists() && file.isDirectory())
-    {
-      file.append("index.html"); // make configurable?
-      if (!file.exists() || file.isDirectory())
-      {
-        metadata._ensurePropertyBag();
-        metadata._bag.setPropertyAsInterface("directory", file.parent);
-        this._indexHandler(metadata, response);
-        return;
-      }
-    }
-
-    // alternately, the file might not exist
-    if (!file.exists())
-      throw HTTP_404;
-
-    var start, end;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
-        metadata.hasHeader("Range") &&
-        this._getTypeFromFile(file) !== SJS_TYPE)
-    {
-      var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
-      if (!rangeMatch)
-        throw HTTP_400;
-
-      if (rangeMatch[1] !== undefined)
-        start = parseInt(rangeMatch[1], 10);
-
-      if (rangeMatch[2] !== undefined)
-        end = parseInt(rangeMatch[2], 10);
-
-      if (start === undefined && end === undefined)
-        throw HTTP_400;
-
-      // No start given, so the end is really the count of bytes from the
-      // end of the file.
-      if (start === undefined)
-      {
-        start = Math.max(0, file.fileSize - end);
-        end = file.fileSize - 1;
-      }
-
-      // start and end are inclusive
-      if (end === undefined || end >= file.fileSize)
-        end = file.fileSize - 1;
-
-      if (start !== undefined && start >= file.fileSize) {
-        var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
-        HTTP_416.customErrorHandling = function(errorResponse)
-        {
-          maybeAddHeaders(file, metadata, errorResponse);
-        };
-        throw HTTP_416;
-      }
-
-      if (end < start)
-      {
-        response.setStatusLine(metadata.httpVersion, 200, "OK");
-        start = 0;
-        end = file.fileSize - 1;
-      }
-      else
-      {
-        response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
-        var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize;
-        response.setHeader("Content-Range", contentRange);
-      }
-    }
-    else
-    {
-      start = 0;
-      end = file.fileSize - 1;
-    }
-
-    // finally...
-    dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " +
-          start + " to " + end + " inclusive");
-    this._writeFileResponse(metadata, file, response, start, end - start + 1);
-  },
-
-  /**
-* Writes an HTTP response for the given file, including setting headers for
-* file metadata.
-*
-* @param metadata : Request
-* the Request for which a response is being generated
-* @param file : nsIFile
-* the file which is to be sent in the response
-* @param response : Response
-* the response to which the file should be written
-* @param offset: uint
-* the byte offset to skip to when writing
-* @param count: uint
-* the number of bytes to write
-*/
-  _writeFileResponse: function(metadata, file, response, offset, count)
-  {
-    const PR_RDONLY = 0x01;
-
-    var type = this._getTypeFromFile(file);
-    if (type === SJS_TYPE)
-    {
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      try
-      {
-        var sis = new ScriptableInputStream(fis);
-        var s = Cu.Sandbox(gGlobalObject);
-        s.importFunction(dump, "dump");
-
-        // Define a basic key-value state-preservation API across requests, with
-        // keys initially corresponding to the empty string.
-        var self = this;
-        var path = metadata.path;
-        s.importFunction(function getState(k)
-        {
-          return self._getState(path, k);
-        });
-        s.importFunction(function setState(k, v)
-        {
-          self._setState(path, k, v);
-        });
-        s.importFunction(function getSharedState(k)
-        {
-          return self._getSharedState(k);
-        });
-        s.importFunction(function setSharedState(k, v)
-        {
-          self._setSharedState(k, v);
-        });
-        s.importFunction(function getObjectState(k, callback)
-        {
-          callback(self._getObjectState(k));
-        });
-        s.importFunction(function setObjectState(k, v)
-        {
-          self._setObjectState(k, v);
-        });
-        s.importFunction(function registerPathHandler(p, h)
-        {
-          self.registerPathHandler(p, h);
-        });
-
-        // Make it possible for sjs files to access their location
-        this._setState(path, "__LOCATION__", file.path);
-
-        try
-        {
-          // Alas, the line number in errors dumped to console when calling the
-          // request handler is simply an offset from where we load the SJS file.
-          // Work around this in a reasonably non-fragile way by dynamically
-          // getting the line number where we evaluate the SJS file. Don't
-          // separate these two lines!
-          var line = new Error().lineNumber;
-          Cu.evalInSandbox(sis.read(file.fileSize), s);
-        }
-        catch (e)
-        {
-          dumpn("*** syntax error in SJS at " + file.path + ": " + e);
-          throw HTTP_500;
-        }
-
-        try
-        {
-          s.handleRequest(metadata, response);
-        }
-        catch (e)
-        {
-          dump("*** error running SJS at " + file.path + ": " +
-               e + " on line " +
-               (e instanceof Error
-               ? e.lineNumber + " in httpd.js"
-               : (e.lineNumber - line)) + "\n");
-          throw HTTP_500;
-        }
-      }
-      finally
-      {
-        fis.close();
-      }
-    }
-    else
-    {
-      try
-      {
-        response.setHeader("Last-Modified",
-                           toDateString(file.lastModifiedTime),
-                           false);
-      }
-      catch (e) { /* lastModifiedTime threw, ignore */ }
-
-      response.setHeader("Content-Type", type, false);
-      maybeAddHeaders(file, metadata, response);
-      response.setHeader("Content-Length", "" + count, false);
-
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      offset = offset || 0;
-      count = count || file.fileSize;
-      NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset");
-      NS_ASSERT(count >= 0, "bad count");
-      NS_ASSERT(offset + count <= file.fileSize, "bad total data size");
-
-      try
-      {
-        if (offset !== 0)
-        {
-          // Seek (or read, if seeking isn't supported) to the correct offset so
-          // the data sent to the client matches the requested range.
-          if (fis instanceof Ci.nsISeekableStream)
-            fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset);
-          else
-            new ScriptableInputStream(fis).read(offset);
-        }
-      }
-      catch (e)
-      {
-        fis.close();
-        throw e;
-      }
-
-      let writeMore = function writeMore()
-      {
-        gThreadManager.dispatchToMainThread(writeData);
-      }
-
-      var input = new BinaryInputStream(fis);
-      var output = new BinaryOutputStream(response.bodyOutputStream);
-      var writeData =
-        {
-          run: function()
-          {
-            var chunkSize = Math.min(65536, count);
-            count -= chunkSize;
-            NS_ASSERT(count >= 0, "underflow");
-
-            try
-            {
-              var data = input.readByteArray(chunkSize);
-              NS_ASSERT(data.length === chunkSize,
-                        "incorrect data returned? got " + data.length +
-                        ", expected " + chunkSize);
-              output.writeByteArray(data, data.length);
-              if (count === 0)
-              {
-                fis.close();
-                response.finish();
-              }
-              else
-              {
-                writeMore();
-              }
-            }
-            catch (e)
-            {
-              try
-              {
-                fis.close();
-              }
-              finally
-              {
-                response.finish();
-              }
-              throw e;
-            }
-          }
-        };
-
-      writeMore();
-
-      // Now that we know copying will start, flag the response as async.
-      response.processAsync();
-    }
-  },
-
-  /**
-* Get the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getState: function(path, k)
-  {
-    var state = this._state;
-    if (path in state && k in state[path])
-      return state[path][k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setState: function(path, k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    var state = this._state;
-    if (!(path in state))
-      state[path] = {};
-    state[path][k] = v;
-  },
-
-  /**
-* Get the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getSharedState: function(k)
-  {
-    var state = this._sharedState;
-    if (k in state)
-      return state[k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setSharedState: function(k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    this._sharedState[k] = v;
-  },
-
-  /**
-* Returns the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be returned
-* @returns nsISupports
-* the corresponding object, or null if none was present
-*/
-  _getObjectState: function(k)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    return this._objectState[k] || null;
-  },
-
-  /**
-* Sets the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be set
-* @param v : nsISupports
-* the object to be associated with the given key; may be null
-*/
-  _setObjectState: function(k, v)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    if (typeof v !== "object")
-      throw new Error("non-object value passed");
-    if (v && !("QueryInterface" in v))
-    {
-      throw new Error("must pass an nsISupports; use wrappedJSObject to ease " +
-                      "pain when using the server from JS");
-    }
-
-    this._objectState[k] = v;
-  },
-
-  /**
-* Gets a content-type for the given file, first by checking for any custom
-* MIME-types registered with this handler for the file's extension, second by
-* asking the global MIME service for a content-type, and finally by failing
-* over to application/octet-stream.
-*
-* @param file : nsIFile
-* the nsIFile for which to get a file type
-* @returns string
-* the best content-type which can be determined for the file
-*/
-  _getTypeFromFile: function(file)
-  {
-    try
-    {
-      var name = file.leafName;
-      var dot = name.lastIndexOf(".");
-      if (dot > 0)
-      {
-        var ext = name.slice(dot + 1);
-        if (ext in this._mimeMappings)
-          return this._mimeMappings[ext];
-      }
-      return Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
-               .getService(Ci.nsIMIMEService)
-               .getTypeFromFile(file);
-    }
-    catch (e)
-    {
-      return "application/octet-stream";
-    }
-  },
-
-  /**
-* Returns the nsIFile which corresponds to the path, as determined using
-* all registered path->directory mappings and any paths which are explicitly
-* overridden.
-*
-* @param path : string
-* the server path for which a file should be retrieved, e.g. "/foo/bar"
-* @throws HttpError
-* when the correct action is the corresponding HTTP error (i.e., because no
-* mapping was found for a directory in path, the referenced file doesn't
-* exist, etc.)
-* @returns nsIFile
-* the file to be sent as the response to a request for the path
-*/
-  _getFileForPath: function(path)
-  {
-    // decode and add underscores as necessary
-    try
-    {
-      path = toInternalPath(path, true);
-    }
-    catch (e)
-    {
-      throw HTTP_400; // malformed path
-    }
-
-    // next, get the directory which contains this path
-    var pathMap = this._pathDirectoryMap;
-
-    // An example progression of tmp for a path "/foo/bar/baz/" might be:
-    // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
-    var tmp = path.substring(1);
-    while (true)
-    {
-      // do we have a match for current head of the path?
-      var file = pathMap.get(tmp);
-      if (file)
-      {
-        // XXX hack; basically disable showing mapping for /foo/bar/ when the
-        // requested path was /foo/bar, because relative links on the page
-        // will all be incorrect -- we really need the ability to easily
-        // redirect here instead
-        if (tmp == path.substring(1) &&
-            tmp.length != 0 &&
-            tmp.charAt(tmp.length - 1) != "/")
-          file = null;
-        else
-          break;
-      }
-
-      // if we've finished trying all prefixes, exit
-      if (tmp == "")
-        break;
-
-      tmp = tmp.substring(0, tmp.lastIndexOf("/"));
-    }
-
-    // no mapping applies, so 404
-    if (!file)
-      throw HTTP_404;
-
-
-    // last, get the file for the path within the determined directory
-    var parentFolder = file.parent;
-    var dirIsRoot = (parentFolder == null);
-
-    // Strategy here is to append components individually, making sure we
-    // never move above the given directory; this allows paths such as
-    // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling";
-    // this component-wise approach also means the code works even on platforms
-    // which don't use "/" as the directory separator, such as Windows
-    var leafPath = path.substring(tmp.length + 1);
-    var comps = leafPath.split("/");
-    for (var i = 0, sz = comps.length; i < sz; i++)
-    {
-      var comp = comps[i];
-
-      if (comp == "..")
-        file = file.parent;
-      else if (comp == "." || comp == "")
-        continue;
-      else
-        file.append(comp);
-
-      if (!dirIsRoot && file.equals(parentFolder))
-        throw HTTP_403;
-    }
-
-    return file;
-  },
-
-  /**
-* Writes the error page for the given HTTP error code over the given
-* connection.
-*
-* @param errorCode : uint
-* the HTTP error code to be used
-* @param connection : Connection
-* the connection on which the error occurred
-*/
-  handleError: function(errorCode, connection)
-  {
-    var response = new Response(connection);
-
-    dumpn("*** error in request: " + errorCode);
-
-    this._handleError(errorCode, new Request(connection.port), response);
-  },
-
-  /**
-* Handles a request which generates the given error code, using the
-* user-defined error handler if one has been set, gracefully falling back to
-* the x00 status code if the code has no handler, and failing to status code
-* 500 if all else fails.
-*
-* @param errorCode : uint
-* the HTTP error which is to be returned
-* @param metadata : Request
-* metadata for the request, which will often be incomplete since this is an
-* error
-* @param response : Response
-* an uninitialized Response should be initialized when this method
-* completes with information which represents the desired error code in the
-* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a
-* fallback for 505, per HTTP specs)
-*/
-  _handleError: function(errorCode, metadata, response)
-  {
-    if (!metadata)
-      throw Cr.NS_ERROR_NULL_POINTER;
-
-    var errorX00 = errorCode - (errorCode % 100);
-
-    try
-    {
-      if (!(errorCode in HTTP_ERROR_CODES))
-        dumpn("*** WARNING: requested invalid error: " + errorCode);
-
-      // RFC 2616 says that we should try to handle an error by its class if we
-      // can't otherwise handle it -- if that fails, we revert to handling it as
-      // a 500 internal server error, and if that fails we throw and shut down
-      // the server
-
-      // actually handle the error
-      try
-      {
-        if (errorCode in this._overrideErrors)
-          this._overrideErrors[errorCode](metadata, response);
-        else
-          this._defaultErrors[errorCode](metadata, response);
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        // don't retry the handler that threw
-        if (errorX00 == errorCode)
-          throw HTTP_500;
-
-        dumpn("*** error in handling for error code " + errorCode + ", " +
-              "falling back to " + errorX00 + "...");
-        response = new Response(response._connection);
-        if (errorX00 in this._overrideErrors)
-          this._overrideErrors[errorX00](metadata, response);
-        else if (errorX00 in this._defaultErrors)
-          this._defaultErrors[errorX00](metadata, response);
-        else
-          throw HTTP_500;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort();
-        return;
-      }
-
-      // we've tried everything possible for a meaningful error -- now try 500
-      dumpn("*** error in handling for error code " + errorX00 + ", falling " +
-            "back to 500...");
-
-      try
-      {
-        response = new Response(response._connection);
-        if (500 in this._overrideErrors)
-          this._overrideErrors[500](metadata, response);
-        else
-          this._defaultErrors[500](metadata, response);
-      }
-      catch (e2)
-      {
-        dumpn("*** multiple errors in default error handlers!");
-        dumpn("*** e == " + e + ", e2 == " + e2);
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  // FIELDS
-
-  /**
-* This object contains the default handlers for the various HTTP error codes.
-*/
-  _defaultErrors:
-  {
-    400: function(metadata, response)
-    {
-      // none of the data in metadata is reliable, so hard-code everything here
-      response.setStatusLine("1.1", 400, "Bad Request");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Bad request\n";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    403: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 403, "Forbidden");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>403 Forbidden</title></head>\
-<body>\
-<h1>403 Forbidden</h1>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    404: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 404, "Not Found");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>404 Not Found</title></head>\
-<body>\
-<h1>404 Not Found</h1>\
-<p>\
-<span style='font-family: monospace;'>" +
-                          htmlEscape(metadata.path) +
-                       "</span> was not found.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    416: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                            416,
-                            "Requested Range Not Satisfiable");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head>\
-<title>416 Requested Range Not Satisfiable</title></head>\
-<body>\
-<h1>416 Requested Range Not Satisfiable</h1>\
-<p>The byte range was not valid for the\
-requested resource.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    500: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                             500,
-                             "Internal Server Error");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>500 Internal Server Error</title></head>\
-<body>\
-<h1>500 Internal Server Error</h1>\
-<p>Something's broken in this server and\
-needs to be fixed.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    501: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 501, "Not Implemented");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>501 Not Implemented</title></head>\
-<body>\
-<h1>501 Not Implemented</h1>\
-<p>This server is not (yet) Apache.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    505: function(metadata, response)
-    {
-      response.setStatusLine("1.1", 505, "HTTP Version Not Supported");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>505 HTTP Version Not Supported</title></head>\
-<body>\
-<h1>505 HTTP Version Not Supported</h1>\
-<p>This server only supports HTTP/1.0 and HTTP/1.1\
-connections.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    }
-  },
-
-  /**
-* Contains handlers for the default set of URIs contained in this server.
-*/
-  _defaultPaths:
-  {
-    "/": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>httpd.js</title></head>\
-<body>\
-<h1>httpd.js</h1>\
-<p>If you're seeing this page, httpd.js is up and\
-serving requests! Now set a base path and serve some\
-files!</p>\
-</body>\
-</html>";
-
-      response.bodyOutputStream.write(body, body.length);
-    },
-
-    "/trace": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Request-URI: " +
-                 metadata.scheme + "://" + metadata.host + ":" + metadata.port +
-                 metadata.path + "\n\n";
-      body += "Request (semantically equivalent, slightly reformatted):\n\n";
-      body += metadata.method + " " + metadata.path;
-
-      if (metadata.queryString)
-        body += "?" + metadata.queryString;
-
-      body += " HTTP/" + metadata.httpVersion + "\r\n";
-
-      var headEnum = metadata.headers;
-      while (headEnum.hasMoreElements())
-      {
-        var fieldName = headEnum.getNext()
-                                .QueryInterface(Ci.nsISupportsString)
-                                .data;
-        body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n";
-      }
-
-      response.bodyOutputStream.write(body, body.length);
-    }
-  }
-};
-
-
-/**
-* Maps absolute paths to files on the local file system (as nsILocalFiles).
-*/
-function FileMap()
-{
-  /** Hash which will map paths to nsILocalFiles. */
-  this._map = {};
-}
-FileMap.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Maps key to a clone of the nsIFile value if value is non-null;
-* otherwise, removes any extant mapping for key.
-*
-* @param key : string
-* string to which a clone of value is mapped
-* @param value : nsIFile
-* the file to map to key, or null to remove a mapping
-*/
-  put: function(key, value)
-  {
-    if (value)
-      this._map[key] = value.clone();
-    else
-      delete this._map[key];
-  },
-
-  /**
-* Returns a clone of the nsIFile mapped to key, or null if no such
-* mapping exists.
-*
-* @param key : string
-* key to which the returned file maps
-* @returns nsIFile
-* a clone of the mapped file, or null if no mapping exists
-*/
-  get: function(key)
-  {
-    var val = this._map[key];
-    return val ? val.clone() : null;
-  }
-};
-
-
-// Response CONSTANTS
-
-// token = *<any CHAR except CTLs or separators>
-// CHAR = <any US-ASCII character (0-127)>
-// CTL = <any US-ASCII control character (0-31) and DEL (127)>
-// separators = "(" | ")" | "<" | ">" | "@"
-// | "," | ";" | ":" | "\" | <">
-// | "/" | "[" | "]" | "?" | "="
-// | "{" | "}" | SP | HT
-const IS_TOKEN_ARRAY =
-  [0, 0, 0, 0, 0, 0, 0, 0, // 0
-   0, 0, 0, 0, 0, 0, 0, 0, // 8
-   0, 0, 0, 0, 0, 0, 0, 0, // 16
-   0, 0, 0, 0, 0, 0, 0, 0, // 24
-
-   0, 1, 0, 1, 1, 1, 1, 1, // 32
-   0, 0, 1, 1, 0, 1, 1, 0, // 40
-   1, 1, 1, 1, 1, 1, 1, 1, // 48
-   1, 1, 0, 0, 0, 0, 0, 0, // 56
-
-   0, 1, 1, 1, 1, 1, 1, 1, // 64
-   1, 1, 1, 1, 1, 1, 1, 1, // 72
-   1, 1, 1, 1, 1, 1, 1, 1, // 80
-   1, 1, 1, 0, 0, 0, 1, 1, // 88
-
-   1, 1, 1, 1, 1, 1, 1, 1, // 96
-   1, 1, 1, 1, 1, 1, 1, 1, // 104
-   1, 1, 1, 1, 1, 1, 1, 1, // 112
-   1, 1, 1, 0, 1, 0, 1]; // 120
-
-
-/**
-* Determines whether the given character code is a CTL.
-*
-* @param code : uint
-* the character code
-* @returns boolean
-* true if code is a CTL, false otherwise
-*/
-function isCTL(code)
-{
-  return (code >= 0 && code <= 31) || (code == 127);
-}
-
-/**
-* Represents a response to an HTTP request, encapsulating all details of that
-* response. This includes all headers, the HTTP version, status code and
-* explanation, and the entity itself.
-*
-* @param connection : Connection
-* the connection over which this response is to be written
-*/
-function Response(connection)
-{
-  /** The connection over which this response will be written. */
-  this._connection = connection;
-
-  /**
-* The HTTP version of this response; defaults to 1.1 if not set by the
-* handler.
-*/
-  this._httpVersion = nsHttpVersion.HTTP_1_1;
-
-  /**
-* The HTTP code of this response; defaults to 200.
-*/
-  this._httpCode = 200;
-
-  /**
-* The description of the HTTP code in this response; defaults to "OK".
-*/
-  this._httpDescription = "OK";
-
-  /**
-* An nsIHttpHeaders object in which the headers in this response should be
-* stored. This property is null after the status line and headers have been
-* written to the network, and it may be modified up until it is cleared,
-* except if this._finished is set first (in which case headers are written
-* asynchronously in response to a finish() call not preceded by
-* flushHeaders()).
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* Set to true when this response is ended (completely constructed if possible
-* and the connection closed); further actions on this will then fail.
-*/
-  this._ended = false;
-
-  /**
-* A stream used to hold data written to the body of this response.
-*/
-  this._bodyOutputStream = null;
-
-  /**
-* A stream containing all data that has been written to the body of this
-* response so far. (Async handlers make the data contained in this
-* unreliable as a way of determining content length in general, but auxiliary
-* saved information can sometimes be used to guarantee reliability.)
-*/
-  this._bodyInputStream = null;
-
-  /**
-* A stream copier which copies data to the network. It is initially null
-* until replaced with a copier for response headers; when headers have been
-* fully sent it is replaced with a copier for the response body, remaining
-* so for the duration of response processing.
-*/
-  this._asyncCopier = null;
-
-  /**
-* True if this response has been designated as being processed
-* asynchronously rather than for the duration of a single call to
-* nsIHttpRequestHandler.handle.
-*/
-  this._processAsync = false;
-
-  /**
-* True iff finish() has been called on this, signaling that no more changes
-* to this may be made.
-*/
-  this._finished = false;
-
-  /**
-* True iff powerSeized() has been called on this, signaling that this
-* response is to be handled manually by the response handler (which may then
-* send arbitrary data in response, even non-HTTP responses).
-*/
-  this._powerSeized = false;
-}
-Response.prototype =
-{
-  // PUBLIC CONSTRUCTION API
-
-  //
-  // see nsIHttpResponse.bodyOutputStream
-  //
-  get bodyOutputStream()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    if (!this._bodyOutputStream)
-    {
-      var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX,
-                          null);
-      this._bodyOutputStream = pipe.outputStream;
-      this._bodyInputStream = pipe.inputStream;
-      if (this._processAsync || this._powerSeized)
-        this._startAsyncProcessor();
-    }
-
-    return this._bodyOutputStream;
-  },
-
-  //
-  // see nsIHttpResponse.write
-  //
-  write: function(data)
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    var dataAsString = String(data);
-    this.bodyOutputStream.write(dataAsString, dataAsString.length);
-  },
-
-  //
-  // see nsIHttpResponse.setStatusLine
-  //
-  setStatusLine: function(httpVersion, code, description)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    if (!(code >= 0 && code < 1000))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    try
-    {
-      var httpVer;
-      // avoid version construction for the most common cases
-      if (!httpVersion || httpVersion == "1.1")
-        httpVer = nsHttpVersion.HTTP_1_1;
-      else if (httpVersion == "1.0")
-        httpVer = nsHttpVersion.HTTP_1_0;
-      else
-        httpVer = new nsHttpVersion(httpVersion);
-    }
-    catch (e)
-    {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    // Reason-Phrase = *<TEXT, excluding CR, LF>
-    // TEXT = <any OCTET except CTLs, but including LWS>
-    //
-    // XXX this ends up disallowing octets which aren't Unicode, I think -- not
-    // much to do if description is IDL'd as string
-    if (!description)
-      description = "";
-    for (var i = 0; i < description.length; i++)
-      if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t")
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // set the values only after validation to preserve atomicity
-    this._httpDescription = description;
-    this._httpCode = code;
-    this._httpVersion = httpVer;
-  },
-
-  //
-  // see nsIHttpResponse.setHeader
-  //
-  setHeader: function(name, value, merge)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    this._headers.setHeader(name, value, merge);
-  },
-
-  //
-  // see nsIHttpResponse.processAsync
-  //
-  processAsync: function()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._processAsync)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** processing connection " + this._connection.number + " async");
-    this._processAsync = true;
-
-    /*
-* Either the bodyOutputStream getter or this method is responsible for
-* starting the asynchronous processor and catching writes of data to the
-* response body of async responses as they happen, for the purpose of
-* forwarding those writes to the actual connection's output stream.
-* If bodyOutputStream is accessed first, calling this method will create
-* the processor (when it first is clear that body data is to be written
-* immediately, not buffered). If this method is called first, accessing
-* bodyOutputStream will create the processor. If only this method is
-* called, we'll write nothing, neither headers nor the nonexistent body,
-* until finish() is called. Since that delay is easily avoided by simply
-* getting bodyOutputStream or calling write(""), we don't worry about it.
-*/
-    if (this._bodyOutputStream && !this._asyncCopier)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.seizePower
-  //
-  seizePower: function()
-  {
-    if (this._processAsync)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** forcefully seizing power over connection " +
-          this._connection.number + "...");
-
-    // Purge any already-written data without sending it. We could as easily
-    // swap out the streams entirely, but that makes it possible to acquire and
-    // unknowingly use a stale reference, so we require there only be one of
-    // each stream ever for any response to avoid this complication.
-    if (this._asyncCopier)
-      this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED);
-    this._asyncCopier = null;
-    if (this._bodyOutputStream)
-    {
-      var input = new BinaryInputStream(this._bodyInputStream);
-      var avail;
-      while ((avail = input.available()) > 0)
-        input.readByteArray(avail);
-    }
-
-    this._powerSeized = true;
-    if (this._bodyOutputStream)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.finish
-  //
-  finish: function()
-  {
-    if (!this._processAsync && !this._powerSeized)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._finished)
-      return;
-
-    dumpn("*** finishing connection " + this._connection.number);
-    this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-    this._finished = true;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // POST-CONSTRUCTION API (not exposed externally)
-
-  /**
-* The HTTP version number of this, as a string (e.g. "1.1").
-*/
-  get httpVersion()
-  {
-    this._ensureAlive();
-    return this._httpVersion.toString();
-  },
-
-  /**
-* The HTTP status code of this response, as a string of three characters per
-* RFC 2616.
-*/
-  get httpCode()
-  {
-    this._ensureAlive();
-
-    var codeString = (this._httpCode < 10 ? "0" : "") +
-                     (this._httpCode < 100 ? "0" : "") +
-                     this._httpCode;
-    return codeString;
-  },
-
-  /**
-* The description of the HTTP status code of this response, or "" if none is
-* set.
-*/
-  get httpDescription()
-  {
-    this._ensureAlive();
-
-    return this._httpDescription;
-  },
-
-  /**
-* The headers in this response, as an nsHttpHeaders object.
-*/
-  get headers()
-  {
-    this._ensureAlive();
-
-    return this._headers;
-  },
-
-  //
-  // see nsHttpHeaders.getHeader
-  //
-  getHeader: function(name)
-  {
-    this._ensureAlive();
-
-    return this._headers.getHeader(name);
-  },
-
-  /**
-* Determines whether this response may be abandoned in favor of a newly
-* constructed response. A response may be abandoned only if it is not being
-* sent asynchronously and if raw control over it has not been taken from the
-* server.
-*
-* @returns boolean
-* true iff no data has been written to the network
-*/
-  partiallySent: function()
-  {
-    dumpn("*** partiallySent()");
-    return this._processAsync || this._powerSeized;
-  },
-
-  /**
-* If necessary, kicks off the remaining request processing needed to be done
-* after a request handler performs its initial work upon this response.
-*/
-  complete: function()
-  {
-    dumpn("*** complete()");
-    if (this._processAsync || this._powerSeized)
-    {
-      NS_ASSERT(this._processAsync ^ this._powerSeized,
-                "can't both send async and relinquish power");
-      return;
-    }
-
-    NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?");
-
-    this._startAsyncProcessor();
-
-    // Now make sure we finish processing this request!
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-  },
-
-  /**
-* Abruptly ends processing of this response, usually due to an error in an
-* incoming request but potentially due to a bad error handler. Since we
-* cannot handle the error in the usual way (giving an HTTP error page in
-* response) because data may already have been sent (or because the response
-* might be expected to have been generated asynchronously or completely from
-* scratch by the handler), we stop processing this response and abruptly
-* close the connection.
-*
-* @param e : Error
-* the exception which precipitated this abort, or null if no such exception
-* was generated
-*/
-  abort: function(e)
-  {
-    dumpn("*** abort(<" + e + ">)");
-
-    // This response will be ended by the processor if one was created.
-    var copier = this._asyncCopier;
-    if (copier)
-    {
-      // We dispatch asynchronously here so that any pending writes of data to
-      // the connection will be deterministically written. This makes it easier
-      // to specify exact behavior, and it makes observable behavior more
-      // predictable for clients. Note that the correctness of this depends on
-      // callbacks in response to _waitToReadData in WriteThroughCopier
-      // happening asynchronously with respect to the actual writing of data to
-      // bodyOutputStream, as they currently do; if they happened synchronously,
-      // an event which ran before this one could write more data to the
-      // response body before we get around to canceling the copier. We have
-      // tests for this in test_seizepower.js, however, and I can't think of a
-      // way to handle both cases without removing bodyOutputStream access and
-      // moving its effective write(data, length) method onto Response, which
-      // would be slower and require more code than this anyway.
-      gThreadManager.dispatchToMainThread({
-        run: function()
-        {
-          dumpn("*** canceling copy asynchronously...");
-          copier.cancel(Cr.NS_ERROR_UNEXPECTED);
-        }
-      });
-    }
-    else
-    {
-      this.end();
-    }
-  },
-
-  /**
-* Closes this response's network connection, marks the response as finished,
-* and notifies the server handler that the request is done being processed.
-*/
-  end: function()
-  {
-    NS_ASSERT(!this._ended, "ending this response twice?!?!");
-
-    this._connection.close();
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-
-    this._finished = true;
-    this._ended = true;
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Sends the status line and headers of this response if they haven't been
-* sent and initiates the process of copying data written to this response's
-* body to the network.
-*/
-  _startAsyncProcessor: function()
-  {
-    dumpn("*** _startAsyncProcessor()");
-
-    // Handle cases where we're being called a second time. The former case
-    // happens when this is triggered both by complete() and by processAsync(),
-    // while the latter happens when processAsync() in conjunction with sent
-    // data causes abort() to be called.
-    if (this._asyncCopier || this._ended)
-    {
-      dumpn("*** ignoring second call to _startAsyncProcessor");
-      return;
-    }
-
-    // Send headers if they haven't been sent already and should be sent, then
-    // asynchronously continue to send the body.
-    if (this._headers && !this._powerSeized)
-    {
-      this._sendHeaders();
-      return;
-    }
-
-    this._headers = null;
-    this._sendBody();
-  },
-
-  /**
-* Signals that all modifications to the response status line and headers are
-* complete and then sends that data over the network to the client. Once
-* this method completes, a different response to the request that resulted
-* in this response cannot be sent -- the only possible action in case of
-* error is to abort the response and close the connection.
-*/
-  _sendHeaders: function()
-  {
-    dumpn("*** _sendHeaders()");
-
-    NS_ASSERT(this._headers);
-    NS_ASSERT(!this._powerSeized);
-
-    // request-line
-    var statusLine = "HTTP/" + this.httpVersion + " " +
-                     this.httpCode + " " +
-                     this.httpDescription + "\r\n";
-
-    // header post-processing
-
-    var headers = this._headers;
-    headers.setHeader("Connection", "close", false);
-    headers.setHeader("Server", "httpd.js", false);
-    if (!headers.hasHeader("Date"))
-      headers.setHeader("Date", toDateString(Date.now()), false);
-
-    // Any response not being processed asynchronously must have an associated
-    // Content-Length header for reasons of backwards compatibility with the
-    // initial server, which fully buffered every response before sending it.
-    // Beyond that, however, it's good to do this anyway because otherwise it's
-    // impossible to test behaviors that depend on the presence or absence of a
-    // Content-Length header.
-    if (!this._processAsync)
-    {
-      dumpn("*** non-async response, set Content-Length");
-
-      var bodyStream = this._bodyInputStream;
-      var avail = bodyStream ? bodyStream.available() : 0;
-
-      // XXX assumes stream will always report the full amount of data available
-      headers.setHeader("Content-Length", "" + avail, false);
-    }
-
-
-    // construct and send response
-    dumpn("*** header post-processing completed, sending response head...");
-
-    // request-line
-    var preambleData = [statusLine];
-
-    // headers
-    var headEnum = headers.enumerator;
-    while (headEnum.hasMoreElements())
-    {
-      var fieldName = headEnum.getNext()
-                              .QueryInterface(Ci.nsISupportsString)
-                              .data;
-      var values = headers.getHeaderValues(fieldName);
-      for (var i = 0, sz = values.length; i < sz; i++)
-        preambleData.push(fieldName + ": " + values[i] + "\r\n");
-    }
-
-    // end request-line/headers
-    preambleData.push("\r\n");
-
-    var preamble = preambleData.join("");
-
-    var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null);
-    responseHeadPipe.outputStream.write(preamble, preamble.length);
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, cx)
-        {
-          dumpn("*** preamble copying started");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** preamble copying complete " +
-                "[status=0x" + statusCode.toString(16) + "]");
-
-          if (!components.isSuccessCode(statusCode))
-          {
-            dumpn("!!! header copying problems: non-success statusCode, " +
-                  "ending response");
-
-            response.end();
-          }
-          else
-          {
-            response._sendBody();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    var headerCopier = this._asyncCopier =
-      new WriteThroughCopier(responseHeadPipe.inputStream,
-                             this._connection.output,
-                             copyObserver, null);
-
-    responseHeadPipe.outputStream.close();
-
-    // Forbid setting any more headers or modifying the request line.
-    this._headers = null;
-  },
-
-  /**
-* Asynchronously writes the body of the response (or the entire response, if
-* seizePower() has been called) to the network.
-*/
-  _sendBody: function()
-  {
-    dumpn("*** _sendBody");
-
-    NS_ASSERT(!this._headers, "still have headers around but sending body?");
-
-    // If no body data was written, we're done
-    if (!this._bodyInputStream)
-    {
-      dumpn("*** empty body, response finished");
-      this.end();
-      return;
-    }
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, context)
-        {
-          dumpn("*** onStartRequest");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]");
-
-          if (statusCode === Cr.NS_BINDING_ABORTED)
-          {
-            dumpn("*** terminating copy observer without ending the response");
-          }
-          else
-          {
-            if (!components.isSuccessCode(statusCode))
-              dumpn("*** WARNING: non-success statusCode in onStopRequest");
-
-            response.end();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    dumpn("*** starting async copier of body data...");
-    this._asyncCopier =
-      new WriteThroughCopier(this._bodyInputStream, this._connection.output,
-                            copyObserver, null);
-  },
-
-  /** Ensures that this hasn't been ended. */
-  _ensureAlive: function()
-  {
-    NS_ASSERT(!this._ended, "not handling response lifetime correctly");
-  }
-};
-
-/**
-* Size of the segments in the buffer used in storing response data and writing
-* it to the socket.
-*/
-Response.SEGMENT_SIZE = 8192;
-
-/** Serves double duty in WriteThroughCopier implementation. */
-function notImplemented()
-{
-  throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/** Returns true iff the given exception represents stream closure. */
-function streamClosed(e)
-{
-  return e === Cr.NS_BASE_STREAM_CLOSED ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED);
-}
-
-/** Returns true iff the given exception represents a blocked stream. */
-function wouldBlock(e)
-{
-  return e === Cr.NS_BASE_STREAM_WOULD_BLOCK ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK);
-}
-
-/**
-* Copies data from source to sink as it becomes available, when that data can
-* be written to sink without blocking.
-*
-* @param source : nsIAsyncInputStream
-* the stream from which data is to be read
-* @param sink : nsIAsyncOutputStream
-* the stream to which data is to be copied
-* @param observer : nsIRequestObserver
-* an observer which will be notified when the copy starts and finishes
-* @param context : nsISupports
-* context passed to observer when notified of start/stop
-* @throws NS_ERROR_NULL_POINTER
-* if source, sink, or observer are null
-*/
-function WriteThroughCopier(source, sink, observer, context)
-{
-  if (!source || !sink || !observer)
-    throw Cr.NS_ERROR_NULL_POINTER;
-
-  /** Stream from which data is being read. */
-  this._source = source;
-
-  /** Stream to which data is being written. */
-  this._sink = sink;
-
-  /** Observer watching this copy. */
-  this._observer = observer;
-
-  /** Context for the observer watching this. */
-  this._context = context;
-
-  /**
-* True iff this is currently being canceled (cancel has been called, the
-* callback may not yet have been made).
-*/
-  this._canceled = false;
-
-  /**
-* False until all data has been read from input and written to output, at
-* which point this copy is completed and cancel() is asynchronously called.
-*/
-  this._completed = false;
-
-  /** Required by nsIRequest, meaningless. */
-  this.loadFlags = 0;
-  /** Required by nsIRequest, meaningless. */
-  this.loadGroup = null;
-  /** Required by nsIRequest, meaningless. */
-  this.name = "response-body-copy";
-
-  /** Status of this request. */
-  this.status = Cr.NS_OK;
-
-  /** Arrays of byte strings waiting to be written to output. */
-  this._pendingData = [];
-
-  // start copying
-  try
-  {
-    observer.onStartRequest(this, context);
-    this._waitToReadData();
-    this._waitForSinkClosure();
-  }
-  catch (e)
-  {
-    dumpn("!!! error starting copy: " + e +
-          ("lineNumber" in e ? ", line " + e.lineNumber : ""));
-    dumpn(e.stack);
-    this.cancel(Cr.NS_ERROR_UNEXPECTED);
-  }
-}
-WriteThroughCopier.prototype =
-{
-  /* nsISupports implementation */
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIInputStreamCallback) ||
-        iid.equals(Ci.nsIOutputStreamCallback) ||
-        iid.equals(Ci.nsIRequest) ||
-        iid.equals(Ci.nsISupports))
-    {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Receives a more-data-in-input notification and writes the corresponding
-* data to the output.
-*
-* @param input : nsIAsyncInputStream
-* the input stream on whose data we have been waiting
-*/
-  onInputStreamReady: function(input)
-  {
-    if (this._source === null)
-      return;
-
-    dumpn("*** onInputStreamReady");
-
-    //
-    // Ordinarily we'll read a non-zero amount of data from input, queue it up
-    // to be written and then wait for further callbacks. The complications in
-    // this method are the cases where we deviate from that behavior when errors
-    // occur or when copying is drawing to a finish.
-    //
-    // The edge cases when reading data are:
-    //
-    // Zero data is read
-    // If zero data was read, we're at the end of available data, so we can
-    // should stop reading and move on to writing out what we have (or, if
-    // we've already done that, onto notifying of completion).
-    // A stream-closed exception is thrown
-    // This is effectively a less kind version of zero data being read; the
-    // only difference is that we notify of completion with that result
-    // rather than with NS_OK.
-    // Some other exception is thrown
-    // This is the least kind result. We don't know what happened, so we
-    // act as though the stream closed except that we notify of completion
-    // with the result NS_ERROR_UNEXPECTED.
-    //
-
-    var bytesWanted = 0, bytesConsumed = -1;
-    try
-    {
-      input = new BinaryInputStream(input);
-
-      bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE);
-      dumpn("*** input wanted: " + bytesWanted);
-
-      if (bytesWanted > 0)
-      {
-        var data = input.readByteArray(bytesWanted);
-        bytesConsumed = data.length;
-        this._pendingData.push(String.fromCharCode.apply(String, data));
-      }
-
-      dumpn("*** " + bytesConsumed + " bytes read");
-
-      // Handle the zero-data edge case in the same place as all other edge
-      // cases are handled.
-      if (bytesWanted === 0)
-        throw Cr.NS_BASE_STREAM_CLOSED;
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** input stream closed");
-        e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED;
-      }
-      else
-      {
-        dumpn("!!! unexpected error reading from input, canceling: " + e);
-        e = Cr.NS_ERROR_UNEXPECTED;
-      }
-
-      this._doneReadingSource(e);
-      return;
-    }
-
-    var pendingData = this._pendingData;
-
-    NS_ASSERT(bytesConsumed > 0);
-    NS_ASSERT(pendingData.length > 0, "no pending data somehow?");
-    NS_ASSERT(pendingData[pendingData.length - 1].length > 0,
-              "buffered zero bytes of data?");
-
-    NS_ASSERT(this._source !== null);
-
-    // Reading has gone great, and we've gotten data to write now. What if we
-    // don't have a place to write that data, because output went away just
-    // before this read? Drop everything on the floor, including new data, and
-    // cancel at this point.
-    if (this._sink === null)
-    {
-      pendingData.length = 0;
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we've read the data, and we know we have a place to write it. We
-    // need to queue up the data to be written, but *only* if none is queued
-    // already -- if data's already queued, the code that actually writes the
-    // data will make sure to wait on unconsumed pending data.
-    try
-    {
-      if (pendingData.length === 1)
-        this._waitToWriteData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to write data just read, swallowing and " +
-            "writing only what we already have: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Whee! We successfully read some data, and it's successfully queued up to
-    // be written. All that remains now is to wait for more data to read.
-    try
-    {
-      this._waitToReadData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to read more data: " + e);
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-    }
-  },
-
-
-  // NSIOUTPUTSTREAMCALLBACK
-
-  /**
-* Callback when data may be written to the output stream without blocking, or
-* when the output stream has been closed.
-*
-* @param output : nsIAsyncOutputStream
-* the output stream on whose writability we've been waiting, also known as
-* this._sink
-*/
-  onOutputStreamReady: function(output)
-  {
-    if (this._sink === null)
-      return;
-
-    dumpn("*** onOutputStreamReady");
-
-    var pendingData = this._pendingData;
-    if (pendingData.length === 0)
-    {
-      // There's no pending data to write. The only way this can happen is if
-      // we're waiting on the output stream's closure, so we can respond to a
-      // copying failure as quickly as possible (rather than waiting for data to
-      // be available to read and then fail to be copied). Therefore, we must
-      // be done now -- don't bother to attempt to write anything and wrap
-      // things up.
-      dumpn("!!! output stream closed prematurely, ending copy");
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-
-    NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?");
-
-    //
-    // Write out the first pending quantum of data. The possible errors here
-    // are:
-    //
-    // The write might fail because we can't write that much data
-    // Okay, we've written what we can now, so re-queue what's left and
-    // finish writing it out later.
-    // The write failed because the stream was closed
-    // Discard pending data that we can no longer write, stop reading, and
-    // signal that copying finished.
-    // Some other error occurred.
-    // Same as if the stream were closed, but notify with the status
-    // NS_ERROR_UNEXPECTED so the observer knows something was wonky.
-    //
-
-    try
-    {
-      var quantum = pendingData[0];
-
-      // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on
-      // undefined behavior! We're only using this because writeByteArray
-      // is unusably broken for asynchronous output streams; see bug 532834
-      // for details.
-      var bytesWritten = output.write(quantum, quantum.length);
-      if (bytesWritten === quantum.length)
-        pendingData.shift();
-      else
-        pendingData[0] = quantum.substring(bytesWritten);
-
-      dumpn("*** wrote " + bytesWritten + " bytes of data");
-    }
-    catch (e)
-    {
-      if (wouldBlock(e))
-      {
-        NS_ASSERT(pendingData.length > 0,
-                  "stream-blocking exception with no data to write?");
-        NS_ASSERT(pendingData[0].length > 0,
-                  "stream-blocking exception with empty quantum?");
-        this._waitToWriteData();
-        return;
-      }
-
-      if (streamClosed(e))
-        dumpn("!!! output stream prematurely closed, signaling error...");
-      else
-        dumpn("!!! unknown error: " + e + ", quantum=" + quantum);
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // The day is ours! Quantum written, now let's see if we have more data
-    // still to write.
-    try
-    {
-      if (pendingData.length > 0)
-      {
-        this._waitToWriteData();
-        return;
-      }
-    }
-    catch (e)
-    {
-      dumpn("!!! unexpected error waiting to write pending data: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we have no more pending data to write -- but might we get more in
-    // the future?
-    if (this._source !== null)
-    {
-      /*
-* If we might, then wait for the output stream to be closed. (We wait
-* only for closure because we have no data to write -- and if we waited
-* for a specific amount of data, we would get repeatedly notified for no
-* reason if over time the output stream permitted more and more data to
-* be written to it without blocking.)
-*/
-       this._waitForSinkClosure();
-    }
-    else
-    {
-      /*
-* On the other hand, if we can't have more data because the input
-* stream's gone away, then it's time to notify of copy completion.
-* Victory!
-*/
-      this._sink = null;
-      this._cancelOrDispatchCancelCallback(Cr.NS_OK);
-    }
-  },
-
-
-  // NSIREQUEST
-
-  /** Returns true if the cancel observer hasn't been notified yet. */
-  isPending: function()
-  {
-    return !this._completed;
-  },
-
-  /** Not implemented, don't use! */
-  suspend: notImplemented,
-  /** Not implemented, don't use! */
-  resume: notImplemented,
-
-  /**
-* Cancels data reading from input, asynchronously writes out any pending
-* data, and causes the observer to be notified with the given error code when
-* all writing has finished.
-*
-* @param status : nsresult
-* the status to pass to the observer when data copying has been canceled
-*/
-  cancel: function(status)
-  {
-    dumpn("*** cancel(" + status.toString(16) + ")");
-
-    if (this._canceled)
-    {
-      dumpn("*** suppressing a late cancel");
-      return;
-    }
-
-    this._canceled = true;
-    this.status = status;
-
-    // We could be in the middle of absolutely anything at this point. Both
-    // input and output might still be around, we might have pending data to
-    // write, and in general we know nothing about the state of the world. We
-    // therefore must assume everything's in progress and take everything to its
-    // final steady state (or so far as it can go before we need to finish
-    // writing out remaining data).
-
-    this._doneReadingSource(status);
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Stop reading input if we haven't already done so, passing e as the status
-* when closing the stream, and kick off a copy-completion notice if no more
-* data remains to be written.
-*
-* @param e : nsresult
-* the status to be used when closing the input stream
-*/
-  _doneReadingSource: function(e)
-  {
-    dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
-
-    this._finishSource(e);
-    if (this._pendingData.length === 0)
-      this._sink = null;
-    else
-      NS_ASSERT(this._sink !== null, "null output?");
-
-    // If we've written out all data read up to this point, then it's time to
-    // signal completion.
-    if (this._sink === null)
-    {
-      NS_ASSERT(this._pendingData.length === 0, "pending data still?");
-      this._cancelOrDispatchCancelCallback(e);
-    }
-  },
-
-  /**
-* Stop writing output if we haven't already done so, discard any data that
-* remained to be sent, close off input if it wasn't already closed, and kick
-* off a copy-completion notice.
-*
-* @param e : nsresult
-* the status to be used when closing input if it wasn't already closed
-*/
-  _doneWritingToSink: function(e)
-  {
-    dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")");
-
-    this._pendingData.length = 0;
-    this._sink = null;
-    this._doneReadingSource(e);
-  },
-
-  /**
-* Completes processing of this copy: either by canceling the copy if it
-* hasn't already been canceled using the provided status, or by dispatching
-* the cancel callback event (with the originally provided status, of course)
-* if it already has been canceled.
-*
-* @param status : nsresult
-* the status code to use to cancel this, if this hasn't already been
-* canceled
-*/
-  _cancelOrDispatchCancelCallback: function(status)
-  {
-    dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")");
-
-    NS_ASSERT(this._source === null, "should have finished input");
-    NS_ASSERT(this._sink === null, "should have finished output");
-    NS_ASSERT(this._pendingData.length === 0, "should have no pending data");
-
-    if (!this._canceled)
-    {
-      this.cancel(status);
-      return;
-    }
-
-    var self = this;
-    var event =
-      {
-        run: function()
-        {
-          dumpn("*** onStopRequest async callback");
-
-          self._completed = true;
-          try
-          {
-            self._observer.onStopRequest(self, self._context, self.status);
-          }
-          catch (e)
-          {
-            NS_ASSERT(false,
-                      "how are we throwing an exception here? we control " +
-                      "all the callers! " + e);
-          }
-        }
-      };
-
-    gThreadManager.dispatchToMainThread(event);
-  },
-
-  /**
-* Kicks off another wait for more data to be available from the input stream.
-*/
-  _waitToReadData: function()
-  {
-    dumpn("*** _waitToReadData");
-    this._source.asyncWait(this, 0, Response.SEGMENT_SIZE,
-                           gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off another wait until data can be written to the output stream.
-*/
-  _waitToWriteData: function()
-  {
-    dumpn("*** _waitToWriteData");
-
-    var pendingData = this._pendingData;
-    NS_ASSERT(pendingData.length > 0, "no pending data to write?");
-    NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?");
-
-    this._sink.asyncWait(this, 0, pendingData[0].length,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off a wait for the sink to which data is being copied to be closed.
-* We wait for stream closure when we don't have any data to be copied, rather
-* than waiting to write a specific amount of data. We can't wait to write
-* data because the sink might be infinitely writable, and if no data appears
-* in the source for a long time we might have to spin quite a bit waiting to
-* write, waiting to write again, &c. Waiting on stream closure instead means
-* we'll get just one notification if the sink dies. Note that when data
-* starts arriving from the sink we'll resume waiting for data to be written,
-* dropping this closure-only callback entirely.
-*/
-  _waitForSinkClosure: function()
-  {
-    dumpn("*** _waitForSinkClosure");
-
-    this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Closes input with the given status, if it hasn't already been closed;
-* otherwise a no-op.
-*
-* @param status : nsresult
-* status code use to close the source stream if necessary
-*/
-  _finishSource: function(status)
-  {
-    dumpn("*** _finishSource(" + status.toString(16) + ")");
-
-    if (this._source !== null)
-    {
-      this._source.closeWithStatus(status);
-      this._source = null;
-    }
-  }
-};
-
-
-/**
-* A container for utility functions used with HTTP headers.
-*/
-const headerUtils =
-{
-  /**
-* Normalizes fieldName (by converting it to lowercase) and ensures it is a
-* valid header field name (although not necessarily one specified in RFC
-* 2616).
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not match the field-name production in RFC 2616
-* @returns string
-* fieldName converted to lowercase if it is a valid header, for characters
-* where case conversion is possible
-*/
-  normalizeFieldName: function(fieldName)
-  {
-    if (fieldName == "")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    for (var i = 0, sz = fieldName.length; i < sz; i++)
-    {
-      if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
-      {
-        dumpn(fieldName + " is not a valid header field name!");
-        throw Cr.NS_ERROR_INVALID_ARG;
-      }
-    }
-
-    return fieldName.toLowerCase();
-  },
-
-  /**
-* Ensures that fieldValue is a valid header field value (although not
-* necessarily as specified in RFC 2616 if the corresponding field name is
-* part of the HTTP protocol), normalizes the value if it is, and
-* returns the normalized value.
-*
-* @param fieldValue : string
-* a value to be normalized as an HTTP header field value
-* @throws NS_ERROR_INVALID_ARG
-* if fieldValue does not match the field-value production in RFC 2616
-* @returns string
-* fieldValue as a normalized HTTP header field value
-*/
-  normalizeFieldValue: function(fieldValue)
-  {
-    // field-value = *( field-content | LWS )
-    // field-content = <the OCTETs making up the field-value
-    // and consisting of either *TEXT or combinations
-    // of token, separators, and quoted-string>
-    // TEXT = <any OCTET except CTLs,
-    // but including LWS>
-    // LWS = [CRLF] 1*( SP | HT )
-    //
-    // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-    // qdtext = <any TEXT except <">>
-    // quoted-pair = "\" CHAR
-    // CHAR = <any US-ASCII character (octets 0 - 127)>
-
-    // Any LWS that occurs between field-content MAY be replaced with a single
-    // SP before interpreting the field value or forwarding the message
-    // downstream (section 4.2); we replace 1*LWS with a single SP
-    var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
-
-    // remove leading/trailing LWS (which has been converted to SP)
-    val = val.replace(/^ +/, "").replace(/ +$/, "");
-
-    // that should have taken care of all CTLs, so val should contain no CTLs
-    for (var i = 0, len = val.length; i < len; i++)
-      if (isCTL(val.charCodeAt(i)))
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
-    // normalize, however, so this can be construed as a tightening of the
-    // spec and not entirely as a bug
-    return val;
-  }
-};
-
-
-
-/**
-* Converts the given string into a string which is safe for use in an HTML
-* context.
-*
-* @param str : string
-* the string to make HTML-safe
-* @returns string
-* an HTML-safe version of str
-*/
-function htmlEscape(str)
-{
-  // this is naive, but it'll work
-  var s = "";
-  for (var i = 0; i < str.length; i++)
-    s += "&#" + str.charCodeAt(i) + ";";
-  return s;
-}
-
-
-/**
-* Constructs an object representing an HTTP version (see section 3.1).
-*
-* @param versionString
-* a string of the form "#.#", where # is an non-negative decimal integer with
-* or without leading zeros
-* @throws
-* if versionString does not specify a valid HTTP version number
-*/
-function nsHttpVersion(versionString)
-{
-  var matches = /^(\d+)\.(\d+)$/.exec(versionString);
-  if (!matches)
-    throw "Not a valid HTTP version!";
-
-  /** The major version number of this, as a number. */
-  this.major = parseInt(matches[1], 10);
-
-  /** The minor version number of this, as a number. */
-  this.minor = parseInt(matches[2], 10);
-
-  if (isNaN(this.major) || isNaN(this.minor) ||
-      this.major < 0 || this.minor < 0)
-    throw "Not a valid HTTP version!";
-}
-nsHttpVersion.prototype =
-{
-  /**
-* Returns the standard string representation of the HTTP version represented
-* by this (e.g., "1.1").
-*/
-  toString: function ()
-  {
-    return this.major + "." + this.minor;
-  },
-
-  /**
-* Returns true if this represents the same HTTP version as otherVersion,
-* false otherwise.
-*
-* @param otherVersion : nsHttpVersion
-* the version to compare against this
-*/
-  equals: function (otherVersion)
-  {
-    return this.major == otherVersion.major &&
-           this.minor == otherVersion.minor;
-  },
-
-  /** True if this >= otherVersion, false otherwise. */
-  atLeast: function(otherVersion)
-  {
-    return this.major > otherVersion.major ||
-           (this.major == otherVersion.major &&
-            this.minor >= otherVersion.minor);
-  }
-};
-
-nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0");
-nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1");
-
-
-/**
-* An object which stores HTTP headers for a request or response.
-*
-* Note that since headers are case-insensitive, this object converts headers to
-* lowercase before storing them. This allows the getHeader and hasHeader
-* methods to work correctly for any case of a header, but it means that the
-* values returned by .enumerator may not be equal case-sensitively to the
-* values passed to setHeader when adding headers to this.
-*/
-function nsHttpHeaders()
-{
-  /**
-* A hash of headers, with header field names as the keys and header field
-* values as the values. Header field names are case-insensitive, but upon
-* insertion here they are converted to lowercase. Header field values are
-* normalized upon insertion to contain no leading or trailing whitespace.
-*
-* Note also that per RFC 2616, section 4.2, two headers with the same name in
-* a message may be treated as one header with the same field name and a field
-* value consisting of the separate field values joined together with a "," in
-* their original order. This hash stores multiple headers with the same name
-* in this manner.
-*/
-  this._headers = {};
-}
-nsHttpHeaders.prototype =
-{
-  /**
-* Sets the header represented by name and value in this.
-*
-* @param name : string
-* the header name
-* @param value : string
-* the header value
-* @throws NS_ERROR_INVALID_ARG
-* if name or value is not a valid header component
-*/
-  setHeader: function(fieldName, fieldValue, merge)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    var value = headerUtils.normalizeFieldValue(fieldValue);
-
-    // The following three headers are stored as arrays because their real-world
-    // syntax prevents joining individual headers into a single header using
-    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
-    if (merge && name in this._headers)
-    {
-      if (name === "www-authenticate" ||
-          name === "proxy-authenticate" ||
-          name === "set-cookie")
-      {
-        this._headers[name].push(value);
-      }
-      else
-      {
-        this._headers[name][0] += "," + value;
-        NS_ASSERT(this._headers[name].length === 1,
-            "how'd a non-special header have multiple values?")
-      }
-    }
-    else
-    {
-      this._headers[name] = [value];
-    }
-  },
-
-  /**
-* Returns the value for the header specified by this.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns string
-* the field value for the given header, possibly with non-semantic changes
-* (i.e., leading/trailing whitespace stripped, whitespace runs replaced
-* with spaces, etc.) at the option of the implementation; multiple
-* instances of the header will be combined with a comma, except for
-* the three headers noted in the description of getHeaderValues
-*/
-  getHeader: function(fieldName)
-  {
-    return this.getHeaderValues(fieldName).join("\n");
-  },
-
-  /**
-* Returns the value for the header specified by fieldName as an array.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns [string]
-* an array of all the header values in this for the given
-* header name. Header values will generally be collapsed
-* into a single header by joining all header values together
-* with commas, but certain headers (Proxy-Authenticate,
-* WWW-Authenticate, and Set-Cookie) violate the HTTP spec
-* and cannot be collapsed in this manner. For these headers
-* only, the returned array may contain multiple elements if
-* that header has been added more than once.
-*/
-  getHeaderValues: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-
-    if (name in this._headers)
-      return this._headers[name];
-    else
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-  },
-
-  /**
-* Returns true if a header with the given field name exists in this, false
-* otherwise.
-*
-* @param fieldName : string
-* the field name whose existence is to be determined in this
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @returns boolean
-* true if the header's present, false otherwise
-*/
-  hasHeader: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    return (name in this._headers);
-  },
-
-  /**
-* Returns a new enumerator over the field names of the headers in this, as
-* nsISupportsStrings. The names returned will be in lowercase, regardless of
-* how they were input using setHeader (header names are case-insensitive per
-* RFC 2616).
-*/
-  get enumerator()
-  {
-    var headers = [];
-    for (var i in this._headers)
-    {
-      var supports = new SupportsString();
-      supports.data = i;
-      headers.push(supports);
-    }
-
-    return new nsSimpleEnumerator(headers);
-  }
-};
-
-
-/**
-* Constructs an nsISimpleEnumerator for the given array of items.
-*
-* @param items : Array
-* the items, which must all implement nsISupports
-*/
-function nsSimpleEnumerator(items)
-{
-  this._items = items;
-  this._nextIndex = 0;
-}
-nsSimpleEnumerator.prototype =
-{
-  hasMoreElements: function()
-  {
-    return this._nextIndex < this._items.length;
-  },
-  getNext: function()
-  {
-    if (!this.hasMoreElements())
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    return this._items[this._nextIndex++];
-  },
-  QueryInterface: function(aIID)
-  {
-    if (Ci.nsISimpleEnumerator.equals(aIID) ||
-        Ci.nsISupports.equals(aIID))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-
-/**
-* A representation of the data in an HTTP request.
-*
-* @param port : uint
-* the port on which the server receiving this request runs
-*/
-function Request(port)
-{
-  /** Method of this request, e.g. GET or POST. */
-  this._method = "";
-
-  /** Path of the requested resource; empty paths are converted to '/'. */
-  this._path = "";
-
-  /** Query string, if any, associated with this request (not including '?'). */
-  this._queryString = "";
-
-  /** Scheme of requested resource, usually http, always lowercase. */
-  this._scheme = "http";
-
-  /** Hostname on which the requested resource resides. */
-  this._host = undefined;
-
-  /** Port number over which the request was received. */
-  this._port = port;
-
-  var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null);
-
-  /** Stream from which data in this request's body may be read. */
-  this._bodyInputStream = bodyPipe.inputStream;
-
-  /** Stream to which data in this request's body is written. */
-  this._bodyOutputStream = bodyPipe.outputStream;
-
-  /**
-* The headers in this request.
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* For the addition of ad-hoc properties and new functionality without having
-* to change nsIHttpRequest every time; currently lazily created, as its only
-* use is in directory listings.
-*/
-  this._bag = null;
-}
-Request.prototype =
-{
-  // SERVER METADATA
-
-  //
-  // see nsIHttpRequest.scheme
-  //
-  get scheme()
-  {
-    return this._scheme;
-  },
-
-  //
-  // see nsIHttpRequest.host
-  //
-  get host()
-  {
-    return this._host;
-  },
-
-  //
-  // see nsIHttpRequest.port
-  //
-  get port()
-  {
-    return this._port;
-  },
-
-  // REQUEST LINE
-
-  //
-  // see nsIHttpRequest.method
-  //
-  get method()
-  {
-    return this._method;
-  },
-
-  //
-  // see nsIHttpRequest.httpVersion
-  //
-  get httpVersion()
-  {
-    return this._httpVersion.toString();
-  },
-
-  //
-  // see nsIHttpRequest.path
-  //
-  get path()
-  {
-    return this._path;
-  },
-
-  //
-  // see nsIHttpRequest.queryString
-  //
-  get queryString()
-  {
-    return this._queryString;
-  },
-
-  // HEADERS
-
-  //
-  // see nsIHttpRequest.getHeader
-  //
-  getHeader: function(name)
-  {
-    return this._headers.getHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.hasHeader
-  //
-  hasHeader: function(name)
-  {
-    return this._headers.hasHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get headers()
-  {
-    return this._headers.enumerator;
-  },
-
-  //
-  // see nsIPropertyBag.enumerator
-  //
-  get enumerator()
-  {
-    this._ensurePropertyBag();
-    return this._bag.enumerator;
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get bodyInputStream()
-  {
-    return this._bodyInputStream;
-  },
-
-  //
-  // see nsIPropertyBag.getProperty
-  //
-  getProperty: function(name)
-  {
-    this._ensurePropertyBag();
-    return this._bag.getProperty(name);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /** Ensures a property bag has been created for ad-hoc behaviors. */
-  _ensurePropertyBag: function()
-  {
-    if (!this._bag)
-      this._bag = new WritablePropertyBag();
-  }
-};
-
-
-// XPCOM trappings
-if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason...
-    "generateNSGetFactory" in XPCOMUtils) {
-  var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]);
-}
-
-
-
-/**
-* Creates a new HTTP server listening for loopback traffic on the given port,
-* starts it, and runs the server until the server processes a shutdown request,
-* spinning an event loop so that events posted by the server's socket are
-* processed.
-*
-* This method is primarily intended for use in running this script from within
-* xpcshell and running a functional HTTP server without having to deal with
-* non-essential details.
-*
-* Note that running multiple servers using variants of this method probably
-* doesn't work, simply due to how the internal event loop is spun and stopped.
-*
-* @note
-* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code);
-* you should use this server as a component in Mozilla 1.8.
-* @param port
-* the port on which the server will run, or -1 if there exists no preference
-* for a specific port; note that attempting to use some values for this
-* parameter (particularly those below 1024) may cause this method to throw or
-* may result in the server being prematurely shut down
-* @param basePath
-* a local directory from which requests will be served (i.e., if this is
-* "/home/jwalden/" then a request to /index.html will load
-* /home/jwalden/index.html); if this is omitted, only the default URLs in
-* this server implementation will be functional
-*/
-function server(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  // if you're running this, you probably want to see debugging info
-  DEBUG = true;
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", SJS_TYPE);
-  srv.start(port);
-
-  gThreadManager.spinEventLoopUntil(() => srv.isStopped());
-
-  gThreadManager.spinEventLoopUntilEmpty();
-
-  DEBUG = false;
-}
-
-function startServerAsync(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", "sjs");
-  srv.start(port);
-  return srv;
-}
-
-exports.nsHttpServer = nsHttpServer;
-exports.ScriptableInputStream = ScriptableInputStream;
-exports.server = server;
-exports.startServerAsync = startServerAsync;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-script-messages-latency/main.js
+++ /dev/null
@@ -1,90 +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 { PageMod } = require("sdk/page-mod");
-const tabs = require("sdk/tabs");
-const { startServerAsync } = require("./httpd");
-const { setTimeout } = require("sdk/timers");
-
-const serverPort = 8099;
-
-exports.testContentScriptLatencyRegression = function*(assert) {
-  let server = startServerAsync(serverPort);
-  server.registerPathHandler("/", function handle(request, response) {
-    response.write(`<html>
-      <head>
-        <link rel="stylesheet" href="/slow.css">
-      </head>
-      <body>
-        slow loading page...
-      </body>
-    </html>`);
-  });
-
-  server.registerPathHandler("/slow.css", function handle(request, response) {
-    response.processAsync();
-    response.setHeader('Content-Type', 'text/css', false);
-    setTimeout(_ => {
-      response.write("body { background: red; }");
-      response.finish();
-    }, 2000);
-  });
-
-
-  let pageMod;
-
-  let worker = yield new Promise((resolve) => {
-    pageMod = PageMod({
-      include: "http://localhost:8099/",
-      attachTo: "top",
-      contentScriptWhen: "start",
-      contentScript: "new " + function ContentScriptScope() {
-        self.port.on("a-port-message", function () {
-          self.port.emit("document-ready-state", document.readyState);
-        });
-      },
-      onAttach: function(w) {
-        resolve(w);
-      }
-    });
-
-    tabs.open({
-      url: "http://localhost:8099/",
-      inBackground: true
-    });
-  });
-
-  worker.port.emit("a-port-message");
-
-  let waitForPortMessage = new Promise((resolve) => {
-    worker.port.once("document-ready-state", (msg) => {
-      resolve(msg);
-    });
-  });
-
-  let documentReadyState = yield waitForPortMessage;
-
-  assert.notEqual(
-    "complete", documentReadyState,
-    "content script received the port message when the page was still loading"
-  );
-
-  assert.notEqual(
-    "uninitialized", documentReadyState,
-    "content script should be frozen if document.readyState is still uninitialized"
-  );
-
-  assert.ok(
-    ["loading", "interactive"].includes(documentReadyState),
-    "content script message received with document.readyState was interactive or loading"
-  );
-
-  // Cleanup.
-  pageMod.destroy();
-  yield new Promise((resolve) => worker.tab.close(resolve));
-  yield new Promise((resolve) => server.stop(resolve));
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/content-script-messages-latency/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-
-{
-  "id": "content-script-messages-latency@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/contributors/main.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { id } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testContributors = function*(assert) {
-  let addon = yield getAddonByID(id);
-  let count = 0;
-  addon.contributors.forEach(({ name }) => {
-    assert.equal(name, ++count == 1 ? 'A' : 'B', 'The contributors keys are correct');
-  });
-  assert.equal(count, 2, 'The key count is correct');
-  assert.equal(addon.contributors.length, 2, 'The key length is correct');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/contributors/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-contributors@jetpack",
-  "contributors": [ "A", "B" ],
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/curly-id/lib/main.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 simple = require('sdk/simple-prefs');
-const service = require('sdk/preferences/service');
-const { id, preferencesBranch } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testCurlyID = function(assert) {
-  assert.equal(id, '{34a1eae1-c20a-464f-9b0e-000000000000}', 'curly ID is curly');
-  assert.equal(simple.prefs.test13, 26, 'test13 is 26');
-
-  simple.prefs.test14 = '15';
-  assert.equal(service.get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test14'), '15', 'test14 is 15');
-  assert.equal(service.get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test14'), simple.prefs.test14, 'simple test14 also 15');
-}
-
-// from `/test/test-self.js`, adapted to `sdk/test/assert` API
-exports.testSelfID = function*(assert) {
-  assert.equal(typeof(id), 'string', 'self.id is a string');
-  assert.ok(id.length > 0, 'self.id not empty');
-
-  let addon = yield getAddonByID(id);
-  assert.ok(addon, 'found addon with self.id');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/curly-id/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "id": "{34a1eae1-c20a-464f-9b0e-000000000000}",
-    "fullName": "curly ID test",
-    "author": "Tomislav Jovanovic",
-    "preferences": [{
-        "name": "test13",
-        "type": "integer",
-        "title": "test13",
-        "value": 26
-    }],
-    "main": "./lib/main.js",
-    "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/developers/main.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { id } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testDevelopers = function*(assert) {
-  let addon = yield getAddonByID(id);
-  let count = 0;
-  addon.developers.forEach(({ name }) => {
-    assert.equal(name, ++count == 1 ? 'A' : 'B', 'The developers keys are correct');
-  });
-  assert.equal(count, 2, 'The key count is correct');
-  assert.equal(addon.developers.length, 2, 'The key length is correct');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/developers/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "test-developers@jetpack",
-  "title": "Test developers package key",
-  "author": "Erik Vold",
-  "developers": [ "A", "B" ],
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/data/test-contentScriptFile.js
+++ /dev/null
@@ -1,5 +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/. */
-
-self.postMessage("msg from contentScriptFile");
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/data/test-page-worker.html
+++ /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/. -->
-
-<html>
-<head>
-    <meta charset="UTF-8">
-    <title>Page Worker test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/data/test-page-worker.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/. */
-
-
-// get title directly
-self.postMessage(["equal", document.title, "Page Worker test",
-            "Correct page title accessed directly"]);
-
-// get <p> directly
-var p = document.getElementById("paragraph");
-self.postMessage(["ok", !!p, "<p> can be accessed directly"]);
-self.postMessage(["equal", p.firstChild.nodeValue,
-            "Lorem ipsum dolor sit amet.",
-            "Correct text node expected"]);
-
-// Modify page
-var div = document.createElement("div");
-div.setAttribute("id", "block");
-div.appendChild(document.createTextNode("Test text created"));
-document.body.appendChild(div);
-
-// Check back the modification
-div = document.getElementById("block");
-self.postMessage(["ok", !!div, "<div> can be accessed directly"]);
-self.postMessage(["equal", div.firstChild.nodeValue,
-            "Test text created", "Correct text node expected"]);
-self.postMessage(["done"]);
-
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/data/test.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>foo</title>
-  </head>
-  <body>
-    <p>bar</p>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/fixtures.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { data } = require('sdk/self');
-
-exports.url = data.url;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/httpd.js
+++ /dev/null
@@ -1,5206 +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/. */
-
-/*
-* An implementation of an HTTP server both as a loadable script and as an XPCOM
-* component. See the accompanying README file for user documentation on
-* httpd.js.
-*/
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { components, CC, Cc, Ci, Cr, Cu } = require("chrome");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
-const PR_UINT32_MAX = Math.pow(2, 32) - 1;
-
-/** True if debugging output is enabled, false otherwise. */
-var DEBUG = false; // non-const *only* so tweakable in server tests
-
-/** True if debugging output should be timestamped. */
-var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests
-
-var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance();
-
-/**
-* Asserts that the given condition holds. If it doesn't, the given message is
-* dumped, a stack trace is printed, and an exception is thrown to attempt to
-* stop execution (which unfortunately must rely upon the exception not being
-* accidentally swallowed by the code that uses it).
-*/
-function NS_ASSERT(cond, msg)
-{
-  if (DEBUG && !cond)
-  {
-    dumpn("###!!!");
-    dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!"));
-    dumpn("###!!! Stack follows:");
-
-    var stack = new Error().stack.split(/\n/);
-    dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n"));
-
-    throw Cr.NS_ERROR_ABORT;
-  }
-}
-
-/** Constructs an HTTP error object. */
-function HttpError(code, description)
-{
-  this.code = code;
-  this.description = description;
-}
-HttpError.prototype =
-{
-  toString: function()
-  {
-    return this.code + " " + this.description;
-  }
-};
-
-/**
-* Errors thrown to trigger specific HTTP server responses.
-*/
-const HTTP_400 = new HttpError(400, "Bad Request");
-const HTTP_401 = new HttpError(401, "Unauthorized");
-const HTTP_402 = new HttpError(402, "Payment Required");
-const HTTP_403 = new HttpError(403, "Forbidden");
-const HTTP_404 = new HttpError(404, "Not Found");
-const HTTP_405 = new HttpError(405, "Method Not Allowed");
-const HTTP_406 = new HttpError(406, "Not Acceptable");
-const HTTP_407 = new HttpError(407, "Proxy Authentication Required");
-const HTTP_408 = new HttpError(408, "Request Timeout");
-const HTTP_409 = new HttpError(409, "Conflict");
-const HTTP_410 = new HttpError(410, "Gone");
-const HTTP_411 = new HttpError(411, "Length Required");
-const HTTP_412 = new HttpError(412, "Precondition Failed");
-const HTTP_413 = new HttpError(413, "Request Entity Too Large");
-const HTTP_414 = new HttpError(414, "Request-URI Too Long");
-const HTTP_415 = new HttpError(415, "Unsupported Media Type");
-const HTTP_417 = new HttpError(417, "Expectation Failed");
-
-const HTTP_500 = new HttpError(500, "Internal Server Error");
-const HTTP_501 = new HttpError(501, "Not Implemented");
-const HTTP_502 = new HttpError(502, "Bad Gateway");
-const HTTP_503 = new HttpError(503, "Service Unavailable");
-const HTTP_504 = new HttpError(504, "Gateway Timeout");
-const HTTP_505 = new HttpError(505, "HTTP Version Not Supported");
-
-/** Creates a hash with fields corresponding to the values in arr. */
-function array2obj(arr)
-{
-  var obj = {};
-  for (var i = 0; i < arr.length; i++)
-    obj[arr[i]] = arr[i];
-  return obj;
-}
-
-/** Returns an array of the integers x through y, inclusive. */
-function range(x, y)
-{
-  var arr = [];
-  for (var i = x; i <= y; i++)
-    arr.push(i);
-  return arr;
-}
-
-/** An object (hash) whose fields are the numbers of all HTTP error codes. */
-const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505)));
-
-
-/**
-* The character used to distinguish hidden files from non-hidden files, a la
-* the leading dot in Apache. Since that mechanism also hides files from
-* easy display in LXR, ls output, etc. however, we choose instead to use a
-* suffix character. If a requested file ends with it, we append another
-* when getting the file on the server. If it doesn't, we just look up that
-* file. Therefore, any file whose name ends with exactly one of the character
-* is "hidden" and available for use by the server.
-*/
-const HIDDEN_CHAR = "^";
-
-/**
-* The file name suffix indicating the file containing overridden headers for
-* a requested file.
-*/
-const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
-
-/** Type used to denote SJS scripts for CGI-like functionality. */
-const SJS_TYPE = "sjs";
-
-/** Base for relative timestamps produced by dumpn(). */
-var firstStamp = 0;
-
-/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */
-function dumpn(str)
-{
-  if (DEBUG)
-  {
-    var prefix = "HTTPD-INFO | ";
-    if (DEBUG_TIMESTAMP)
-    {
-      if (firstStamp === 0)
-        firstStamp = Date.now();
-
-      var elapsed = Date.now() - firstStamp; // milliseconds
-      var min = Math.floor(elapsed / 60000);
-      var sec = (elapsed % 60000) / 1000;
-
-      if (sec < 10)
-        prefix += min + ":0" + sec.toFixed(3) + " | ";
-      else
-        prefix += min + ":" + sec.toFixed(3) + " | ";
-    }
-
-    dump(prefix + str + "\n");
-  }
-}
-
-/** Dumps the current JS stack if DEBUG. */
-function dumpStack()
-{
-  // peel off the frames for dumpStack() and Error()
-  var stack = new Error().stack.split(/\n/).slice(2);
-  stack.forEach(dumpn);
-}
-
-
-/** The XPCOM thread manager. */
-var gThreadManager = null;
-
-/** The XPCOM prefs service. */
-var gRootPrefBranch = null;
-function getRootPrefBranch()
-{
-  if (!gRootPrefBranch)
-  {
-    gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"]
-                        .getService(Ci.nsIPrefBranch);
-  }
-  return gRootPrefBranch;
-}
-
-/**
-* JavaScript constructors for commonly-used classes; precreating these is a
-* speedup over doing the same from base principles. See the docs at
-* http://developer.mozilla.org/en/docs/components.Constructor for details.
-*/
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
-                                 "nsIScriptableInputStream",
-                                 "init");
-const Pipe = CC("@mozilla.org/pipe;1",
-                "nsIPipe",
-                "init");
-const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
-                           "nsIFileInputStream",
-                           "init");
-const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1",
-                                "nsIConverterInputStream",
-                                "init");
-const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
-                               "nsIWritablePropertyBag2");
-const SupportsString = CC("@mozilla.org/supports-string;1",
-                          "nsISupportsString");
-
-/* These two are non-const only so a test can overwrite them. */
-var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
-                            "nsIBinaryOutputStream",
-                            "setOutputStream");
-
-/**
-* Returns the RFC 822/1123 representation of a date.
-*
-* @param date : Number
-* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT
-* @returns string
-* the representation of the given date
-*/
-function toDateString(date)
-{
-  //
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // date1 = 2DIGIT SP month SP 4DIGIT
-  // ; day month year (e.g., 02 Jun 1982)
-  // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  // ; 00:00:00 - 23:59:59
-  // wkday = "Mon" | "Tue" | "Wed"
-  // | "Thu" | "Fri" | "Sat" | "Sun"
-  // month = "Jan" | "Feb" | "Mar" | "Apr"
-  // | "May" | "Jun" | "Jul" | "Aug"
-  // | "Sep" | "Oct" | "Nov" | "Dec"
-  //
-
-  const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-  const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-  /**
-* Processes a date and returns the encoded UTC time as a string according to
-* the format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toTime(date)
-  {
-    var hrs = date.getUTCHours();
-    var rv = (hrs < 10) ? "0" + hrs : hrs;
-
-    var mins = date.getUTCMinutes();
-    rv += ":";
-    rv += (mins < 10) ? "0" + mins : mins;
-
-    var secs = date.getUTCSeconds();
-    rv += ":";
-    rv += (secs < 10) ? "0" + secs : secs;
-
-    return rv;
-  }
-
-  /**
-* Processes a date and returns the encoded UTC date as a string according to
-* the date1 format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toDate1(date)
-  {
-    var day = date.getUTCDate();
-    var month = date.getUTCMonth();
-    var year = date.getUTCFullYear();
-
-    var rv = (day < 10) ? "0" + day : day;
-    rv += " " + monthStrings[month];
-    rv += " " + year;
-
-    return rv;
-  }
-
-  date = new Date(date);
-
-  const fmtString = "%wkday%, %date1% %time% GMT";
-  var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]);
-  rv = rv.replace("%time%", toTime(date));
-  return rv.replace("%date1%", toDate1(date));
-}
-
-/**
-* Prints out a human-readable representation of the object o and its fields,
-* omitting those whose names begin with "_" if showMembers != true (to ignore
-* "private" properties exposed via getters/setters).
-*/
-function printObj(o, showMembers)
-{
-  var s = "******************************\n";
-  s += "o = {\n";
-  for (var i in o)
-  {
-    if (typeof(i) != "string" ||
-        (showMembers || (i.length > 0 && i[0] != "_")))
-      s+= " " + i + ": " + o[i] + ",\n";
-  }
-  s += " };\n";
-  s += "******************************";
-  dumpn(s);
-}
-
-/**
-* Instantiates a new HTTP server.
-*/
-function nsHttpServer()
-{
-  if (!gThreadManager)
-    gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-
-  /** The port on which this server listens. */
-  this._port = undefined;
-
-  /** The socket associated with this. */
-  this._socket = null;
-
-  /** The handler used to process requests to this server. */
-  this._handler = new ServerHandler(this);
-
-  /** Naming information for this server. */
-  this._identity = new ServerIdentity();
-
-  /**
-* Indicates when the server is to be shut down at the end of the request.
-*/
-  this._doQuit = false;
-
-  /**
-* True if the socket in this is closed (and closure notifications have been
-* sent and processed if the socket was ever opened), false otherwise.
-*/
-  this._socketClosed = true;
-
-  /**
-* Used for tracking existing connections and ensuring that all connections
-* are properly cleaned up before server shutdown; increases by 1 for every
-* new incoming connection.
-*/
-  this._connectionGen = 0;
-
-  /**
-* Hash of all open connections, indexed by connection number at time of
-* creation.
-*/
-  this._connections = {};
-}
-nsHttpServer.prototype =
-{
-  classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"),
-
-  // NSISERVERSOCKETLISTENER
-
-  /**
-* Processes an incoming request coming in on the given socket and contained
-* in the given transport.
-*
-* @param socket : nsIServerSocket
-* the socket through which the request was served
-* @param trans : nsISocketTransport
-* the transport for the request/response
-* @see nsIServerSocketListener.onSocketAccepted
-*/
-  onSocketAccepted: function(socket, trans)
-  {
-    dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")");
-
-    dumpn(">>> new connection on " + trans.host + ":" + trans.port);
-
-    const SEGMENT_SIZE = 8192;
-    const SEGMENT_COUNT = 1024;
-    try
-    {
-      var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
-                       .QueryInterface(Ci.nsIAsyncInputStream);
-      var output = trans.openOutputStream(0, 0, 0);
-    }
-    catch (e)
-    {
-      dumpn("*** error opening transport streams: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    var connectionNumber = ++this._connectionGen;
-
-    try
-    {
-      var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
-      var reader = new RequestReader(conn);
-
-      // XXX add request timeout functionality here!
-
-      // Note: must use main thread here, or we might get a GC that will cause
-      // threadsafety assertions. We really need to fix XPConnect so that
-      // you can actually do things in multi-threaded JS. :-(
-      input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
-    }
-    catch (e)
-    {
-      // Assume this connection can't be salvaged and bail on it completely;
-      // don't attempt to close it so that we can assert that any connection
-      // being closed is in this._connections.
-      dumpn("*** error in initial request-processing stages: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    this._connections[connectionNumber] = conn;
-    dumpn("*** starting connection " + connectionNumber);
-  },
-
-  /**
-* Called when the socket associated with this is closed.
-*
-* @param socket : nsIServerSocket
-* the socket being closed
-* @param status : nsresult
-* the reason the socket stopped listening (NS_BINDING_ABORTED if the server
-* was stopped using nsIHttpServer.stop)
-* @see nsIServerSocketListener.onStopListening
-*/
-  onStopListening: function(socket, status)
-  {
-    dumpn(">>> shutting down server on port " + socket.port);
-    this._socketClosed = true;
-    if (!this._hasOpenConnections())
-    {
-      dumpn("*** no open connections, notifying async from onStopListening");
-
-      // Notify asynchronously so that any pending teardown in stop() has a
-      // chance to run first.
-      var self = this;
-      var stopEvent =
-        {
-          run: function()
-          {
-            dumpn("*** _notifyStopped async callback");
-            self._notifyStopped();
-          }
-        };
-      gThreadManager.dispatchToMainThread(stopEvent);
-    }
-  },
-
-  // NSIHTTPSERVER
-
-  //
-  // see nsIHttpServer.start
-  //
-  start: function(port)
-  {
-    this._start(port, "localhost")
-  },
-
-  _start: function(port, host)
-  {
-    if (this._socket)
-      throw Cr.NS_ERROR_ALREADY_INITIALIZED;
-
-    this._port = port;
-    this._doQuit = this._socketClosed = false;
-
-    this._host = host;
-
-    // The listen queue needs to be long enough to handle
-    // network.http.max-persistent-connections-per-server concurrent connections,
-    // plus a safety margin in case some other process is talking to
-    // the server as well.
-    var prefs = getRootPrefBranch();
-    var maxConnections;
-    try {
-      // Bug 776860: The original pref was removed in favor of this new one:
-      maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server") + 5;
-    }
-    catch(e) {
-      maxConnections = prefs.getIntPref("network.http.max-connections-per-server") + 5;
-    }
-
-    try
-    {
-      var loopback = true;
-      if (this._host != "127.0.0.1" && this._host != "localhost") {
-        var loopback = false;
-      }
-
-      var socket = new ServerSocket(this._port,
-                                    loopback, // true = localhost, false = everybody
-                                    maxConnections);
-      dumpn(">>> listening on port " + socket.port + ", " + maxConnections +
-            " pending connections");
-      socket.asyncListen(this);
-      this._identity._initialize(socket.port, host, true);
-      this._socket = socket;
-    }
-    catch (e)
-    {
-      dumpn("!!! could not start server on port " + port + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-  },
-
-  //
-  // see nsIHttpServer.stop
-  //
-  stop: function(callback)
-  {
-    if (!callback)
-      throw Cr.NS_ERROR_NULL_POINTER;
-    if (!this._socket)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    this._stopCallback = typeof callback === "function"
-                       ? callback
-                       : function() { callback.onStopped(); };
-
-    dumpn(">>> stopping listening on port " + this._socket.port);
-    this._socket.close();
-    this._socket = null;
-
-    // We can't have this identity any more, and the port on which we're running
-    // this server now could be meaningless the next time around.
-    this._identity._teardown();
-
-    this._doQuit = false;
-
-    // socket-close notification and pending request completion happen async
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (file && (!file.exists() || file.isDirectory()))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handler.registerFile(path, file);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/" ||
-        path.charAt(path.length - 1) != "/" ||
-        (directory &&
-         (!directory.exists() || !directory.isDirectory())))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping
-    // exists!
-
-    this._handler.registerDirectory(path, directory);
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    this._handler.registerPathHandler(path, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    this._handler.registerPrefixHandler(prefix, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(code, handler)
-  {
-    this._handler.registerErrorHandler(code, handler);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    this._handler.setIndexHandler(handler);
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    this._handler.registerContentType(ext, type);
-  },
-
-  //
-  // see nsIHttpServer.serverIdentity
-  //
-  get identity()
-  {
-    return this._identity;
-  },
-
-  //
-  // see nsIHttpServer.getState
-  //
-  getState: function(path, k)
-  {
-    return this._handler._getState(path, k);
-  },
-
-  //
-  // see nsIHttpServer.setState
-  //
-  setState: function(path, k, v)
-  {
-    return this._handler._setState(path, k, v);
-  },
-
-  //
-  // see nsIHttpServer.getSharedState
-  //
-  getSharedState: function(k)
-  {
-    return this._handler._getSharedState(k);
-  },
-
-  //
-  // see nsIHttpServer.setSharedState
-  //
-  setSharedState: function(k, v)
-  {
-    return this._handler._setSharedState(k, v);
-  },
-
-  //
-  // see nsIHttpServer.getObjectState
-  //
-  getObjectState: function(k)
-  {
-    return this._handler._getObjectState(k);
-  },
-
-  //
-  // see nsIHttpServer.setObjectState
-  //
-  setObjectState: function(k, v)
-  {
-    return this._handler._setObjectState(k, v);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NON-XPCOM PUBLIC API
-
-  /**
-* Returns true iff this server is not running (and is not in the process of
-* serving any requests still to be processed when the server was last
-* stopped after being run).
-*/
-  isStopped: function()
-  {
-    return this._socketClosed && !this._hasOpenConnections();
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /** True if this server has any open connections to it, false otherwise. */
-  _hasOpenConnections: function()
-  {
-    //
-    // If we have any open connections, they're tracked as numeric properties on
-    // |this._connections|. The non-standard __count__ property could be used
-    // to check whether there are any properties, but standard-wise, even
-    // looking forward to ES5, there's no less ugly yet still O(1) way to do
-    // this.
-    //
-    for (var n in this._connections)
-      return true;
-    return false;
-  },
-
-  /** Calls the server-stopped callback provided when stop() was called. */
-  _notifyStopped: function()
-  {
-    NS_ASSERT(this._stopCallback !== null, "double-notifying?");
-    NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now");
-
-    //
-    // NB: We have to grab this now, null out the member, *then* call the
-    // callback here, or otherwise the callback could (indirectly) futz with
-    // this._stopCallback by starting and immediately stopping this, at
-    // which point we'd be nulling out a field we no longer have a right to
-    // modify.
-    //
-    var callback = this._stopCallback;
-    this._stopCallback = null;
-    try
-    {
-      callback();
-    }
-    catch (e)
-    {
-      // not throwing because this is specified as being usually (but not
-      // always) asynchronous
-      dump("!!! error running onStopped callback: " + e + "\n");
-    }
-  },
-
-  /**
-* Notifies this server that the given connection has been closed.
-*
-* @param connection : Connection
-* the connection that was closed
-*/
-  _connectionClosed: function(connection)
-  {
-    NS_ASSERT(connection.number in this._connections,
-              "closing a connection " + this + " that we never added to the " +
-              "set of open connections?");
-    NS_ASSERT(this._connections[connection.number] === connection,
-              "connection number mismatch? " +
-              this._connections[connection.number]);
-    delete this._connections[connection.number];
-
-    // Fire a pending server-stopped notification if it's our responsibility.
-    if (!this._hasOpenConnections() && this._socketClosed)
-      this._notifyStopped();
-  },
-
-  /**
-* Requests that the server be shut down when possible.
-*/
-  _requestQuit: function()
-  {
-    dumpn(">>> requesting a quit");
-    dumpStack();
-    this._doQuit = true;
-  }
-};
-
-
-//
-// RFC 2396 section 3.2.2:
-//
-// host = hostname | IPv4address
-// hostname = *( domainlabel "." ) toplabel [ "." ]
-// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-//
-
-const HOST_REGEX =
-  new RegExp("^(?:" +
-               // *( domainlabel "." )
-               "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
-               // toplabel
-               "[a-z](?:[a-z0-9-]*[a-z0-9])?" +
-             "|" +
-               // IPv4 address
-               "\\d+\\.\\d+\\.\\d+\\.\\d+" +
-             ")$",
-             "i");
-
-
-/**
-* Represents the identity of a server. An identity consists of a set of
-* (scheme, host, port) tuples denoted as locations (allowing a single server to
-* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any
-* host/port). Any incoming request must be to one of these locations, or it
-* will be rejected with an HTTP 400 error. One location, denoted as the
-* primary location, is the location assigned in contexts where a location
-* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests.
-*
-* A single identity may contain at most one location per unique host/port pair;
-* other than that, no restrictions are placed upon what locations may
-* constitute an identity.
-*/
-function ServerIdentity()
-{
-  /** The scheme of the primary location. */
-  this._primaryScheme = "http";
-
-  /** The hostname of the primary location. */
-  this._primaryHost = "127.0.0.1"
-
-  /** The port number of the primary location. */
-  this._primaryPort = -1;
-
-  /**
-* The current port number for the corresponding server, stored so that a new
-* primary location can always be set if the current one is removed.
-*/
-  this._defaultPort = -1;
-
-  /**
-* Maps hosts to maps of ports to schemes, e.g. the following would represent
-* https://example.com:789/ and http://example.org/:
-*
-* {
-* "xexample.com": { 789: "https" },
-* "xexample.org": { 80: "http" }
-* }
-*
-* Note the "x" prefix on hostnames, which prevents collisions with special
-* JS names like "prototype".
-*/
-  this._locations = { "xlocalhost": {} };
-}
-ServerIdentity.prototype =
-{
-  // NSIHTTPSERVERIDENTITY
-
-  //
-  // see nsIHttpServerIdentity.primaryScheme
-  //
-  get primaryScheme()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryScheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryHost
-  //
-  get primaryHost()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryHost;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryPort
-  //
-  get primaryPort()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryPort;
-  },
-
-  //
-  // see nsIHttpServerIdentity.add
-  //
-  add: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      this._locations["x" + host] = entry = {};
-
-    entry[port] = scheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.remove
-  //
-  remove: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return false;
-
-    var present = port in entry;
-    delete entry[port];
-
-    if (this._primaryScheme == scheme &&
-        this._primaryHost == host &&
-        this._primaryPort == port &&
-        this._defaultPort !== -1)
-    {
-      // Always keep at least one identity in existence at any time, unless
-      // we're in the process of shutting down (the last condition above).
-      this._primaryPort = -1;
-      this._initialize(this._defaultPort, host, false);
-    }
-
-    return present;
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  has: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    return "x" + host in this._locations &&
-           scheme === this._locations["x" + host][port];
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  getScheme: function(host, port)
-  {
-    this._validate("http", host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return "";
-
-    return entry[port] || "";
-  },
-
-  //
-  // see nsIHttpServerIdentity.setPrimary
-  //
-  setPrimary: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    this.add(scheme, host, port);
-
-    this._primaryScheme = scheme;
-    this._primaryHost = host;
-    this._primaryPort = port;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Initializes the primary name for the corresponding server, based on the
-* provided port number.
-*/
-  _initialize: function(port, host, addSecondaryDefault)
-  {
-    this._host = host;
-    if (this._primaryPort !== -1)
-      this.add("http", host, port);
-    else
-      this.setPrimary("http", "localhost", port);
-    this._defaultPort = port;
-
-    // Only add this if we're being called at server startup
-    if (addSecondaryDefault && host != "127.0.0.1")
-      this.add("http", "127.0.0.1", port);
-  },
-
-  /**
-* Called at server shutdown time, unsets the primary location only if it was
-* the default-assigned location and removes the default location from the
-* set of locations used.
-*/
-  _teardown: function()
-  {
-    if (this._host != "127.0.0.1") {
-      // Not the default primary location, nothing special to do here
-      this.remove("http", "127.0.0.1", this._defaultPort);
-    }
-
-    // This is a *very* tricky bit of reasoning here; make absolutely sure the
-    // tests for this code pass before you commit changes to it.
-    if (this._primaryScheme == "http" &&
-        this._primaryHost == this._host &&
-        this._primaryPort == this._defaultPort)
-    {
-      // Make sure we don't trigger the readding logic in .remove(), then remove
-      // the default location.
-      var port = this._defaultPort;
-      this._defaultPort = -1;
-      this.remove("http", this._host, port);
-
-      // Ensure a server start triggers the setPrimary() path in ._initialize()
-      this._primaryPort = -1;
-    }
-    else
-    {
-      // No reason not to remove directly as it's not our primary location
-      this.remove("http", this._host, this._defaultPort);
-    }
-  },
-
-  /**
-* Ensures scheme, host, and port are all valid with respect to RFC 2396.
-*
-* @throws NS_ERROR_ILLEGAL_VALUE
-* if any argument doesn't match the corresponding production
-*/
-  _validate: function(scheme, host, port)
-  {
-    if (scheme !== "http" && scheme !== "https")
-    {
-      dumpn("*** server only supports http/https schemes: '" + scheme + "'");
-      dumpStack();
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (!HOST_REGEX.test(host))
-    {
-      dumpn("*** unexpected host: '" + host + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (port < 0 || port > 65535)
-    {
-      dumpn("*** unexpected port: '" + port + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-  }
-};
-
-
-/**
-* Represents a connection to the server (and possibly in the future the thread
-* on which the connection is processed).
-*
-* @param input : nsIInputStream
-* stream from which incoming data on the connection is read
-* @param output : nsIOutputStream
-* stream to write data out the connection
-* @param server : nsHttpServer
-* the server handling the connection
-* @param port : int
-* the port on which the server is running
-* @param outgoingPort : int
-* the outgoing port used by this connection
-* @param number : uint
-* a serial number used to uniquely identify this connection
-*/
-function Connection(input, output, server, port, outgoingPort, number)
-{
-  dumpn("*** opening new connection " + number + " on port " + outgoingPort);
-
-  /** Stream of incoming data. */
-  this.input = input;
-
-  /** Stream for outgoing data. */
-  this.output = output;
-
-  /** The server associated with this request. */
-  this.server = server;
-
-  /** The port on which the server is running. */
-  this.port = port;
-
-  /** The outgoing poort used by this connection. */
-  this._outgoingPort = outgoingPort;
-
-  /** The serial number of this connection. */
-  this.number = number;
-
-  /**
-* The request for which a response is being generated, null if the
-* incoming request has not been fully received or if it had errors.
-*/
-  this.request = null;
-
-  /** State variables for debugging. */
-  this._closed = this._processed = false;
-}
-Connection.prototype =
-{
-  /** Closes this connection's input/output streams. */
-  close: function()
-  {
-    dumpn("*** closing connection " + this.number +
-          " on port " + this._outgoingPort);
-
-    this.input.close();
-    this.output.close();
-    this._closed = true;
-
-    var server = this.server;
-    server._connectionClosed(this);
-
-    // If an error triggered a server shutdown, act on it now
-    if (server._doQuit)
-      server.stop(function() { /* not like we can do anything better */ });
-  },
-
-  /**
-* Initiates processing of this connection, using the data in the given
-* request.
-*
-* @param request : Request
-* the request which should be processed
-*/
-  process: function(request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-
-    this.request = request;
-    this.server._handler.handleResponse(this);
-  },
-
-  /**
-* Initiates processing of this connection, generating a response with the
-* given HTTP error code.
-*
-* @param code : uint
-* an HTTP code, so in the range [0, 1000)
-* @param request : Request
-* incomplete data about the incoming request (since there were errors
-* during its processing
-*/
-  processError: function(code, request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-    this.request = request;
-    this.server._handler.handleError(code, this);
-  },
-
-  /** Converts this to a string for debugging purposes. */
-  toString: function()
-  {
-    return "<Connection(" + this.number +
-           (this.request ? ", " + this.request.path : "") +"): " +
-           (this._closed ? "closed" : "open") + ">";
-  }
-};
-
-
-
-/** Returns an array of count bytes from the given input stream. */
-function readBytes(inputStream, count)
-{
-  return new BinaryInputStream(inputStream).readByteArray(count);
-}
-
-
-
-/** Request reader processing states; see RequestReader for details. */
-const READER_IN_REQUEST_LINE = 0;
-const READER_IN_HEADERS = 1;
-const READER_IN_BODY = 2;
-const READER_FINISHED = 3;
-
-
-/**
-* Reads incoming request data asynchronously, does any necessary preprocessing,
-* and forwards it to the request handler. Processing occurs in three states:
-*
-* READER_IN_REQUEST_LINE Reading the request's status line
-* READER_IN_HEADERS Reading headers in the request
-* READER_IN_BODY Reading the body of the request
-* READER_FINISHED Entire request has been read and processed
-*
-* During the first two stages, initial metadata about the request is gathered
-* into a Request object. Once the status line and headers have been processed,
-* we start processing the body of the request into the Request. Finally, when
-* the entire body has been read, we create a Response and hand it off to the
-* ServerHandler to be given to the appropriate request handler.
-*
-* @param connection : Connection
-* the connection for the request being read
-*/
-function RequestReader(connection)
-{
-  /** Connection metadata for this request. */
-  this._connection = connection;
-
-  /**
-* A container providing line-by-line access to the raw bytes that make up the
-* data which has been read from the connection but has not yet been acted
-* upon (by passing it to the request handler or by extracting request
-* metadata from it).
-*/
-  this._data = new LineData();
-
-  /**
-* The amount of data remaining to be read from the body of this request.
-* After all headers in the request have been read this is the value in the
-* Content-Length header, but as the body is read its value decreases to zero.
-*/
-  this._contentLength = 0;
-
-  /** The current state of parsing the incoming request. */
-  this._state = READER_IN_REQUEST_LINE;
-
-  /** Metadata constructed from the incoming request for the request handler. */
-  this._metadata = new Request(connection.port);
-
-  /**
-* Used to preserve state if we run out of line data midway through a
-* multi-line header. _lastHeaderName stores the name of the header, while
-* _lastHeaderValue stores the value we've seen so far for the header.
-*
-* These fields are always either both undefined or both strings.
-*/
-  this._lastHeaderName = this._lastHeaderValue = undefined;
-}
-RequestReader.prototype =
-{
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Called when more data from the incoming request is available. This method
-* then reads the available data from input and deals with that data as
-* necessary, depending upon the syntax of already-downloaded data.
-*
-* @param input : nsIAsyncInputStream
-* the stream of incoming data from the connection
-*/
-  onInputStreamReady: function(input)
-  {
-    dumpn("*** onInputStreamReady(input=" + input + ") on thread " +
-          gThreadManager.currentThread + " (main is " +
-          gThreadManager.mainThread + ")");
-    dumpn("*** this._state == " + this._state);
-
-    // Handle cases where we get more data after a request error has been
-    // discovered but *before* we can close the connection.
-    var data = this._data;
-    if (!data)
-      return;
-
-    try
-    {
-      data.appendBytes(readBytes(input, input.available()));
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** WARNING: unexpected error when reading from socket; will " +
-              "be treated as if the input stream had been closed");
-        dumpn("*** WARNING: actual error was: " + e);
-      }
-
-      // We've lost a race -- input has been closed, but we're still expecting
-      // to read more data. available() will throw in this case, and since
-      // we're dead in the water now, destroy the connection.
-      dumpn("*** onInputStreamReady called on a closed input, destroying " +
-            "connection");
-      this._connection.close();
-      return;
-    }
-
-    switch (this._state)
-    {
-      default:
-        NS_ASSERT(false, "invalid state: " + this._state);
-        break;
-
-      case READER_IN_REQUEST_LINE:
-        if (!this._processRequestLine())
-          break;
-        /* fall through */
-
-      case READER_IN_HEADERS:
-        if (!this._processHeaders())
-          break;
-        /* fall through */
-
-      case READER_IN_BODY:
-        this._processBody();
-    }
-
-    if (this._state != READER_FINISHED)
-      input.asyncWait(this, 0, 0, gThreadManager.currentThread);
-  },
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(aIID)
-  {
-    if (aIID.equals(Ci.nsIInputStreamCallback) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE API
-
-  /**
-* Processes unprocessed, downloaded data as a request line.
-*
-* @returns boolean
-* true iff the request line has been fully processed
-*/
-  _processRequestLine: function()
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    // Servers SHOULD ignore any empty line(s) received where a Request-Line
-    // is expected (section 4.1).
-    var data = this._data;
-    var line = {};
-    var readSuccess;
-    while ((readSuccess = data.readLine(line)) && line.value == "")
-      dumpn("*** ignoring beginning blank line...");
-
-    // if we don't have a full line, wait until we do
-    if (!readSuccess)
-      return false;
-
-    // we have the first non-blank line
-    try
-    {
-      this._parseRequestLine(line.value);
-      this._state = READER_IN_HEADERS;
-      return true;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing request headers.
-*
-* @returns boolean
-* true iff header data in the request has been fully processed
-*/
-  _processHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    // XXX things to fix here:
-    //
-    // - need to support RFC 2047-encoded non-US-ASCII characters
-
-    try
-    {
-      var done = this._parseHeaders();
-      if (done)
-      {
-        var request = this._metadata;
-
-        // XXX this is wrong for requests with transfer-encodings applied to
-        // them, particularly chunked (which by its nature can have no
-        // meaningful Content-Length header)!
-        this._contentLength = request.hasHeader("Content-Length")
-                            ? parseInt(request.getHeader("Content-Length"), 10)
-                            : 0;
-        dumpn("_processHeaders, Content-length=" + this._contentLength);
-
-        this._state = READER_IN_BODY;
-      }
-      return done;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing the request body.
-*
-* @returns boolean
-* true iff the request body has been fully processed
-*/
-  _processBody: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    // XXX handle chunked transfer-coding request bodies!
-
-    try
-    {
-      if (this._contentLength > 0)
-      {
-        var data = this._data.purge();
-        var count = Math.min(data.length, this._contentLength);
-        dumpn("*** loading data=" + data + " len=" + data.length +
-              " excess=" + (data.length - count));
-
-        var bos = new BinaryOutputStream(this._metadata._bodyOutputStream);
-        bos.writeByteArray(data, count);
-        this._contentLength -= count;
-      }
-
-      dumpn("*** remaining body data len=" + this._contentLength);
-      if (this._contentLength == 0)
-      {
-        this._validateRequest();
-        this._state = READER_FINISHED;
-        this._handleResponse();
-        return true;
-      }
-
-      return false;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Does various post-header checks on the data in this request.
-*
-* @throws : HttpError
-* if the request was malformed in some way
-*/
-  _validateRequest: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    dumpn("*** _validateRequest");
-
-    var metadata = this._metadata;
-    var headers = metadata._headers;
-
-    // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header
-    var identity = this._connection.server.identity;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-    {
-      if (!headers.hasHeader("Host"))
-      {
-        dumpn("*** malformed HTTP/1.1 or greater request with no Host header!");
-        throw HTTP_400;
-      }
-
-      // If the Request-URI wasn't absolute, then we need to determine our host.
-      // We have to determine what scheme was used to access us based on the
-      // server identity data at this point, because the request just doesn't
-      // contain enough data on its own to do this, sadly.
-      if (!metadata._host)
-      {
-        var host, port;
-        var hostPort = headers.getHeader("Host");
-        var colon = hostPort.indexOf(":");
-        if (colon < 0)
-        {
-          host = hostPort;
-          port = "";
-        }
-        else
-        {
-          host = hostPort.substring(0, colon);
-          port = hostPort.substring(colon + 1);
-        }
-
-        // NB: We allow an empty port here because, oddly, a colon may be
-        // present even without a port number, e.g. "example.com:"; in this
-        // case the default port applies.
-        if (!HOST_REGEX.test(host) || !/^\d*$/.test(port))
-        {
-          dumpn("*** malformed hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        // If we're not given a port, we're stuck, because we don't know what
-        // scheme to use to look up the correct port here, in general. Since
-        // the HTTPS case requires a tunnel/proxy and thus requires that the
-        // requested URI be absolute (and thus contain the necessary
-        // information), let's assume HTTP will prevail and use that.
-        port = +port || 80;
-
-        var scheme = identity.getScheme(host, port);
-        if (!scheme)
-        {
-          dumpn("*** unrecognized hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        metadata._scheme = scheme;
-        metadata._host = host;
-        metadata._port = port;
-      }
-    }
-    else
-    {
-      NS_ASSERT(metadata._host === undefined,
-                "HTTP/1.0 doesn't allow absolute paths in the request line!");
-
-      metadata._scheme = identity.primaryScheme;
-      metadata._host = identity.primaryHost;
-      metadata._port = identity.primaryPort;
-    }
-
-    NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port),
-              "must have a location we recognize by now!");
-  },
-
-  /**
-* Handles responses in case of error, either in the server or in the request.
-*
-* @param e
-* the specific error encountered, which is an HttpError in the case where
-* the request is in some way invalid or cannot be fulfilled; if this isn't
-* an HttpError we're going to be paranoid and shut down, because that
-* shouldn't happen, ever
-*/
-  _handleError: function(e)
-  {
-    // Don't fall back into normal processing!
-    this._state = READER_FINISHED;
-
-    var server = this._connection.server;
-    if (e instanceof HttpError)
-    {
-      var code = e.code;
-    }
-    else
-    {
-      dumpn("!!! UNEXPECTED ERROR: " + e +
-            (e.lineNumber ? ", line " + e.lineNumber : ""));
-
-      // no idea what happened -- be paranoid and shut down
-      code = 500;
-      server._requestQuit();
-    }
-
-    // make attempted reuse of data an error
-    this._data = null;
-
-    this._connection.processError(code, this._metadata);
-  },
-
-  /**
-* Now that we've read the request line and headers, we can actually hand off
-* the request to be handled.
-*
-* This method is called once per request, after the request line and all
-* headers and the body, if any, have been received.
-*/
-  _handleResponse: function()
-  {
-    NS_ASSERT(this._state == READER_FINISHED);
-
-    // We don't need the line-based data any more, so make attempted reuse an
-    // error.
-    this._data = null;
-
-    this._connection.process(this._metadata);
-  },
-
-
-  // PARSING
-
-  /**
-* Parses the request line for the HTTP request associated with this.
-*
-* @param line : string
-* the request line
-*/
-  _parseRequestLine: function(line)
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    dumpn("*** _parseRequestLine('" + line + "')");
-
-    var metadata = this._metadata;
-
-    // clients and servers SHOULD accept any amount of SP or HT characters
-    // between fields, even though only a single SP is required (section 19.3)
-    var request = line.split(/[ \t]+/);
-    if (!request || request.length != 3)
-      throw HTTP_400;
-
-    metadata._method = request[0];
-
-    // get the HTTP version
-    var ver = request[2];
-    var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
-    if (!match)
-      throw HTTP_400;
-
-    // determine HTTP version
-    try
-    {
-      metadata._httpVersion = new nsHttpVersion(match[1]);
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
-        throw "unsupported HTTP version";
-    }
-    catch (e)
-    {
-      // we support HTTP/1.0 and HTTP/1.1 only
-      throw HTTP_501;
-    }
-
-
-    var fullPath = request[1];
-    var serverIdentity = this._connection.server.identity;
-
-    var scheme, host, port;
-
-    if (fullPath.charAt(0) != "/")
-    {
-      // No absolute paths in the request line in HTTP prior to 1.1
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-        throw HTTP_400;
-
-      try
-      {
-        var uri = Cc["@mozilla.org/network/io-service;1"]
-                    .getService(Ci.nsIIOService)
-                    .newURI(fullPath);
-        fullPath = uri.pathQueryRef;
-        scheme = uri.scheme;
-        host = metadata._host = uri.asciiHost;
-        port = uri.port;
-        if (port === -1)
-        {
-          if (scheme === "http")
-            port = 80;
-          else if (scheme === "https")
-            port = 443;
-          else
-            throw HTTP_400;
-        }
-      }
-      catch (e)
-      {
-        // If the host is not a valid host on the server, the response MUST be a
-        // 400 (Bad Request) error message (section 5.2). Alternately, the URI
-        // is malformed.
-        throw HTTP_400;
-      }
-
-      if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
-        throw HTTP_400;
-    }
-
-    var splitter = fullPath.indexOf("?");
-    if (splitter < 0)
-    {
-      // _queryString already set in ctor
-      metadata._path = fullPath;
-    }
-    else
-    {
-      metadata._path = fullPath.substring(0, splitter);
-      metadata._queryString = fullPath.substring(splitter + 1);
-    }
-
-    metadata._scheme = scheme;
-    metadata._host = host;
-    metadata._port = port;
-  },
-
-  /**
-* Parses all available HTTP headers in this until the header-ending CRLFCRLF,
-* adding them to the store of headers in the request.
-*
-* @throws
-* HTTP_400 if the headers are malformed
-* @returns boolean
-* true if all headers have now been processed, false otherwise
-*/
-  _parseHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    dumpn("*** _parseHeaders");
-
-    var data = this._data;
-
-    var headers = this._metadata._headers;
-    var lastName = this._lastHeaderName;
-    var lastVal = this._lastHeaderValue;
-
-    var line = {};
-    while (true)
-    {
-      NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
-                lastName === undefined ?
-                  "lastVal without lastName? lastVal: '" + lastVal + "'" :
-                  "lastName without lastVal? lastName: '" + lastName + "'");
-
-      if (!data.readLine(line))
-      {
-        // save any data we have from the header we might still be processing
-        this._lastHeaderName = lastName;
-        this._lastHeaderValue = lastVal;
-        return false;
-      }
-
-      var lineText = line.value;
-      var firstChar = lineText.charAt(0);
-
-      // blank line means end of headers
-      if (lineText == "")
-      {
-        // we're finished with the previous header
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-        else
-        {
-          // no headers in request -- valid for HTTP/1.0 requests
-        }
-
-        // either way, we're done processing headers
-        this._state = READER_IN_BODY;
-        return true;
-      }
-      else if (firstChar == " " || firstChar == "\t")
-      {
-        // multi-line header if we've already seen a header line
-        if (!lastName)
-        {
-          // we don't have a header to continue!
-          throw HTTP_400;
-        }
-
-        // append this line's text to the value; starts with SP/HT, so no need
-        // for separating whitespace
-        lastVal += lineText;
-      }
-      else
-      {
-        // we have a new header, so set the old one (if one existed)
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-
-        var colon = lineText.indexOf(":"); // first colon must be splitter
-        if (colon < 1)
-        {
-          // no colon or missing header field-name
-          throw HTTP_400;
-        }
-
-        // set header name, value (to be set in the next loop, usually)
-        lastName = lineText.substring(0, colon);
-        lastVal = lineText.substring(colon + 1);
-      } // empty, continuation, start of header
-    } // while (true)
-  }
-};
-
-
-/** The character codes for CR and LF. */
-const CR = 0x0D, LF = 0x0A;
-
-/**
-* Calculates the number of characters before the first CRLF pair in array, or
-* -1 if the array contains no CRLF pair.
-*
-* @param array : Array
-* an array of numbers in the range [0, 256), each representing a single
-* character; the first CRLF is the lowest index i where
-* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|,
-* if such an |i| exists, and -1 otherwise
-* @returns int
-* the index of the first CRLF if any were present, -1 otherwise
-*/
-function findCRLF(array)
-{
-  for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1))
-  {
-    if (array[i + 1] == LF)
-      return i;
-  }
-  return -1;
-}
-
-
-/**
-* A container which provides line-by-line access to the arrays of bytes with
-* which it is seeded.
-*/
-function LineData()
-{
-  /** An array of queued bytes from which to get line-based characters. */
-  this._data = [];
-}
-LineData.prototype =
-{
-  /**
-* Appends the bytes in the given array to the internal data cache maintained
-* by this.
-*/
-  appendBytes: function(bytes)
-  {
-    Array.prototype.push.apply(this._data, bytes);
-  },
-
-  /**
-* Removes and returns a line of data, delimited by CRLF, from this.
-*
-* @param out
-* an object whose "value" property will be set to the first line of text
-* present in this, sans CRLF, if this contains a full CRLF-delimited line
-* of text; if this doesn't contain enough data, the value of the property
-* is undefined
-* @returns boolean
-* true if a full line of data could be read from the data in this, false
-* otherwise
-*/
-  readLine: function(out)
-  {
-    var data = this._data;
-    var length = findCRLF(data);
-    if (length < 0)
-      return false;
-
-    //
-    // We have the index of the CR, so remove all the characters, including
-    // CRLF, from the array with splice, and convert the removed array into the
-    // corresponding string, from which we then strip the trailing CRLF.
-    //
-    // Getting the line in this matter acknowledges that substring is an O(1)
-    // operation in SpiderMonkey because strings are immutable, whereas two
-    // splices, both from the beginning of the data, are less likely to be as
-    // cheap as a single splice plus two extra character conversions.
-    //
-    var line = String.fromCharCode.apply(null, data.splice(0, length + 2));
-    out.value = line.substring(0, length);
-
-    return true;
-  },
-
-  /**
-* Removes the bytes currently within this and returns them in an array.
-*
-* @returns Array
-* the bytes within this when this method is called
-*/
-  purge: function()
-  {
-    var data = this._data;
-    this._data = [];
-    return data;
-  }
-};
-
-
-
-/**
-* Creates a request-handling function for an nsIHttpRequestHandler object.
-*/
-function createHandlerFunc(handler)
-{
-  return function(metadata, response) { handler.handle(metadata, response); };
-}
-
-
-/**
-* The default handler for directories; writes an HTML response containing a
-* slightly-formatted directory listing.
-*/
-function defaultIndexHandler(metadata, response)
-{
-  response.setHeader("Content-Type", "text/html", false);
-
-  var path = htmlEscape(decodeURI(metadata.path));
-
-  //
-  // Just do a very basic bit of directory listings -- no need for too much
-  // fanciness, especially since we don't have a style sheet in which we can
-  // stick rules (don't want to pollute the default path-space).
-  //
-
-  var body = '<html>\
-<head>\
-<title>' + path + '</title>\
-</head>\
-<body>\
-<h1>' + path + '</h1>\
-<ol style="list-style-type: none">';
-
-  var directory = metadata.getProperty("directory").QueryInterface(Ci.nsIFile);
-  NS_ASSERT(directory && directory.isDirectory());
-
-  var fileList = [];
-  var files = directory.directoryEntries;
-  while (files.hasMoreElements())
-  {
-    var f = files.getNext().QueryInterface(Ci.nsIFile);
-    var name = f.leafName;
-    if (!f.isHidden() &&
-        (name.charAt(name.length - 1) != HIDDEN_CHAR ||
-         name.charAt(name.length - 2) == HIDDEN_CHAR))
-      fileList.push(f);
-  }
-
-  fileList.sort(fileSort);
-
-  for (var i = 0; i < fileList.length; i++)
-  {
-    var file = fileList[i];
-    try
-    {
-      var name = file.leafName;
-      if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-        name = name.substring(0, name.length - 1);
-      var sep = file.isDirectory() ? "/" : "";
-
-      // Note: using " to delimit the attribute here because encodeURIComponent
-      // passes through '.
-      var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' +
-                   htmlEscape(name) + sep +
-                 '</a></li>';
-
-      body += item;
-    }
-    catch (e) { /* some file system error, ignore the file */ }
-  }
-
-  body += ' </ol>\
-</body>\
-</html>';
-
-  response.bodyOutputStream.write(body, body.length);
-}
-
-/**
-* Sorts a and b (nsIFile objects) into an aesthetically pleasing order.
-*/
-function fileSort(a, b)
-{
-  var dira = a.isDirectory(), dirb = b.isDirectory();
-
-  if (dira && !dirb)
-    return -1;
-  if (dirb && !dira)
-    return 1;
-
-  var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase();
-  return nameb > namea ? -1 : 1;
-}
-
-
-/**
-* Converts an externally-provided path into an internal path for use in
-* determining file mappings.
-*
-* @param path
-* the path to convert
-* @param encoded
-* true if the given path should be passed through decodeURI prior to
-* conversion
-* @throws URIError
-* if path is incorrectly encoded
-*/
-function toInternalPath(path, encoded)
-{
-  if (encoded)
-    path = decodeURI(path);
-
-  var comps = path.split("/");
-  for (var i = 0, sz = comps.length; i < sz; i++)
-  {
-    var comp = comps[i];
-    if (comp.charAt(comp.length - 1) == HIDDEN_CHAR)
-      comps[i] = comp + HIDDEN_CHAR;
-  }
-  return comps.join("/");
-}
-
-
-/**
-* Adds custom-specified headers for the given file to the given response, if
-* any such headers are specified.
-*
-* @param file
-* the file on the disk which is to be written
-* @param metadata
-* metadata about the incoming request
-* @param response
-* the Response to which any specified headers/data should be written
-* @throws HTTP_500
-* if an error occurred while processing custom-specified headers
-*/
-function maybeAddHeaders(file, metadata, response)
-{
-  var name = file.leafName;
-  if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-    name = name.substring(0, name.length - 1);
-
-  var headerFile = file.parent;
-  headerFile.append(name + HEADERS_SUFFIX);
-
-  if (!headerFile.exists())
-    return;
-
-  const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(headerFile, PR_RDONLY, 0o444,
-                                Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-  try
-  {
-    var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0);
-    lis.QueryInterface(Ci.nsIUnicharLineInputStream);
-
-    var line = {value: ""};
-    var more = lis.readLine(line);
-
-    if (!more && line.value == "")
-      return;
-
-
-    // request line
-
-    var status = line.value;
-    if (status.indexOf("HTTP ") == 0)
-    {
-      status = status.substring(5);
-      var space = status.indexOf(" ");
-      var code, description;
-      if (space < 0)
-      {
-        code = status;
-        description = "";
-      }
-      else
-      {
-        code = status.substring(0, space);
-        description = status.substring(space + 1, status.length);
-      }
-
-      response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description);
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-
-    // headers
-    while (more || line.value != "")
-    {
-      var header = line.value;
-      var colon = header.indexOf(":");
-
-      response.setHeader(header.substring(0, colon),
-                         header.substring(colon + 1, header.length),
-                         false); // allow overriding server-set headers
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-  }
-  catch (e)
-  {
-    dumpn("WARNING: error in headers for " + metadata.path + ": " + e);
-    throw HTTP_500;
-  }
-  finally
-  {
-    fis.close();
-  }
-}
-
-
-/**
-* An object which handles requests for a server, executing default and
-* overridden behaviors as instructed by the code which uses and manipulates it.
-* Default behavior includes the paths / and /trace (diagnostics), with some
-* support for HTTP error pages for various codes and fallback to HTTP 500 if
-* those codes fail for any reason.
-*
-* @param server : nsHttpServer
-* the server in which this handler is being used
-*/
-function ServerHandler(server)
-{
-  // FIELDS
-
-  /**
-* The nsHttpServer instance associated with this handler.
-*/
-  this._server = server;
-
-  /**
-* A FileMap object containing the set of path->nsIFile mappings for
-* all directory mappings set in the server (e.g., "/" for /var/www/html/,
-* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2).
-*
-* Note carefully: the leading and trailing "/" in each path (not file) are
-* removed before insertion to simplify the code which uses this. You have
-* been warned!
-*/
-  this._pathDirectoryMap = new FileMap();
-
-  /**
-* Custom request handlers for the server in which this resides. Path-handler
-* pairs are stored as property-value pairs in this property.
-*
-* @see ServerHandler.prototype._defaultPaths
-*/
-  this._overridePaths = {};
-
-  /**
-* Custom request handlers for the server in which this resides. Prefix-handler
-* pairs are stored as property-value pairs in this property.
-*/
-  this._overridePrefixes = {};
-
-  /**
-* Custom request handlers for the error handlers in the server in which this
-* resides. Path-handler pairs are stored as property-value pairs in this
-* property.
-*
-* @see ServerHandler.prototype._defaultErrors
-*/
-  this._overrideErrors = {};
-
-  /**
-* Maps file extensions to their MIME types in the server, overriding any
-* mapping that might or might not exist in the MIME service.
-*/
-  this._mimeMappings = {};
-
-  /**
-* The default handler for requests for directories, used to serve directories
-* when no index file is present.
-*/
-  this._indexHandler = defaultIndexHandler;
-
-  /** Per-path state storage for the server. */
-  this._state = {};
-
-  /** Entire-server state storage. */
-  this._sharedState = {};
-
-  /** Entire-server state storage for nsISupports values. */
-  this._objectState = {};
-}
-ServerHandler.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Handles a request to this server, responding to the request appropriately
-* and initiating server shutdown if necessary.
-*
-* This method never throws an exception.
-*
-* @param connection : Connection
-* the connection for this request
-*/
-  handleResponse: function(connection)
-  {
-    var request = connection.request;
-    var response = new Response(connection);
-
-    var path = request.path;
-    dumpn("*** path == " + path);
-
-    try
-    {
-      try
-      {
-        if (path in this._overridePaths)
-        {
-          // explicit paths first, then files based on existing directory mappings,
-          // then (if the file doesn't exist) built-in server default paths
-          dumpn("calling override for " + path);
-          this._overridePaths[path](request, response);
-        }
-        else
-        {
-          let longestPrefix = "";
-          for (let prefix in this._overridePrefixes)
-          {
-            if (prefix.length > longestPrefix.length && path.startsWith(prefix))
-            {
-              longestPrefix = prefix;
-            }
-          }
-          if (longestPrefix.length > 0)
-          {
-            dumpn("calling prefix override for " + longestPrefix);
-            this._overridePrefixes[longestPrefix](request, response);
-          }
-          else
-          {
-            this._handleDefault(request, response);
-          }
-        }
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        if (!(e instanceof HttpError))
-        {
-          dumpn("*** unexpected error: e == " + e);
-          throw HTTP_500;
-        }
-        if (e.code !== 404)
-          throw e;
-
-        dumpn("*** default: " + (path in this._defaultPaths));
-
-        response = new Response(connection);
-        if (path in this._defaultPaths)
-          this._defaultPaths[path](request, response);
-        else
-          throw HTTP_404;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort(e);
-        return;
-      }
-
-      var errorCode = "internal";
-
-      try
-      {
-        if (!(e instanceof HttpError))
-          throw e;
-
-        errorCode = e.code;
-        dumpn("*** errorCode == " + errorCode);
-
-        response = new Response(connection);
-        if (e.customErrorHandling)
-          e.customErrorHandling(response);
-        this._handleError(errorCode, request, response);
-        return;
-      }
-      catch (e2)
-      {
-        dumpn("*** error handling " + errorCode + " error: " +
-              "e2 == " + e2 + ", shutting down server");
-
-        connection.server._requestQuit();
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (!file)
-    {
-      dumpn("*** unregistering '" + path + "' mapping");
-      delete this._overridePaths[path];
-      return;
-    }
-
-    dumpn("*** registering '" + path + "' as mapping to " + file.path);
-    file = file.clone();
-
-    var self = this;
-    this._overridePaths[path] =
-      function(request, response)
-      {
-        if (!file.exists())
-          throw HTTP_404;
-
-        response.setStatusLine(request.httpVersion, 200, "OK");
-        self._writeFileResponse(request, file, response, 0, file.fileSize);
-      };
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePaths, path);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    // XXX true prefix validation!
-    if (!(prefix.startsWith("/") && prefix.endsWith("/")))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePrefixes, prefix);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // strip off leading and trailing '/' so that we can use lastIndexOf when
-    // determining exactly how a path maps onto a mapped directory --
-    // conditional is required here to deal with "/".substring(1, 0) being
-    // converted to "/".substring(0, 1) per the JS specification
-    var key = path.length == 1 ? "" : path.substring(1, path.length - 1);
-
-    // the path-to-directory mapping code requires that the first character not
-    // be "/", or it will go into an infinite loop
-    if (key.charAt(0) == "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    key = toInternalPath(key, false);
-
-    if (directory)
-    {
-      dumpn("*** mapping '" + path + "' to the location " + directory.path);
-      this._pathDirectoryMap.put(key, directory);
-    }
-    else
-    {
-      dumpn("*** removing mapping for '" + path + "'");
-      this._pathDirectoryMap.put(key, null);
-    }
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(err, handler)
-  {
-    if (!(err in HTTP_ERROR_CODES))
-      dumpn("*** WARNING: registering non-HTTP/1.1 error code " +
-            "(" + err + ") handler -- was this intentional?");
-
-    this._handlerToField(handler, this._overrideErrors, err);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    if (!handler)
-      handler = defaultIndexHandler;
-    else if (typeof(handler) != "function")
-      handler = createHandlerFunc(handler);
-
-    this._indexHandler = handler;
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    if (!type)
-      delete this._mimeMappings[ext];
-    else
-      this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type);
-  },
-
-  // PRIVATE API
-
-  /**
-* Sets or remove (if handler is null) a handler in an object with a key.
-*
-* @param handler
-* a handler, either function or an nsIHttpRequestHandler
-* @param dict
-* The object to attach the handler to.
-* @param key
-* The field name of the handler.
-*/
-  _handlerToField: function(handler, dict, key)
-  {
-    // for convenience, handler can be a function if this is run from xpcshell
-    if (typeof(handler) == "function")
-      dict[key] = handler;
-    else if (handler)
-      dict[key] = createHandlerFunc(handler);
-    else
-      delete dict[key];
-  },
-
-  /**
-* Handles a request which maps to a file in the local filesystem (if a base
-* path has already been set; otherwise the 404 error is thrown).
-*
-* @param metadata : Request
-* metadata for the incoming request
-* @param response : Response
-* an uninitialized Response to the given request, to be initialized by a
-* request handler
-* @throws HTTP_###
-* if an HTTP error occurred (usually HTTP_404); note that in this case the
-* calling code must handle post-processing of the response
-*/
-  _handleDefault: function(metadata, response)
-  {
-    dumpn("*** _handleDefault()");
-
-    response.setStatusLine(metadata.httpVersion, 200, "OK");
-
-    var path = metadata.path;
-    NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">");
-
-    // determine the actual on-disk file; this requires finding the deepest
-    // path-to-directory mapping in the requested URL
-    var file = this._getFileForPath(path);
-
-    // the "file" might be a directory, in which case we either serve the
-    // contained index.html or make the index handler write the response
-    if (file.exists() && file.isDirectory())
-    {
-      file.append("index.html"); // make configurable?
-      if (!file.exists() || file.isDirectory())
-      {
-        metadata._ensurePropertyBag();
-        metadata._bag.setPropertyAsInterface("directory", file.parent);
-        this._indexHandler(metadata, response);
-        return;
-      }
-    }
-
-    // alternately, the file might not exist
-    if (!file.exists())
-      throw HTTP_404;
-
-    var start, end;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
-        metadata.hasHeader("Range") &&
-        this._getTypeFromFile(file) !== SJS_TYPE)
-    {
-      var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
-      if (!rangeMatch)
-        throw HTTP_400;
-
-      if (rangeMatch[1] !== undefined)
-        start = parseInt(rangeMatch[1], 10);
-
-      if (rangeMatch[2] !== undefined)
-        end = parseInt(rangeMatch[2], 10);
-
-      if (start === undefined && end === undefined)
-        throw HTTP_400;
-
-      // No start given, so the end is really the count of bytes from the
-      // end of the file.
-      if (start === undefined)
-      {
-        start = Math.max(0, file.fileSize - end);
-        end = file.fileSize - 1;
-      }
-
-      // start and end are inclusive
-      if (end === undefined || end >= file.fileSize)
-        end = file.fileSize - 1;
-
-      if (start !== undefined && start >= file.fileSize) {
-        var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
-        HTTP_416.customErrorHandling = function(errorResponse)
-        {
-          maybeAddHeaders(file, metadata, errorResponse);
-        };
-        throw HTTP_416;
-      }
-
-      if (end < start)
-      {
-        response.setStatusLine(metadata.httpVersion, 200, "OK");
-        start = 0;
-        end = file.fileSize - 1;
-      }
-      else
-      {
-        response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
-        var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize;
-        response.setHeader("Content-Range", contentRange);
-      }
-    }
-    else
-    {
-      start = 0;
-      end = file.fileSize - 1;
-    }
-
-    // finally...
-    dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " +
-          start + " to " + end + " inclusive");
-    this._writeFileResponse(metadata, file, response, start, end - start + 1);
-  },
-
-  /**
-* Writes an HTTP response for the given file, including setting headers for
-* file metadata.
-*
-* @param metadata : Request
-* the Request for which a response is being generated
-* @param file : nsIFile
-* the file which is to be sent in the response
-* @param response : Response
-* the response to which the file should be written
-* @param offset: uint
-* the byte offset to skip to when writing
-* @param count: uint
-* the number of bytes to write
-*/
-  _writeFileResponse: function(metadata, file, response, offset, count)
-  {
-    const PR_RDONLY = 0x01;
-
-    var type = this._getTypeFromFile(file);
-    if (type === SJS_TYPE)
-    {
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      try
-      {
-        var sis = new ScriptableInputStream(fis);
-        var s = Cu.Sandbox(gGlobalObject);
-        s.importFunction(dump, "dump");
-
-        // Define a basic key-value state-preservation API across requests, with
-        // keys initially corresponding to the empty string.
-        var self = this;
-        var path = metadata.path;
-        s.importFunction(function getState(k)
-        {
-          return self._getState(path, k);
-        });
-        s.importFunction(function setState(k, v)
-        {
-          self._setState(path, k, v);
-        });
-        s.importFunction(function getSharedState(k)
-        {
-          return self._getSharedState(k);
-        });
-        s.importFunction(function setSharedState(k, v)
-        {
-          self._setSharedState(k, v);
-        });
-        s.importFunction(function getObjectState(k, callback)
-        {
-          callback(self._getObjectState(k));
-        });
-        s.importFunction(function setObjectState(k, v)
-        {
-          self._setObjectState(k, v);
-        });
-        s.importFunction(function registerPathHandler(p, h)
-        {
-          self.registerPathHandler(p, h);
-        });
-
-        // Make it possible for sjs files to access their location
-        this._setState(path, "__LOCATION__", file.path);
-
-        try
-        {
-          // Alas, the line number in errors dumped to console when calling the
-          // request handler is simply an offset from where we load the SJS file.
-          // Work around this in a reasonably non-fragile way by dynamically
-          // getting the line number where we evaluate the SJS file. Don't
-          // separate these two lines!
-          var line = new Error().lineNumber;
-          Cu.evalInSandbox(sis.read(file.fileSize), s);
-        }
-        catch (e)
-        {
-          dumpn("*** syntax error in SJS at " + file.path + ": " + e);
-          throw HTTP_500;
-        }
-
-        try
-        {
-          s.handleRequest(metadata, response);
-        }
-        catch (e)
-        {
-          dump("*** error running SJS at " + file.path + ": " +
-               e + " on line " +
-               (e instanceof Error
-               ? e.lineNumber + " in httpd.js"
-               : (e.lineNumber - line)) + "\n");
-          throw HTTP_500;
-        }
-      }
-      finally
-      {
-        fis.close();
-      }
-    }
-    else
-    {
-      try
-      {
-        response.setHeader("Last-Modified",
-                           toDateString(file.lastModifiedTime),
-                           false);
-      }
-      catch (e) { /* lastModifiedTime threw, ignore */ }
-
-      response.setHeader("Content-Type", type, false);
-      maybeAddHeaders(file, metadata, response);
-      response.setHeader("Content-Length", "" + count, false);
-
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      offset = offset || 0;
-      count = count || file.fileSize;
-      NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset");
-      NS_ASSERT(count >= 0, "bad count");
-      NS_ASSERT(offset + count <= file.fileSize, "bad total data size");
-
-      try
-      {
-        if (offset !== 0)
-        {
-          // Seek (or read, if seeking isn't supported) to the correct offset so
-          // the data sent to the client matches the requested range.
-          if (fis instanceof Ci.nsISeekableStream)
-            fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset);
-          else
-            new ScriptableInputStream(fis).read(offset);
-        }
-      }
-      catch (e)
-      {
-        fis.close();
-        throw e;
-      }
-
-      let writeMore = function writeMore()
-      {
-        gThreadManager.dispatchToMainThread(writeData);
-      }
-
-      var input = new BinaryInputStream(fis);
-      var output = new BinaryOutputStream(response.bodyOutputStream);
-      var writeData =
-        {
-          run: function()
-          {
-            var chunkSize = Math.min(65536, count);
-            count -= chunkSize;
-            NS_ASSERT(count >= 0, "underflow");
-
-            try
-            {
-              var data = input.readByteArray(chunkSize);
-              NS_ASSERT(data.length === chunkSize,
-                        "incorrect data returned? got " + data.length +
-                        ", expected " + chunkSize);
-              output.writeByteArray(data, data.length);
-              if (count === 0)
-              {
-                fis.close();
-                response.finish();
-              }
-              else
-              {
-                writeMore();
-              }
-            }
-            catch (e)
-            {
-              try
-              {
-                fis.close();
-              }
-              finally
-              {
-                response.finish();
-              }
-              throw e;
-            }
-          }
-        };
-
-      writeMore();
-
-      // Now that we know copying will start, flag the response as async.
-      response.processAsync();
-    }
-  },
-
-  /**
-* Get the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getState: function(path, k)
-  {
-    var state = this._state;
-    if (path in state && k in state[path])
-      return state[path][k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setState: function(path, k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    var state = this._state;
-    if (!(path in state))
-      state[path] = {};
-    state[path][k] = v;
-  },
-
-  /**
-* Get the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getSharedState: function(k)
-  {
-    var state = this._sharedState;
-    if (k in state)
-      return state[k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setSharedState: function(k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    this._sharedState[k] = v;
-  },
-
-  /**
-* Returns the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be returned
-* @returns nsISupports
-* the corresponding object, or null if none was present
-*/
-  _getObjectState: function(k)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    return this._objectState[k] || null;
-  },
-
-  /**
-* Sets the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be set
-* @param v : nsISupports
-* the object to be associated with the given key; may be null
-*/
-  _setObjectState: function(k, v)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    if (typeof v !== "object")
-      throw new Error("non-object value passed");
-    if (v && !("QueryInterface" in v))
-    {
-      throw new Error("must pass an nsISupports; use wrappedJSObject to ease " +
-                      "pain when using the server from JS");
-    }
-
-    this._objectState[k] = v;
-  },
-
-  /**
-* Gets a content-type for the given file, first by checking for any custom
-* MIME-types registered with this handler for the file's extension, second by
-* asking the global MIME service for a content-type, and finally by failing
-* over to application/octet-stream.
-*
-* @param file : nsIFile
-* the nsIFile for which to get a file type
-* @returns string
-* the best content-type which can be determined for the file
-*/
-  _getTypeFromFile: function(file)
-  {
-    try
-    {
-      var name = file.leafName;
-      var dot = name.lastIndexOf(".");
-      if (dot > 0)
-      {
-        var ext = name.slice(dot + 1);
-        if (ext in this._mimeMappings)
-          return this._mimeMappings[ext];
-      }
-      return Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
-               .getService(Ci.nsIMIMEService)
-               .getTypeFromFile(file);
-    }
-    catch (e)
-    {
-      return "application/octet-stream";
-    }
-  },
-
-  /**
-* Returns the nsIFile which corresponds to the path, as determined using
-* all registered path->directory mappings and any paths which are explicitly
-* overridden.
-*
-* @param path : string
-* the server path for which a file should be retrieved, e.g. "/foo/bar"
-* @throws HttpError
-* when the correct action is the corresponding HTTP error (i.e., because no
-* mapping was found for a directory in path, the referenced file doesn't
-* exist, etc.)
-* @returns nsIFile
-* the file to be sent as the response to a request for the path
-*/
-  _getFileForPath: function(path)
-  {
-    // decode and add underscores as necessary
-    try
-    {
-      path = toInternalPath(path, true);
-    }
-    catch (e)
-    {
-      throw HTTP_400; // malformed path
-    }
-
-    // next, get the directory which contains this path
-    var pathMap = this._pathDirectoryMap;
-
-    // An example progression of tmp for a path "/foo/bar/baz/" might be:
-    // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
-    var tmp = path.substring(1);
-    while (true)
-    {
-      // do we have a match for current head of the path?
-      var file = pathMap.get(tmp);
-      if (file)
-      {
-        // XXX hack; basically disable showing mapping for /foo/bar/ when the
-        // requested path was /foo/bar, because relative links on the page
-        // will all be incorrect -- we really need the ability to easily
-        // redirect here instead
-        if (tmp == path.substring(1) &&
-            tmp.length != 0 &&
-            tmp.charAt(tmp.length - 1) != "/")
-          file = null;
-        else
-          break;
-      }
-
-      // if we've finished trying all prefixes, exit
-      if (tmp == "")
-        break;
-
-      tmp = tmp.substring(0, tmp.lastIndexOf("/"));
-    }
-
-    // no mapping applies, so 404
-    if (!file)
-      throw HTTP_404;
-
-
-    // last, get the file for the path within the determined directory
-    var parentFolder = file.parent;
-    var dirIsRoot = (parentFolder == null);
-
-    // Strategy here is to append components individually, making sure we
-    // never move above the given directory; this allows paths such as
-    // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling";
-    // this component-wise approach also means the code works even on platforms
-    // which don't use "/" as the directory separator, such as Windows
-    var leafPath = path.substring(tmp.length + 1);
-    var comps = leafPath.split("/");
-    for (var i = 0, sz = comps.length; i < sz; i++)
-    {
-      var comp = comps[i];
-
-      if (comp == "..")
-        file = file.parent;
-      else if (comp == "." || comp == "")
-        continue;
-      else
-        file.append(comp);
-
-      if (!dirIsRoot && file.equals(parentFolder))
-        throw HTTP_403;
-    }
-
-    return file;
-  },
-
-  /**
-* Writes the error page for the given HTTP error code over the given
-* connection.
-*
-* @param errorCode : uint
-* the HTTP error code to be used
-* @param connection : Connection
-* the connection on which the error occurred
-*/
-  handleError: function(errorCode, connection)
-  {
-    var response = new Response(connection);
-
-    dumpn("*** error in request: " + errorCode);
-
-    this._handleError(errorCode, new Request(connection.port), response);
-  },
-
-  /**
-* Handles a request which generates the given error code, using the
-* user-defined error handler if one has been set, gracefully falling back to
-* the x00 status code if the code has no handler, and failing to status code
-* 500 if all else fails.
-*
-* @param errorCode : uint
-* the HTTP error which is to be returned
-* @param metadata : Request
-* metadata for the request, which will often be incomplete since this is an
-* error
-* @param response : Response
-* an uninitialized Response should be initialized when this method
-* completes with information which represents the desired error code in the
-* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a
-* fallback for 505, per HTTP specs)
-*/
-  _handleError: function(errorCode, metadata, response)
-  {
-    if (!metadata)
-      throw Cr.NS_ERROR_NULL_POINTER;
-
-    var errorX00 = errorCode - (errorCode % 100);
-
-    try
-    {
-      if (!(errorCode in HTTP_ERROR_CODES))
-        dumpn("*** WARNING: requested invalid error: " + errorCode);
-
-      // RFC 2616 says that we should try to handle an error by its class if we
-      // can't otherwise handle it -- if that fails, we revert to handling it as
-      // a 500 internal server error, and if that fails we throw and shut down
-      // the server
-
-      // actually handle the error
-      try
-      {
-        if (errorCode in this._overrideErrors)
-          this._overrideErrors[errorCode](metadata, response);
-        else
-          this._defaultErrors[errorCode](metadata, response);
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        // don't retry the handler that threw
-        if (errorX00 == errorCode)
-          throw HTTP_500;
-
-        dumpn("*** error in handling for error code " + errorCode + ", " +
-              "falling back to " + errorX00 + "...");
-        response = new Response(response._connection);
-        if (errorX00 in this._overrideErrors)
-          this._overrideErrors[errorX00](metadata, response);
-        else if (errorX00 in this._defaultErrors)
-          this._defaultErrors[errorX00](metadata, response);
-        else
-          throw HTTP_500;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort();
-        return;
-      }
-
-      // we've tried everything possible for a meaningful error -- now try 500
-      dumpn("*** error in handling for error code " + errorX00 + ", falling " +
-            "back to 500...");
-
-      try
-      {
-        response = new Response(response._connection);
-        if (500 in this._overrideErrors)
-          this._overrideErrors[500](metadata, response);
-        else
-          this._defaultErrors[500](metadata, response);
-      }
-      catch (e2)
-      {
-        dumpn("*** multiple errors in default error handlers!");
-        dumpn("*** e == " + e + ", e2 == " + e2);
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  // FIELDS
-
-  /**
-* This object contains the default handlers for the various HTTP error codes.
-*/
-  _defaultErrors:
-  {
-    400: function(metadata, response)
-    {
-      // none of the data in metadata is reliable, so hard-code everything here
-      response.setStatusLine("1.1", 400, "Bad Request");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Bad request\n";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    403: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 403, "Forbidden");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>403 Forbidden</title></head>\
-<body>\
-<h1>403 Forbidden</h1>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    404: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 404, "Not Found");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>404 Not Found</title></head>\
-<body>\
-<h1>404 Not Found</h1>\
-<p>\
-<span style='font-family: monospace;'>" +
-                          htmlEscape(metadata.path) +
-                       "</span> was not found.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    416: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                            416,
-                            "Requested Range Not Satisfiable");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head>\
-<title>416 Requested Range Not Satisfiable</title></head>\
-<body>\
-<h1>416 Requested Range Not Satisfiable</h1>\
-<p>The byte range was not valid for the\
-requested resource.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    500: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                             500,
-                             "Internal Server Error");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>500 Internal Server Error</title></head>\
-<body>\
-<h1>500 Internal Server Error</h1>\
-<p>Something's broken in this server and\
-needs to be fixed.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    501: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 501, "Not Implemented");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>501 Not Implemented</title></head>\
-<body>\
-<h1>501 Not Implemented</h1>\
-<p>This server is not (yet) Apache.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    505: function(metadata, response)
-    {
-      response.setStatusLine("1.1", 505, "HTTP Version Not Supported");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>505 HTTP Version Not Supported</title></head>\
-<body>\
-<h1>505 HTTP Version Not Supported</h1>\
-<p>This server only supports HTTP/1.0 and HTTP/1.1\
-connections.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    }
-  },
-
-  /**
-* Contains handlers for the default set of URIs contained in this server.
-*/
-  _defaultPaths:
-  {
-    "/": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>httpd.js</title></head>\
-<body>\
-<h1>httpd.js</h1>\
-<p>If you're seeing this page, httpd.js is up and\
-serving requests! Now set a base path and serve some\
-files!</p>\
-</body>\
-</html>";
-
-      response.bodyOutputStream.write(body, body.length);
-    },
-
-    "/trace": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Request-URI: " +
-                 metadata.scheme + "://" + metadata.host + ":" + metadata.port +
-                 metadata.path + "\n\n";
-      body += "Request (semantically equivalent, slightly reformatted):\n\n";
-      body += metadata.method + " " + metadata.path;
-
-      if (metadata.queryString)
-        body += "?" + metadata.queryString;
-
-      body += " HTTP/" + metadata.httpVersion + "\r\n";
-
-      var headEnum = metadata.headers;
-      while (headEnum.hasMoreElements())
-      {
-        var fieldName = headEnum.getNext()
-                                .QueryInterface(Ci.nsISupportsString)
-                                .data;
-        body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n";
-      }
-
-      response.bodyOutputStream.write(body, body.length);
-    }
-  }
-};
-
-
-/**
-* Maps absolute paths to files on the local file system (as nsILocalFiles).
-*/
-function FileMap()
-{
-  /** Hash which will map paths to nsILocalFiles. */
-  this._map = {};
-}
-FileMap.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Maps key to a clone of the nsIFile value if value is non-null;
-* otherwise, removes any extant mapping for key.
-*
-* @param key : string
-* string to which a clone of value is mapped
-* @param value : nsIFile
-* the file to map to key, or null to remove a mapping
-*/
-  put: function(key, value)
-  {
-    if (value)
-      this._map[key] = value.clone();
-    else
-      delete this._map[key];
-  },
-
-  /**
-* Returns a clone of the nsIFile mapped to key, or null if no such
-* mapping exists.
-*
-* @param key : string
-* key to which the returned file maps
-* @returns nsIFile
-* a clone of the mapped file, or null if no mapping exists
-*/
-  get: function(key)
-  {
-    var val = this._map[key];
-    return val ? val.clone() : null;
-  }
-};
-
-
-// Response CONSTANTS
-
-// token = *<any CHAR except CTLs or separators>
-// CHAR = <any US-ASCII character (0-127)>
-// CTL = <any US-ASCII control character (0-31) and DEL (127)>
-// separators = "(" | ")" | "<" | ">" | "@"
-// | "," | ";" | ":" | "\" | <">
-// | "/" | "[" | "]" | "?" | "="
-// | "{" | "}" | SP | HT
-const IS_TOKEN_ARRAY =
-  [0, 0, 0, 0, 0, 0, 0, 0, // 0
-   0, 0, 0, 0, 0, 0, 0, 0, // 8
-   0, 0, 0, 0, 0, 0, 0, 0, // 16
-   0, 0, 0, 0, 0, 0, 0, 0, // 24
-
-   0, 1, 0, 1, 1, 1, 1, 1, // 32
-   0, 0, 1, 1, 0, 1, 1, 0, // 40
-   1, 1, 1, 1, 1, 1, 1, 1, // 48
-   1, 1, 0, 0, 0, 0, 0, 0, // 56
-
-   0, 1, 1, 1, 1, 1, 1, 1, // 64
-   1, 1, 1, 1, 1, 1, 1, 1, // 72
-   1, 1, 1, 1, 1, 1, 1, 1, // 80
-   1, 1, 1, 0, 0, 0, 1, 1, // 88
-
-   1, 1, 1, 1, 1, 1, 1, 1, // 96
-   1, 1, 1, 1, 1, 1, 1, 1, // 104
-   1, 1, 1, 1, 1, 1, 1, 1, // 112
-   1, 1, 1, 0, 1, 0, 1]; // 120
-
-
-/**
-* Determines whether the given character code is a CTL.
-*
-* @param code : uint
-* the character code
-* @returns boolean
-* true if code is a CTL, false otherwise
-*/
-function isCTL(code)
-{
-  return (code >= 0 && code <= 31) || (code == 127);
-}
-
-/**
-* Represents a response to an HTTP request, encapsulating all details of that
-* response. This includes all headers, the HTTP version, status code and
-* explanation, and the entity itself.
-*
-* @param connection : Connection
-* the connection over which this response is to be written
-*/
-function Response(connection)
-{
-  /** The connection over which this response will be written. */
-  this._connection = connection;
-
-  /**
-* The HTTP version of this response; defaults to 1.1 if not set by the
-* handler.
-*/
-  this._httpVersion = nsHttpVersion.HTTP_1_1;
-
-  /**
-* The HTTP code of this response; defaults to 200.
-*/
-  this._httpCode = 200;
-
-  /**
-* The description of the HTTP code in this response; defaults to "OK".
-*/
-  this._httpDescription = "OK";
-
-  /**
-* An nsIHttpHeaders object in which the headers in this response should be
-* stored. This property is null after the status line and headers have been
-* written to the network, and it may be modified up until it is cleared,
-* except if this._finished is set first (in which case headers are written
-* asynchronously in response to a finish() call not preceded by
-* flushHeaders()).
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* Set to true when this response is ended (completely constructed if possible
-* and the connection closed); further actions on this will then fail.
-*/
-  this._ended = false;
-
-  /**
-* A stream used to hold data written to the body of this response.
-*/
-  this._bodyOutputStream = null;
-
-  /**
-* A stream containing all data that has been written to the body of this
-* response so far. (Async handlers make the data contained in this
-* unreliable as a way of determining content length in general, but auxiliary
-* saved information can sometimes be used to guarantee reliability.)
-*/
-  this._bodyInputStream = null;
-
-  /**
-* A stream copier which copies data to the network. It is initially null
-* until replaced with a copier for response headers; when headers have been
-* fully sent it is replaced with a copier for the response body, remaining
-* so for the duration of response processing.
-*/
-  this._asyncCopier = null;
-
-  /**
-* True if this response has been designated as being processed
-* asynchronously rather than for the duration of a single call to
-* nsIHttpRequestHandler.handle.
-*/
-  this._processAsync = false;
-
-  /**
-* True iff finish() has been called on this, signaling that no more changes
-* to this may be made.
-*/
-  this._finished = false;
-
-  /**
-* True iff powerSeized() has been called on this, signaling that this
-* response is to be handled manually by the response handler (which may then
-* send arbitrary data in response, even non-HTTP responses).
-*/
-  this._powerSeized = false;
-}
-Response.prototype =
-{
-  // PUBLIC CONSTRUCTION API
-
-  //
-  // see nsIHttpResponse.bodyOutputStream
-  //
-  get bodyOutputStream()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    if (!this._bodyOutputStream)
-    {
-      var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX,
-                          null);
-      this._bodyOutputStream = pipe.outputStream;
-      this._bodyInputStream = pipe.inputStream;
-      if (this._processAsync || this._powerSeized)
-        this._startAsyncProcessor();
-    }
-
-    return this._bodyOutputStream;
-  },
-
-  //
-  // see nsIHttpResponse.write
-  //
-  write: function(data)
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    var dataAsString = String(data);
-    this.bodyOutputStream.write(dataAsString, dataAsString.length);
-  },
-
-  //
-  // see nsIHttpResponse.setStatusLine
-  //
-  setStatusLine: function(httpVersion, code, description)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    if (!(code >= 0 && code < 1000))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    try
-    {
-      var httpVer;
-      // avoid version construction for the most common cases
-      if (!httpVersion || httpVersion == "1.1")
-        httpVer = nsHttpVersion.HTTP_1_1;
-      else if (httpVersion == "1.0")
-        httpVer = nsHttpVersion.HTTP_1_0;
-      else
-        httpVer = new nsHttpVersion(httpVersion);
-    }
-    catch (e)
-    {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    // Reason-Phrase = *<TEXT, excluding CR, LF>
-    // TEXT = <any OCTET except CTLs, but including LWS>
-    //
-    // XXX this ends up disallowing octets which aren't Unicode, I think -- not
-    // much to do if description is IDL'd as string
-    if (!description)
-      description = "";
-    for (var i = 0; i < description.length; i++)
-      if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t")
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // set the values only after validation to preserve atomicity
-    this._httpDescription = description;
-    this._httpCode = code;
-    this._httpVersion = httpVer;
-  },
-
-  //
-  // see nsIHttpResponse.setHeader
-  //
-  setHeader: function(name, value, merge)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    this._headers.setHeader(name, value, merge);
-  },
-
-  //
-  // see nsIHttpResponse.processAsync
-  //
-  processAsync: function()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._processAsync)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** processing connection " + this._connection.number + " async");
-    this._processAsync = true;
-
-    /*
-* Either the bodyOutputStream getter or this method is responsible for
-* starting the asynchronous processor and catching writes of data to the
-* response body of async responses as they happen, for the purpose of
-* forwarding those writes to the actual connection's output stream.
-* If bodyOutputStream is accessed first, calling this method will create
-* the processor (when it first is clear that body data is to be written
-* immediately, not buffered). If this method is called first, accessing
-* bodyOutputStream will create the processor. If only this method is
-* called, we'll write nothing, neither headers nor the nonexistent body,
-* until finish() is called. Since that delay is easily avoided by simply
-* getting bodyOutputStream or calling write(""), we don't worry about it.
-*/
-    if (this._bodyOutputStream && !this._asyncCopier)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.seizePower
-  //
-  seizePower: function()
-  {
-    if (this._processAsync)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** forcefully seizing power over connection " +
-          this._connection.number + "...");
-
-    // Purge any already-written data without sending it. We could as easily
-    // swap out the streams entirely, but that makes it possible to acquire and
-    // unknowingly use a stale reference, so we require there only be one of
-    // each stream ever for any response to avoid this complication.
-    if (this._asyncCopier)
-      this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED);
-    this._asyncCopier = null;
-    if (this._bodyOutputStream)
-    {
-      var input = new BinaryInputStream(this._bodyInputStream);
-      var avail;
-      while ((avail = input.available()) > 0)
-        input.readByteArray(avail);
-    }
-
-    this._powerSeized = true;
-    if (this._bodyOutputStream)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.finish
-  //
-  finish: function()
-  {
-    if (!this._processAsync && !this._powerSeized)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._finished)
-      return;
-
-    dumpn("*** finishing connection " + this._connection.number);
-    this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-    this._finished = true;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // POST-CONSTRUCTION API (not exposed externally)
-
-  /**
-* The HTTP version number of this, as a string (e.g. "1.1").
-*/
-  get httpVersion()
-  {
-    this._ensureAlive();
-    return this._httpVersion.toString();
-  },
-
-  /**
-* The HTTP status code of this response, as a string of three characters per
-* RFC 2616.
-*/
-  get httpCode()
-  {
-    this._ensureAlive();
-
-    var codeString = (this._httpCode < 10 ? "0" : "") +
-                     (this._httpCode < 100 ? "0" : "") +
-                     this._httpCode;
-    return codeString;
-  },
-
-  /**
-* The description of the HTTP status code of this response, or "" if none is
-* set.
-*/
-  get httpDescription()
-  {
-    this._ensureAlive();
-
-    return this._httpDescription;
-  },
-
-  /**
-* The headers in this response, as an nsHttpHeaders object.
-*/
-  get headers()
-  {
-    this._ensureAlive();
-
-    return this._headers;
-  },
-
-  //
-  // see nsHttpHeaders.getHeader
-  //
-  getHeader: function(name)
-  {
-    this._ensureAlive();
-
-    return this._headers.getHeader(name);
-  },
-
-  /**
-* Determines whether this response may be abandoned in favor of a newly
-* constructed response. A response may be abandoned only if it is not being
-* sent asynchronously and if raw control over it has not been taken from the
-* server.
-*
-* @returns boolean
-* true iff no data has been written to the network
-*/
-  partiallySent: function()
-  {
-    dumpn("*** partiallySent()");
-    return this._processAsync || this._powerSeized;
-  },
-
-  /**
-* If necessary, kicks off the remaining request processing needed to be done
-* after a request handler performs its initial work upon this response.
-*/
-  complete: function()
-  {
-    dumpn("*** complete()");
-    if (this._processAsync || this._powerSeized)
-    {
-      NS_ASSERT(this._processAsync ^ this._powerSeized,
-                "can't both send async and relinquish power");
-      return;
-    }
-
-    NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?");
-
-    this._startAsyncProcessor();
-
-    // Now make sure we finish processing this request!
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-  },
-
-  /**
-* Abruptly ends processing of this response, usually due to an error in an
-* incoming request but potentially due to a bad error handler. Since we
-* cannot handle the error in the usual way (giving an HTTP error page in
-* response) because data may already have been sent (or because the response
-* might be expected to have been generated asynchronously or completely from
-* scratch by the handler), we stop processing this response and abruptly
-* close the connection.
-*
-* @param e : Error
-* the exception which precipitated this abort, or null if no such exception
-* was generated
-*/
-  abort: function(e)
-  {
-    dumpn("*** abort(<" + e + ">)");
-
-    // This response will be ended by the processor if one was created.
-    var copier = this._asyncCopier;
-    if (copier)
-    {
-      // We dispatch asynchronously here so that any pending writes of data to
-      // the connection will be deterministically written. This makes it easier
-      // to specify exact behavior, and it makes observable behavior more
-      // predictable for clients. Note that the correctness of this depends on
-      // callbacks in response to _waitToReadData in WriteThroughCopier
-      // happening asynchronously with respect to the actual writing of data to
-      // bodyOutputStream, as they currently do; if they happened synchronously,
-      // an event which ran before this one could write more data to the
-      // response body before we get around to canceling the copier. We have
-      // tests for this in test_seizepower.js, however, and I can't think of a
-      // way to handle both cases without removing bodyOutputStream access and
-      // moving its effective write(data, length) method onto Response, which
-      // would be slower and require more code than this anyway.
-      gThreadManager.dispatchToMainThread({
-        run: function()
-        {
-          dumpn("*** canceling copy asynchronously...");
-          copier.cancel(Cr.NS_ERROR_UNEXPECTED);
-        }
-      });
-    }
-    else
-    {
-      this.end();
-    }
-  },
-
-  /**
-* Closes this response's network connection, marks the response as finished,
-* and notifies the server handler that the request is done being processed.
-*/
-  end: function()
-  {
-    NS_ASSERT(!this._ended, "ending this response twice?!?!");
-
-    this._connection.close();
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-
-    this._finished = true;
-    this._ended = true;
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Sends the status line and headers of this response if they haven't been
-* sent and initiates the process of copying data written to this response's
-* body to the network.
-*/
-  _startAsyncProcessor: function()
-  {
-    dumpn("*** _startAsyncProcessor()");
-
-    // Handle cases where we're being called a second time. The former case
-    // happens when this is triggered both by complete() and by processAsync(),
-    // while the latter happens when processAsync() in conjunction with sent
-    // data causes abort() to be called.
-    if (this._asyncCopier || this._ended)
-    {
-      dumpn("*** ignoring second call to _startAsyncProcessor");
-      return;
-    }
-
-    // Send headers if they haven't been sent already and should be sent, then
-    // asynchronously continue to send the body.
-    if (this._headers && !this._powerSeized)
-    {
-      this._sendHeaders();
-      return;
-    }
-
-    this._headers = null;
-    this._sendBody();
-  },
-
-  /**
-* Signals that all modifications to the response status line and headers are
-* complete and then sends that data over the network to the client. Once
-* this method completes, a different response to the request that resulted
-* in this response cannot be sent -- the only possible action in case of
-* error is to abort the response and close the connection.
-*/
-  _sendHeaders: function()
-  {
-    dumpn("*** _sendHeaders()");
-
-    NS_ASSERT(this._headers);
-    NS_ASSERT(!this._powerSeized);
-
-    // request-line
-    var statusLine = "HTTP/" + this.httpVersion + " " +
-                     this.httpCode + " " +
-                     this.httpDescription + "\r\n";
-
-    // header post-processing
-
-    var headers = this._headers;
-    headers.setHeader("Connection", "close", false);
-    headers.setHeader("Server", "httpd.js", false);
-    if (!headers.hasHeader("Date"))
-      headers.setHeader("Date", toDateString(Date.now()), false);
-
-    // Any response not being processed asynchronously must have an associated
-    // Content-Length header for reasons of backwards compatibility with the
-    // initial server, which fully buffered every response before sending it.
-    // Beyond that, however, it's good to do this anyway because otherwise it's
-    // impossible to test behaviors that depend on the presence or absence of a
-    // Content-Length header.
-    if (!this._processAsync)
-    {
-      dumpn("*** non-async response, set Content-Length");
-
-      var bodyStream = this._bodyInputStream;
-      var avail = bodyStream ? bodyStream.available() : 0;
-
-      // XXX assumes stream will always report the full amount of data available
-      headers.setHeader("Content-Length", "" + avail, false);
-    }
-
-
-    // construct and send response
-    dumpn("*** header post-processing completed, sending response head...");
-
-    // request-line
-    var preambleData = [statusLine];
-
-    // headers
-    var headEnum = headers.enumerator;
-    while (headEnum.hasMoreElements())
-    {
-      var fieldName = headEnum.getNext()
-                              .QueryInterface(Ci.nsISupportsString)
-                              .data;
-      var values = headers.getHeaderValues(fieldName);
-      for (var i = 0, sz = values.length; i < sz; i++)
-        preambleData.push(fieldName + ": " + values[i] + "\r\n");
-    }
-
-    // end request-line/headers
-    preambleData.push("\r\n");
-
-    var preamble = preambleData.join("");
-
-    var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null);
-    responseHeadPipe.outputStream.write(preamble, preamble.length);
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, cx)
-        {
-          dumpn("*** preamble copying started");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** preamble copying complete " +
-                "[status=0x" + statusCode.toString(16) + "]");
-
-          if (!components.isSuccessCode(statusCode))
-          {
-            dumpn("!!! header copying problems: non-success statusCode, " +
-                  "ending response");
-
-            response.end();
-          }
-          else
-          {
-            response._sendBody();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    var headerCopier = this._asyncCopier =
-      new WriteThroughCopier(responseHeadPipe.inputStream,
-                             this._connection.output,
-                             copyObserver, null);
-
-    responseHeadPipe.outputStream.close();
-
-    // Forbid setting any more headers or modifying the request line.
-    this._headers = null;
-  },
-
-  /**
-* Asynchronously writes the body of the response (or the entire response, if
-* seizePower() has been called) to the network.
-*/
-  _sendBody: function()
-  {
-    dumpn("*** _sendBody");
-
-    NS_ASSERT(!this._headers, "still have headers around but sending body?");
-
-    // If no body data was written, we're done
-    if (!this._bodyInputStream)
-    {
-      dumpn("*** empty body, response finished");
-      this.end();
-      return;
-    }
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, context)
-        {
-          dumpn("*** onStartRequest");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]");
-
-          if (statusCode === Cr.NS_BINDING_ABORTED)
-          {
-            dumpn("*** terminating copy observer without ending the response");
-          }
-          else
-          {
-            if (!components.isSuccessCode(statusCode))
-              dumpn("*** WARNING: non-success statusCode in onStopRequest");
-
-            response.end();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    dumpn("*** starting async copier of body data...");
-    this._asyncCopier =
-      new WriteThroughCopier(this._bodyInputStream, this._connection.output,
-                            copyObserver, null);
-  },
-
-  /** Ensures that this hasn't been ended. */
-  _ensureAlive: function()
-  {
-    NS_ASSERT(!this._ended, "not handling response lifetime correctly");
-  }
-};
-
-/**
-* Size of the segments in the buffer used in storing response data and writing
-* it to the socket.
-*/
-Response.SEGMENT_SIZE = 8192;
-
-/** Serves double duty in WriteThroughCopier implementation. */
-function notImplemented()
-{
-  throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/** Returns true iff the given exception represents stream closure. */
-function streamClosed(e)
-{
-  return e === Cr.NS_BASE_STREAM_CLOSED ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED);
-}
-
-/** Returns true iff the given exception represents a blocked stream. */
-function wouldBlock(e)
-{
-  return e === Cr.NS_BASE_STREAM_WOULD_BLOCK ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK);
-}
-
-/**
-* Copies data from source to sink as it becomes available, when that data can
-* be written to sink without blocking.
-*
-* @param source : nsIAsyncInputStream
-* the stream from which data is to be read
-* @param sink : nsIAsyncOutputStream
-* the stream to which data is to be copied
-* @param observer : nsIRequestObserver
-* an observer which will be notified when the copy starts and finishes
-* @param context : nsISupports
-* context passed to observer when notified of start/stop
-* @throws NS_ERROR_NULL_POINTER
-* if source, sink, or observer are null
-*/
-function WriteThroughCopier(source, sink, observer, context)
-{
-  if (!source || !sink || !observer)
-    throw Cr.NS_ERROR_NULL_POINTER;
-
-  /** Stream from which data is being read. */
-  this._source = source;
-
-  /** Stream to which data is being written. */
-  this._sink = sink;
-
-  /** Observer watching this copy. */
-  this._observer = observer;
-
-  /** Context for the observer watching this. */
-  this._context = context;
-
-  /**
-* True iff this is currently being canceled (cancel has been called, the
-* callback may not yet have been made).
-*/
-  this._canceled = false;
-
-  /**
-* False until all data has been read from input and written to output, at
-* which point this copy is completed and cancel() is asynchronously called.
-*/
-  this._completed = false;
-
-  /** Required by nsIRequest, meaningless. */
-  this.loadFlags = 0;
-  /** Required by nsIRequest, meaningless. */
-  this.loadGroup = null;
-  /** Required by nsIRequest, meaningless. */
-  this.name = "response-body-copy";
-
-  /** Status of this request. */
-  this.status = Cr.NS_OK;
-
-  /** Arrays of byte strings waiting to be written to output. */
-  this._pendingData = [];
-
-  // start copying
-  try
-  {
-    observer.onStartRequest(this, context);
-    this._waitToReadData();
-    this._waitForSinkClosure();
-  }
-  catch (e)
-  {
-    dumpn("!!! error starting copy: " + e +
-          ("lineNumber" in e ? ", line " + e.lineNumber : ""));
-    dumpn(e.stack);
-    this.cancel(Cr.NS_ERROR_UNEXPECTED);
-  }
-}
-WriteThroughCopier.prototype =
-{
-  /* nsISupports implementation */
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIInputStreamCallback) ||
-        iid.equals(Ci.nsIOutputStreamCallback) ||
-        iid.equals(Ci.nsIRequest) ||
-        iid.equals(Ci.nsISupports))
-    {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Receives a more-data-in-input notification and writes the corresponding
-* data to the output.
-*
-* @param input : nsIAsyncInputStream
-* the input stream on whose data we have been waiting
-*/
-  onInputStreamReady: function(input)
-  {
-    if (this._source === null)
-      return;
-
-    dumpn("*** onInputStreamReady");
-
-    //
-    // Ordinarily we'll read a non-zero amount of data from input, queue it up
-    // to be written and then wait for further callbacks. The complications in
-    // this method are the cases where we deviate from that behavior when errors
-    // occur or when copying is drawing to a finish.
-    //
-    // The edge cases when reading data are:
-    //
-    // Zero data is read
-    // If zero data was read, we're at the end of available data, so we can
-    // should stop reading and move on to writing out what we have (or, if
-    // we've already done that, onto notifying of completion).
-    // A stream-closed exception is thrown
-    // This is effectively a less kind version of zero data being read; the
-    // only difference is that we notify of completion with that result
-    // rather than with NS_OK.
-    // Some other exception is thrown
-    // This is the least kind result. We don't know what happened, so we
-    // act as though the stream closed except that we notify of completion
-    // with the result NS_ERROR_UNEXPECTED.
-    //
-
-    var bytesWanted = 0, bytesConsumed = -1;
-    try
-    {
-      input = new BinaryInputStream(input);
-
-      bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE);
-      dumpn("*** input wanted: " + bytesWanted);
-
-      if (bytesWanted > 0)
-      {
-        var data = input.readByteArray(bytesWanted);
-        bytesConsumed = data.length;
-        this._pendingData.push(String.fromCharCode.apply(String, data));
-      }
-
-      dumpn("*** " + bytesConsumed + " bytes read");
-
-      // Handle the zero-data edge case in the same place as all other edge
-      // cases are handled.
-      if (bytesWanted === 0)
-        throw Cr.NS_BASE_STREAM_CLOSED;
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** input stream closed");
-        e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED;
-      }
-      else
-      {
-        dumpn("!!! unexpected error reading from input, canceling: " + e);
-        e = Cr.NS_ERROR_UNEXPECTED;
-      }
-
-      this._doneReadingSource(e);
-      return;
-    }
-
-    var pendingData = this._pendingData;
-
-    NS_ASSERT(bytesConsumed > 0);
-    NS_ASSERT(pendingData.length > 0, "no pending data somehow?");
-    NS_ASSERT(pendingData[pendingData.length - 1].length > 0,
-              "buffered zero bytes of data?");
-
-    NS_ASSERT(this._source !== null);
-
-    // Reading has gone great, and we've gotten data to write now. What if we
-    // don't have a place to write that data, because output went away just
-    // before this read? Drop everything on the floor, including new data, and
-    // cancel at this point.
-    if (this._sink === null)
-    {
-      pendingData.length = 0;
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we've read the data, and we know we have a place to write it. We
-    // need to queue up the data to be written, but *only* if none is queued
-    // already -- if data's already queued, the code that actually writes the
-    // data will make sure to wait on unconsumed pending data.
-    try
-    {
-      if (pendingData.length === 1)
-        this._waitToWriteData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to write data just read, swallowing and " +
-            "writing only what we already have: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Whee! We successfully read some data, and it's successfully queued up to
-    // be written. All that remains now is to wait for more data to read.
-    try
-    {
-      this._waitToReadData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to read more data: " + e);
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-    }
-  },
-
-
-  // NSIOUTPUTSTREAMCALLBACK
-
-  /**
-* Callback when data may be written to the output stream without blocking, or
-* when the output stream has been closed.
-*
-* @param output : nsIAsyncOutputStream
-* the output stream on whose writability we've been waiting, also known as
-* this._sink
-*/
-  onOutputStreamReady: function(output)
-  {
-    if (this._sink === null)
-      return;
-
-    dumpn("*** onOutputStreamReady");
-
-    var pendingData = this._pendingData;
-    if (pendingData.length === 0)
-    {
-      // There's no pending data to write. The only way this can happen is if
-      // we're waiting on the output stream's closure, so we can respond to a
-      // copying failure as quickly as possible (rather than waiting for data to
-      // be available to read and then fail to be copied). Therefore, we must
-      // be done now -- don't bother to attempt to write anything and wrap
-      // things up.
-      dumpn("!!! output stream closed prematurely, ending copy");
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-
-    NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?");
-
-    //
-    // Write out the first pending quantum of data. The possible errors here
-    // are:
-    //
-    // The write might fail because we can't write that much data
-    // Okay, we've written what we can now, so re-queue what's left and
-    // finish writing it out later.
-    // The write failed because the stream was closed
-    // Discard pending data that we can no longer write, stop reading, and
-    // signal that copying finished.
-    // Some other error occurred.
-    // Same as if the stream were closed, but notify with the status
-    // NS_ERROR_UNEXPECTED so the observer knows something was wonky.
-    //
-
-    try
-    {
-      var quantum = pendingData[0];
-
-      // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on
-      // undefined behavior! We're only using this because writeByteArray
-      // is unusably broken for asynchronous output streams; see bug 532834
-      // for details.
-      var bytesWritten = output.write(quantum, quantum.length);
-      if (bytesWritten === quantum.length)
-        pendingData.shift();
-      else
-        pendingData[0] = quantum.substring(bytesWritten);
-
-      dumpn("*** wrote " + bytesWritten + " bytes of data");
-    }
-    catch (e)
-    {
-      if (wouldBlock(e))
-      {
-        NS_ASSERT(pendingData.length > 0,
-                  "stream-blocking exception with no data to write?");
-        NS_ASSERT(pendingData[0].length > 0,
-                  "stream-blocking exception with empty quantum?");
-        this._waitToWriteData();
-        return;
-      }
-
-      if (streamClosed(e))
-        dumpn("!!! output stream prematurely closed, signaling error...");
-      else
-        dumpn("!!! unknown error: " + e + ", quantum=" + quantum);
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // The day is ours! Quantum written, now let's see if we have more data
-    // still to write.
-    try
-    {
-      if (pendingData.length > 0)
-      {
-        this._waitToWriteData();
-        return;
-      }
-    }
-    catch (e)
-    {
-      dumpn("!!! unexpected error waiting to write pending data: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we have no more pending data to write -- but might we get more in
-    // the future?
-    if (this._source !== null)
-    {
-      /*
-* If we might, then wait for the output stream to be closed. (We wait
-* only for closure because we have no data to write -- and if we waited
-* for a specific amount of data, we would get repeatedly notified for no
-* reason if over time the output stream permitted more and more data to
-* be written to it without blocking.)
-*/
-       this._waitForSinkClosure();
-    }
-    else
-    {
-      /*
-* On the other hand, if we can't have more data because the input
-* stream's gone away, then it's time to notify of copy completion.
-* Victory!
-*/
-      this._sink = null;
-      this._cancelOrDispatchCancelCallback(Cr.NS_OK);
-    }
-  },
-
-
-  // NSIREQUEST
-
-  /** Returns true if the cancel observer hasn't been notified yet. */
-  isPending: function()
-  {
-    return !this._completed;
-  },
-
-  /** Not implemented, don't use! */
-  suspend: notImplemented,
-  /** Not implemented, don't use! */
-  resume: notImplemented,
-
-  /**
-* Cancels data reading from input, asynchronously writes out any pending
-* data, and causes the observer to be notified with the given error code when
-* all writing has finished.
-*
-* @param status : nsresult
-* the status to pass to the observer when data copying has been canceled
-*/
-  cancel: function(status)
-  {
-    dumpn("*** cancel(" + status.toString(16) + ")");
-
-    if (this._canceled)
-    {
-      dumpn("*** suppressing a late cancel");
-      return;
-    }
-
-    this._canceled = true;
-    this.status = status;
-
-    // We could be in the middle of absolutely anything at this point. Both
-    // input and output might still be around, we might have pending data to
-    // write, and in general we know nothing about the state of the world. We
-    // therefore must assume everything's in progress and take everything to its
-    // final steady state (or so far as it can go before we need to finish
-    // writing out remaining data).
-
-    this._doneReadingSource(status);
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Stop reading input if we haven't already done so, passing e as the status
-* when closing the stream, and kick off a copy-completion notice if no more
-* data remains to be written.
-*
-* @param e : nsresult
-* the status to be used when closing the input stream
-*/
-  _doneReadingSource: function(e)
-  {
-    dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
-
-    this._finishSource(e);
-    if (this._pendingData.length === 0)
-      this._sink = null;
-    else
-      NS_ASSERT(this._sink !== null, "null output?");
-
-    // If we've written out all data read up to this point, then it's time to
-    // signal completion.
-    if (this._sink === null)
-    {
-      NS_ASSERT(this._pendingData.length === 0, "pending data still?");
-      this._cancelOrDispatchCancelCallback(e);
-    }
-  },
-
-  /**
-* Stop writing output if we haven't already done so, discard any data that
-* remained to be sent, close off input if it wasn't already closed, and kick
-* off a copy-completion notice.
-*
-* @param e : nsresult
-* the status to be used when closing input if it wasn't already closed
-*/
-  _doneWritingToSink: function(e)
-  {
-    dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")");
-
-    this._pendingData.length = 0;
-    this._sink = null;
-    this._doneReadingSource(e);
-  },
-
-  /**
-* Completes processing of this copy: either by canceling the copy if it
-* hasn't already been canceled using the provided status, or by dispatching
-* the cancel callback event (with the originally provided status, of course)
-* if it already has been canceled.
-*
-* @param status : nsresult
-* the status code to use to cancel this, if this hasn't already been
-* canceled
-*/
-  _cancelOrDispatchCancelCallback: function(status)
-  {
-    dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")");
-
-    NS_ASSERT(this._source === null, "should have finished input");
-    NS_ASSERT(this._sink === null, "should have finished output");
-    NS_ASSERT(this._pendingData.length === 0, "should have no pending data");
-
-    if (!this._canceled)
-    {
-      this.cancel(status);
-      return;
-    }
-
-    var self = this;
-    var event =
-      {
-        run: function()
-        {
-          dumpn("*** onStopRequest async callback");
-
-          self._completed = true;
-          try
-          {
-            self._observer.onStopRequest(self, self._context, self.status);
-          }
-          catch (e)
-          {
-            NS_ASSERT(false,
-                      "how are we throwing an exception here? we control " +
-                      "all the callers! " + e);
-          }
-        }
-      };
-
-    gThreadManager.dispatchToMainThread(event);
-  },
-
-  /**
-* Kicks off another wait for more data to be available from the input stream.
-*/
-  _waitToReadData: function()
-  {
-    dumpn("*** _waitToReadData");
-    this._source.asyncWait(this, 0, Response.SEGMENT_SIZE,
-                           gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off another wait until data can be written to the output stream.
-*/
-  _waitToWriteData: function()
-  {
-    dumpn("*** _waitToWriteData");
-
-    var pendingData = this._pendingData;
-    NS_ASSERT(pendingData.length > 0, "no pending data to write?");
-    NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?");
-
-    this._sink.asyncWait(this, 0, pendingData[0].length,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off a wait for the sink to which data is being copied to be closed.
-* We wait for stream closure when we don't have any data to be copied, rather
-* than waiting to write a specific amount of data. We can't wait to write
-* data because the sink might be infinitely writable, and if no data appears
-* in the source for a long time we might have to spin quite a bit waiting to
-* write, waiting to write again, &c. Waiting on stream closure instead means
-* we'll get just one notification if the sink dies. Note that when data
-* starts arriving from the sink we'll resume waiting for data to be written,
-* dropping this closure-only callback entirely.
-*/
-  _waitForSinkClosure: function()
-  {
-    dumpn("*** _waitForSinkClosure");
-
-    this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Closes input with the given status, if it hasn't already been closed;
-* otherwise a no-op.
-*
-* @param status : nsresult
-* status code use to close the source stream if necessary
-*/
-  _finishSource: function(status)
-  {
-    dumpn("*** _finishSource(" + status.toString(16) + ")");
-
-    if (this._source !== null)
-    {
-      this._source.closeWithStatus(status);
-      this._source = null;
-    }
-  }
-};
-
-
-/**
-* A container for utility functions used with HTTP headers.
-*/
-const headerUtils =
-{
-  /**
-* Normalizes fieldName (by converting it to lowercase) and ensures it is a
-* valid header field name (although not necessarily one specified in RFC
-* 2616).
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not match the field-name production in RFC 2616
-* @returns string
-* fieldName converted to lowercase if it is a valid header, for characters
-* where case conversion is possible
-*/
-  normalizeFieldName: function(fieldName)
-  {
-    if (fieldName == "")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    for (var i = 0, sz = fieldName.length; i < sz; i++)
-    {
-      if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
-      {
-        dumpn(fieldName + " is not a valid header field name!");
-        throw Cr.NS_ERROR_INVALID_ARG;
-      }
-    }
-
-    return fieldName.toLowerCase();
-  },
-
-  /**
-* Ensures that fieldValue is a valid header field value (although not
-* necessarily as specified in RFC 2616 if the corresponding field name is
-* part of the HTTP protocol), normalizes the value if it is, and
-* returns the normalized value.
-*
-* @param fieldValue : string
-* a value to be normalized as an HTTP header field value
-* @throws NS_ERROR_INVALID_ARG
-* if fieldValue does not match the field-value production in RFC 2616
-* @returns string
-* fieldValue as a normalized HTTP header field value
-*/
-  normalizeFieldValue: function(fieldValue)
-  {
-    // field-value = *( field-content | LWS )
-    // field-content = <the OCTETs making up the field-value
-    // and consisting of either *TEXT or combinations
-    // of token, separators, and quoted-string>
-    // TEXT = <any OCTET except CTLs,
-    // but including LWS>
-    // LWS = [CRLF] 1*( SP | HT )
-    //
-    // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-    // qdtext = <any TEXT except <">>
-    // quoted-pair = "\" CHAR
-    // CHAR = <any US-ASCII character (octets 0 - 127)>
-
-    // Any LWS that occurs between field-content MAY be replaced with a single
-    // SP before interpreting the field value or forwarding the message
-    // downstream (section 4.2); we replace 1*LWS with a single SP
-    var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
-
-    // remove leading/trailing LWS (which has been converted to SP)
-    val = val.replace(/^ +/, "").replace(/ +$/, "");
-
-    // that should have taken care of all CTLs, so val should contain no CTLs
-    for (var i = 0, len = val.length; i < len; i++)
-      if (isCTL(val.charCodeAt(i)))
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
-    // normalize, however, so this can be construed as a tightening of the
-    // spec and not entirely as a bug
-    return val;
-  }
-};
-
-
-
-/**
-* Converts the given string into a string which is safe for use in an HTML
-* context.
-*
-* @param str : string
-* the string to make HTML-safe
-* @returns string
-* an HTML-safe version of str
-*/
-function htmlEscape(str)
-{
-  // this is naive, but it'll work
-  var s = "";
-  for (var i = 0; i < str.length; i++)
-    s += "&#" + str.charCodeAt(i) + ";";
-  return s;
-}
-
-
-/**
-* Constructs an object representing an HTTP version (see section 3.1).
-*
-* @param versionString
-* a string of the form "#.#", where # is an non-negative decimal integer with
-* or without leading zeros
-* @throws
-* if versionString does not specify a valid HTTP version number
-*/
-function nsHttpVersion(versionString)
-{
-  var matches = /^(\d+)\.(\d+)$/.exec(versionString);
-  if (!matches)
-    throw "Not a valid HTTP version!";
-
-  /** The major version number of this, as a number. */
-  this.major = parseInt(matches[1], 10);
-
-  /** The minor version number of this, as a number. */
-  this.minor = parseInt(matches[2], 10);
-
-  if (isNaN(this.major) || isNaN(this.minor) ||
-      this.major < 0 || this.minor < 0)
-    throw "Not a valid HTTP version!";
-}
-nsHttpVersion.prototype =
-{
-  /**
-* Returns the standard string representation of the HTTP version represented
-* by this (e.g., "1.1").
-*/
-  toString: function ()
-  {
-    return this.major + "." + this.minor;
-  },
-
-  /**
-* Returns true if this represents the same HTTP version as otherVersion,
-* false otherwise.
-*
-* @param otherVersion : nsHttpVersion
-* the version to compare against this
-*/
-  equals: function (otherVersion)
-  {
-    return this.major == otherVersion.major &&
-           this.minor == otherVersion.minor;
-  },
-
-  /** True if this >= otherVersion, false otherwise. */
-  atLeast: function(otherVersion)
-  {
-    return this.major > otherVersion.major ||
-           (this.major == otherVersion.major &&
-            this.minor >= otherVersion.minor);
-  }
-};
-
-nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0");
-nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1");
-
-
-/**
-* An object which stores HTTP headers for a request or response.
-*
-* Note that since headers are case-insensitive, this object converts headers to
-* lowercase before storing them. This allows the getHeader and hasHeader
-* methods to work correctly for any case of a header, but it means that the
-* values returned by .enumerator may not be equal case-sensitively to the
-* values passed to setHeader when adding headers to this.
-*/
-function nsHttpHeaders()
-{
-  /**
-* A hash of headers, with header field names as the keys and header field
-* values as the values. Header field names are case-insensitive, but upon
-* insertion here they are converted to lowercase. Header field values are
-* normalized upon insertion to contain no leading or trailing whitespace.
-*
-* Note also that per RFC 2616, section 4.2, two headers with the same name in
-* a message may be treated as one header with the same field name and a field
-* value consisting of the separate field values joined together with a "," in
-* their original order. This hash stores multiple headers with the same name
-* in this manner.
-*/
-  this._headers = {};
-}
-nsHttpHeaders.prototype =
-{
-  /**
-* Sets the header represented by name and value in this.
-*
-* @param name : string
-* the header name
-* @param value : string
-* the header value
-* @throws NS_ERROR_INVALID_ARG
-* if name or value is not a valid header component
-*/
-  setHeader: function(fieldName, fieldValue, merge)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    var value = headerUtils.normalizeFieldValue(fieldValue);
-
-    // The following three headers are stored as arrays because their real-world
-    // syntax prevents joining individual headers into a single header using
-    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
-    if (merge && name in this._headers)
-    {
-      if (name === "www-authenticate" ||
-          name === "proxy-authenticate" ||
-          name === "set-cookie")
-      {
-        this._headers[name].push(value);
-      }
-      else
-      {
-        this._headers[name][0] += "," + value;
-        NS_ASSERT(this._headers[name].length === 1,
-            "how'd a non-special header have multiple values?")
-      }
-    }
-    else
-    {
-      this._headers[name] = [value];
-    }
-  },
-
-  /**
-* Returns the value for the header specified by this.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns string
-* the field value for the given header, possibly with non-semantic changes
-* (i.e., leading/trailing whitespace stripped, whitespace runs replaced
-* with spaces, etc.) at the option of the implementation; multiple
-* instances of the header will be combined with a comma, except for
-* the three headers noted in the description of getHeaderValues
-*/
-  getHeader: function(fieldName)
-  {
-    return this.getHeaderValues(fieldName).join("\n");
-  },
-
-  /**
-* Returns the value for the header specified by fieldName as an array.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns [string]
-* an array of all the header values in this for the given
-* header name. Header values will generally be collapsed
-* into a single header by joining all header values together
-* with commas, but certain headers (Proxy-Authenticate,
-* WWW-Authenticate, and Set-Cookie) violate the HTTP spec
-* and cannot be collapsed in this manner. For these headers
-* only, the returned array may contain multiple elements if
-* that header has been added more than once.
-*/
-  getHeaderValues: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-
-    if (name in this._headers)
-      return this._headers[name];
-    else
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-  },
-
-  /**
-* Returns true if a header with the given field name exists in this, false
-* otherwise.
-*
-* @param fieldName : string
-* the field name whose existence is to be determined in this
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @returns boolean
-* true if the header's present, false otherwise
-*/
-  hasHeader: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    return (name in this._headers);
-  },
-
-  /**
-* Returns a new enumerator over the field names of the headers in this, as
-* nsISupportsStrings. The names returned will be in lowercase, regardless of
-* how they were input using setHeader (header names are case-insensitive per
-* RFC 2616).
-*/
-  get enumerator()
-  {
-    var headers = [];
-    for (var i in this._headers)
-    {
-      var supports = new SupportsString();
-      supports.data = i;
-      headers.push(supports);
-    }
-
-    return new nsSimpleEnumerator(headers);
-  }
-};
-
-
-/**
-* Constructs an nsISimpleEnumerator for the given array of items.
-*
-* @param items : Array
-* the items, which must all implement nsISupports
-*/
-function nsSimpleEnumerator(items)
-{
-  this._items = items;
-  this._nextIndex = 0;
-}
-nsSimpleEnumerator.prototype =
-{
-  hasMoreElements: function()
-  {
-    return this._nextIndex < this._items.length;
-  },
-  getNext: function()
-  {
-    if (!this.hasMoreElements())
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    return this._items[this._nextIndex++];
-  },
-  QueryInterface: function(aIID)
-  {
-    if (Ci.nsISimpleEnumerator.equals(aIID) ||
-        Ci.nsISupports.equals(aIID))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-
-/**
-* A representation of the data in an HTTP request.
-*
-* @param port : uint
-* the port on which the server receiving this request runs
-*/
-function Request(port)
-{
-  /** Method of this request, e.g. GET or POST. */
-  this._method = "";
-
-  /** Path of the requested resource; empty paths are converted to '/'. */
-  this._path = "";
-
-  /** Query string, if any, associated with this request (not including '?'). */
-  this._queryString = "";
-
-  /** Scheme of requested resource, usually http, always lowercase. */
-  this._scheme = "http";
-
-  /** Hostname on which the requested resource resides. */
-  this._host = undefined;
-
-  /** Port number over which the request was received. */
-  this._port = port;
-
-  var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null);
-
-  /** Stream from which data in this request's body may be read. */
-  this._bodyInputStream = bodyPipe.inputStream;
-
-  /** Stream to which data in this request's body is written. */
-  this._bodyOutputStream = bodyPipe.outputStream;
-
-  /**
-* The headers in this request.
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* For the addition of ad-hoc properties and new functionality without having
-* to change nsIHttpRequest every time; currently lazily created, as its only
-* use is in directory listings.
-*/
-  this._bag = null;
-}
-Request.prototype =
-{
-  // SERVER METADATA
-
-  //
-  // see nsIHttpRequest.scheme
-  //
-  get scheme()
-  {
-    return this._scheme;
-  },
-
-  //
-  // see nsIHttpRequest.host
-  //
-  get host()
-  {
-    return this._host;
-  },
-
-  //
-  // see nsIHttpRequest.port
-  //
-  get port()
-  {
-    return this._port;
-  },
-
-  // REQUEST LINE
-
-  //
-  // see nsIHttpRequest.method
-  //
-  get method()
-  {
-    return this._method;
-  },
-
-  //
-  // see nsIHttpRequest.httpVersion
-  //
-  get httpVersion()
-  {
-    return this._httpVersion.toString();
-  },
-
-  //
-  // see nsIHttpRequest.path
-  //
-  get path()
-  {
-    return this._path;
-  },
-
-  //
-  // see nsIHttpRequest.queryString
-  //
-  get queryString()
-  {
-    return this._queryString;
-  },
-
-  // HEADERS
-
-  //
-  // see nsIHttpRequest.getHeader
-  //
-  getHeader: function(name)
-  {
-    return this._headers.getHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.hasHeader
-  //
-  hasHeader: function(name)
-  {
-    return this._headers.hasHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get headers()
-  {
-    return this._headers.enumerator;
-  },
-
-  //
-  // see nsIPropertyBag.enumerator
-  //
-  get enumerator()
-  {
-    this._ensurePropertyBag();
-    return this._bag.enumerator;
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get bodyInputStream()
-  {
-    return this._bodyInputStream;
-  },
-
-  //
-  // see nsIPropertyBag.getProperty
-  //
-  getProperty: function(name)
-  {
-    this._ensurePropertyBag();
-    return this._bag.getProperty(name);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /** Ensures a property bag has been created for ad-hoc behaviors. */
-  _ensurePropertyBag: function()
-  {
-    if (!this._bag)
-      this._bag = new WritablePropertyBag();
-  }
-};
-
-
-// XPCOM trappings
-if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason...
-    "generateNSGetFactory" in XPCOMUtils) {
-  var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]);
-}
-
-
-
-/**
-* Creates a new HTTP server listening for loopback traffic on the given port,
-* starts it, and runs the server until the server processes a shutdown request,
-* spinning an event loop so that events posted by the server's socket are
-* processed.
-*
-* This method is primarily intended for use in running this script from within
-* xpcshell and running a functional HTTP server without having to deal with
-* non-essential details.
-*
-* Note that running multiple servers using variants of this method probably
-* doesn't work, simply due to how the internal event loop is spun and stopped.
-*
-* @note
-* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code);
-* you should use this server as a component in Mozilla 1.8.
-* @param port
-* the port on which the server will run, or -1 if there exists no preference
-* for a specific port; note that attempting to use some values for this
-* parameter (particularly those below 1024) may cause this method to throw or
-* may result in the server being prematurely shut down
-* @param basePath
-* a local directory from which requests will be served (i.e., if this is
-* "/home/jwalden/" then a request to /index.html will load
-* /home/jwalden/index.html); if this is omitted, only the default URLs in
-* this server implementation will be functional
-*/
-function server(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  // if you're running this, you probably want to see debugging info
-  DEBUG = true;
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", SJS_TYPE);
-  srv.start(port);
-
-  gThreadManager.spinEventLoopUntil(() => srv.isStopped());
-
-  gThreadManager.spinEventLoopUntilEmpty();
-
-  DEBUG = false;
-}
-
-function startServerAsync(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", "sjs");
-  srv.start(port);
-  return srv;
-}
-
-exports.nsHttpServer = nsHttpServer;
-exports.ScriptableInputStream = ScriptableInputStream;
-exports.server = server;
-exports.startServerAsync = startServerAsync;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/main.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { merge } = require('sdk/util/object');
-const { version } = require('sdk/system');
-
-const SKIPPING_TESTS = {
-  "test skip": (assert) => assert.pass("nothing to test here")
-};
-
-merge(module.exports, require('./test-content-script'));
-merge(module.exports, require('./test-content-worker'));
-merge(module.exports, require('./test-page-worker'));
-
-// run e10s tests only on builds from trunk, fx-team, Nightly..
-if (!version.endsWith('a1')) {
-  module.exports = SKIPPING_TESTS;
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js
+++ /dev/null
@@ -1,838 +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 hiddenFrames = require("sdk/frame/hidden-frame");
-const { create: makeFrame } = require("sdk/frame/utils");
-const { window } = require("sdk/addon/window");
-const { Loader } = require('sdk/test/loader');
-const { URL } = require("sdk/url");
-const testURI = require("./fixtures").url("test.html");
-const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
-
-/*
- * Utility function that allow to easily run a proxy test with a clean
- * new HTML document. See first unit test for usage.
- */
-function createProxyTest(html, callback) {
-  return function (assert, done) {
-    let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
-    let principalLoaded = false;
-
-    let element = makeFrame(window.document, {
-      nodeName: "iframe",
-      type: "content",
-      allowJavascript: true,
-      allowPlugins: true,
-      allowAuth: true,
-      uri: testURI
-    });
-
-    element.addEventListener("DOMContentLoaded", onDOMReady);
-
-    function onDOMReady() {
-      // Reload frame after getting principal from `testURI`
-      if (!principalLoaded) {
-        element.setAttribute("src", url);
-        principalLoaded = true;
-        return;
-      }
-
-      assert.equal(element.getAttribute("src"), url, "correct URL loaded");
-      element.removeEventListener("DOMContentLoaded", onDOMReady);
-      let xrayWindow = element.contentWindow;
-      let rawWindow = xrayWindow.wrappedJSObject;
-
-      let isDone = false;
-      let helper = {
-        xrayWindow: xrayWindow,
-        rawWindow: rawWindow,
-        createWorker: function (contentScript) {
-          return createWorker(assert, xrayWindow, contentScript, helper.done);
-        },
-        done: function () {
-          if (isDone)
-            return;
-          isDone = true;
-          element.remove();
-          done();
-        }
-      };
-      callback(helper, assert);
-    }
-  };
-}
-
-function createWorker(assert, xrayWindow, contentScript, done) {
-  let loader = Loader(module);
-  let Worker = loader.require("sdk/content/worker").Worker;
-  let worker = Worker({
-    window: xrayWindow,
-    contentScript: [
-      'let assert, done; new ' + function () {
-        assert = function assert(v, msg) {
-          self.port.emit("assert", {assertion:v, msg:msg});
-        }
-        done = function done() {
-          self.port.emit("done");
-        }
-      },
-      contentScript
-    ]
-  });
-
-  worker.port.on("done", done);
-  worker.port.on("assert", function (data) {
-    assert.ok(data.assertion, data.msg);
-  });
-
-  return worker;
-}
-
-/* Examples for the `createProxyTest` uses */
-
-var html = "<script>var documentGlobal = true</script>";
-
-exports["test Create Proxy Test"] = createProxyTest(html, function (helper, assert) {
-  // You can get access to regular `test` object in second argument of
-  // `createProxyTest` method:
-  assert.ok(helper.rawWindow.documentGlobal,
-              "You have access to a raw window reference via `helper.rawWindow`");
-  assert.ok(!("documentGlobal" in helper.xrayWindow),
-              "You have access to an XrayWrapper reference via `helper.xrayWindow`");
-
-  // If you do not create a Worker, you have to call helper.done(),
-  // in order to say when your test is finished
-  helper.done();
-});
-
-exports["test Create Proxy Test With Worker"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    "new " + function WorkerScope() {
-      assert(true, "You can do assertions in your content script");
-      // And if you create a worker, you either have to call `done`
-      // from content script or helper.done()
-      done();
-    }
-  );
-
-});
-
-exports["test Create Proxy Test With Events"] = createProxyTest("", function (helper, assert) {
-
-  let worker = helper.createWorker(
-    "new " + function WorkerScope() {
-      self.port.emit("foo");
-    }
-  );
-
-  worker.port.on("foo", function () {
-    assert.pass("You can use events");
-    // And terminate your test with helper.done:
-    helper.done();
-  });
-
-});
-
-/* Disabled due to bug 1038432
-// Bug 714778: There was some issue around `toString` functions
-//             that ended up being shared between content scripts
-exports["test Shared To String Proxies"] = createProxyTest("", function(helper) {
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // We ensure that `toString` can't be modified so that nothing could
-      // leak to/from the document and between content scripts
-      // It only applies to JS proxies, there isn't any such issue with xrays.
-      //document.location.toString = function foo() {};
-      document.location.toString.foo = "bar";
-      assert("foo" in document.location.toString, "document.location.toString can be modified");
-      assert(document.location.toString() == "data:text/html;charset=utf-8,",
-             "First document.location.toString()");
-      self.postMessage("next");
-    }
-  );
-  worker.on("message", function () {
-    helper.createWorker(
-      'new ' + function ContentScriptScope2() {
-        assert(!("foo" in document.location.toString),
-               "document.location.toString is different for each content script");
-        assert(document.location.toString() == "data:text/html;charset=utf-8,",
-               "Second document.location.toString()");
-        done();
-      }
-    );
-  });
-});
-*/
-
-// Ensure that postMessage is working correctly across documents with an iframe
-var html = '<iframe id="iframe" name="test" src="data:text/html;charset=utf-8," />';
-exports["test postMessage"] = createProxyTest(html, function (helper, assert) {
-  let ifWindow = helper.xrayWindow.document.getElementById("iframe").contentWindow;
-  // Listen without proxies, to check that it will work in regular case
-  // simulate listening from a web document.
-  ifWindow.addEventListener("message", function(event) {
-    // As we are in system principal, event is an XrayWrapper
-    // xrays use current compartments when calling postMessage method.
-    // Whereas js proxies was using postMessage method compartment,
-    // not the caller one.
-    assert.strictEqual(event.source, helper.xrayWindow,
-                      "event.source is the top window");
-    assert.equal(event.origin, testHost, "origin matches testHost");
-
-    assert.equal(event.data, "{\"foo\":\"bar\\n \\\"escaped\\\".\"}",
-                     "message data is correct");
-
-    helper.done();
-  }, {once: true});
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      var json = JSON.stringify({foo : "bar\n \"escaped\"."});
-
-      document.getElementById("iframe").contentWindow.postMessage(json, "*");
-    }
-  );
-});
-
-var html = '<input id="input2" type="checkbox" />';
-exports["test Object Listener"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Test objects being given as event listener
-      let input = document.getElementById("input2");
-      let myClickListener = {
-        called: false,
-        handleEvent: function(event) {
-          assert(this === myClickListener, "`this` is the original object");
-          assert(!this.called, "called only once");
-          this.called = true;
-          assert(event.target, input, "event.target is the wrapped window");
-          done();
-        }
-      };
-
-      window.addEventListener("click", myClickListener, true);
-      input.click();
-      window.removeEventListener("click", myClickListener, true);
-    }
-  );
-
-});
-
-exports["test Object Listener 2"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    ('new ' + function ContentScriptScope() {
-      // variable replaced with `testHost`
-      let testHost = "TOKEN";
-      // Verify object as DOM event listener
-      let myMessageListener = {
-        called: false,
-        handleEvent: function(event) {
-          window.removeEventListener("message", myMessageListener, true);
-
-          assert(this == myMessageListener, "`this` is the original object");
-          assert(!this.called, "called only once");
-          this.called = true;
-          assert(event.target == document.defaultView, "event.target is the wrapped window");
-          assert(event.source == document.defaultView, "event.source is the wrapped window");
-          assert(event.origin == testHost, "origin matches testHost");
-          assert(event.data == "ok", "message data is correct");
-          done();
-        }
-      };
-
-      window.addEventListener("message", myMessageListener, true);
-      document.defaultView.postMessage("ok", '*');
-    }
-  ).replace("TOKEN", testHost));
-
-});
-
-var html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
-             '<input id="input2" type="checkbox" />';
-
-exports.testStringOverload = createProxyTest(html, function (helper, assert) {
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // RightJS is hacking around String.prototype, and do similar thing:
-      // Pass `this` from a String prototype method.
-      // It is funny because typeof this == "object"!
-      // So that when we pass `this` to a native method,
-      // our proxy code can fail on another even more crazy thing.
-      // See following test to see what fails around proxies.
-      String.prototype.update = function () {
-        assert(typeof this == "object", "in update, `this` is an object");
-        assert(this.toString() == "input", "in update, `this.toString works");
-        return document.querySelectorAll(this);
-      };
-      assert("input".update().length == 3, "String.prototype overload works");
-      done();
-    }
-  );
-});
-
-exports["test Element.matches()"] = createProxyTest("", function (helper) {
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check matches XrayWrappers bug (Bug 658909):
-      // Test that Element.matches() does not return bad results when we are
-      // not calling it from the node itself.
-      assert(document.createElement( "div" ).matches("div"),
-             "matches works while being called from the node");
-      assert(document.documentElement.matches.call(
-               document.createElement( "div" ),
-               "div"
-             ),
-             "matches works while being called from a " +
-             "function reference to " +
-             "document.documentElement.matches.call");
-      done();
-    }
-  );
-});
-
-exports["test Events Overload"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // If we add a "____proxy" attribute on XrayWrappers in order to store
-      // the related proxy to create an unique proxy for each wrapper;
-      // we end up setting this attribute to prototype objects :x
-      // And so, instances created with such prototype will be considered
-      // as equal to the prototype ...
-      //   // Internal method that return the proxy for a given XrayWrapper
-      //   function proxify(obj) {
-      //     if (obj._proxy) return obj._proxy;
-      //     return obj._proxy = Proxy.create(...);
-      //   }
-      //
-      //   // Get a proxy of an XrayWrapper prototype object
-      //   let proto = proxify(xpcProto);
-      //
-      //   // Use this proxy as a prototype
-      //   function Constr() {}
-      //   Constr.proto = proto;
-      //
-      //   // Try to create an instance using this prototype
-      //   let xpcInstance = new Constr();
-      //   let wrapper = proxify(xpcInstance)
-      //
-      //   xpcProto._proxy = proto and as xpcInstance.__proto__ = xpcProto,
-      //   xpcInstance._proxy = proto ... and profixy(xpcInstance) = proto :(
-      //
-      let proto = window.document.createEvent('HTMLEvents').__proto__;
-      window.Event.prototype = proto;
-      let event = document.createEvent('HTMLEvents');
-      assert(event !== proto, "Event should not be equal to its prototype");
-      event.initEvent('dataavailable', true, true);
-      assert(event.type === 'dataavailable', "Events are working fine");
-      done();
-    }
-  );
-
-});
-
-exports["test Nested Attributes"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // XrayWrappers has a bug when you set an attribute on it,
-      // in some cases, it creates an unnecessary wrapper that introduces
-      // a different object that refers to the same original object
-      // Check that our wrappers don't reproduce this bug
-      // SEE BUG 658560: Fix identity problem with CrossOriginWrappers
-      let o = {sandboxObject:true};
-      window.nested = o;
-      o.foo = true;
-      assert(o === window.nested, "Nested attribute to sandbox object should not be proxified");
-      window.nested = document;
-      assert(window.nested === document, "Nested attribute to proxy should not be double proxified");
-      done();
-    }
-  );
-
-});
-
-exports["test Form nodeName"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Check form[nodeName]
-      let form = document.createElement("form");
-      let input = document.createElement("input");
-      input.setAttribute("name", "test");
-      form.appendChild(input);
-      body.appendChild(form);
-      assert(form.test == input, "form[nodeName] is valid");
-      body.removeChild(form);
-      done();
-    }
-  );
-
-});
-
-exports["test localStorage"] = createProxyTest("", function (helper, assert) {
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check localStorage:
-      assert(window.localStorage, "has access to localStorage");
-      window.localStorage.name = 1;
-      assert(window.localStorage.name == 1, "localStorage appears to work");
-
-      self.port.on("step2", function () {
-        window.localStorage.clear();
-        assert(window.localStorage.name == undefined, "localStorage really, really works");
-        done();
-      });
-      self.port.emit("step1");
-    }
-  );
-
-  worker.port.on("step1", function () {
-    assert.equal(helper.rawWindow.localStorage.name, 1, "localStorage really works");
-    worker.port.emit("step2");
-  });
-
-});
-
-exports["test Auto Unwrap Custom Attributes"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Setting a custom object to a proxy attribute is not wrapped when we get it afterward
-      let object = {custom: true, enumerable: false};
-      body.customAttribute = object;
-      assert(object === body.customAttribute, "custom JS attributes are not wrapped");
-      done();
-    }
-  );
-
-});
-
-exports["test Object Tag"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // <object>, <embed> and other tags return typeof 'function'
-      let flash = document.createElement("object");
-      assert(typeof flash == "function", "<object> is typeof 'function'");
-      assert(flash.toString().match(/\[object HTMLObjectElement.*\]/), "<object> is HTMLObjectElement");
-      assert("setAttribute" in flash, "<object> has a setAttribute method");
-      done();
-    }
-  );
-
-});
-
-exports["test Highlight toString Behavior"] = createProxyTest("", function (helper, assert) {
-  // We do not have any workaround this particular use of toString
-  // applied on <object> elements. So disable this test until we found one!
-  //assert.equal(helper.rawWindow.Object.prototype.toString.call(flash), "[object HTMLObjectElement]", "<object> is HTMLObjectElement");
-  function f() {};
-  let funToString = Object.prototype.toString.call(f);
-  assert.ok(/\[object Function.*\]/.test(funToString), "functions are functions 1");
-
-  // This is how jquery call toString:
-  let strToString = helper.rawWindow.Object.prototype.toString.call("");
-  assert.ok(/\[object String.*\]/.test(strToString), "strings are strings");
-
-  let o = {__exposedProps__:{}};
-  let objToString = helper.rawWindow.Object.prototype.toString.call(o);
-  assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects");
-
-  // Make sure to pass a function from the same compartments
-  // or toString will return [object Object] on FF8+
-  let f2 = helper.rawWindow.eval("(function () {})");
-  let funToString2 = helper.rawWindow.Object.prototype.toString.call(f2);
-  assert.ok(/\[object Function.*\]/.test(funToString2), "functions are functions 2");
-
-  helper.done();
-});
-
-exports["test Document TagName"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Check document[tagName]
-      let div = document.createElement("div");
-      div.setAttribute("name", "test");
-      body.appendChild(div);
-      assert(!document.test, "document[divName] is undefined");
-      body.removeChild(div);
-
-      let form = document.createElement("form");
-      form.setAttribute("name", "test");
-      body.appendChild(form);
-      assert(document.test == form, "document[formName] is valid");
-      body.removeChild(form);
-
-      let img = document.createElement("img");
-      img.setAttribute("name", "test");
-      body.appendChild(img);
-      assert(document.test == img, "document[imgName] is valid");
-      body.removeChild(img);
-      done();
-    }
-  );
-
-});
-
-var html = '<iframe id="iframe" name="test" src="data:text/html;charset=utf-8," />';
-exports["test Window Frames"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'let glob = this; new ' + function ContentScriptScope() {
-      // Check window[frameName] and window.frames[i]
-      let iframe = document.getElementById("iframe");
-      //assert(window.frames.length == 1, "The iframe is reported in window.frames check1");
-      //assert(window.frames[0] == iframe.contentWindow, "The iframe is reported in window.frames check2");
-      assert(window.test == iframe.contentWindow, "window[frameName] is valid");
-      done();
-    }
-  );
-
-});
-
-exports["test Collections"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Highlight XPCNativeWrapper bug with HTMLCollection
-      // tds[0] is only defined on first access :o
-      let body = document.body;
-      let div = document.createElement("div");
-      body.appendChild(div);
-      div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
-      let tds = div.getElementsByTagName("td");
-      assert(tds[0] == tds[0], "We can get array element multiple times");
-      body.removeChild(div);
-      done();
-    }
-  );
-
-});
-
-var html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
-             '<input id="input2" type="checkbox" />';
-exports["test Collections 2"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify that NodeList/HTMLCollection are working fine
-      let body = document.body;
-      let inputs = body.getElementsByTagName("input");
-      assert(body.childNodes.length == 3, "body.childNodes length is correct");
-      assert(inputs.length == 3, "inputs.length is correct");
-      assert(body.childNodes[0] == inputs[0], "body.childNodes[0] is correct");
-      assert(body.childNodes[1] == inputs[1], "body.childNodes[1] is correct");
-      assert(body.childNodes[2] == inputs[2], "body.childNodes[2] is correct");
-      let count = 0;
-      for(let i in body.childNodes) {
-        count++;
-      }
-
-      assert(count >= 3, "body.childNodes is iterable");
-      done();
-    }
-  );
-
-});
-
-exports["test XMLHttpRequest"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // XMLHttpRequest doesn't support XMLHttpRequest.apply,
-      // that may break our proxy code
-      assert(new window.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object");
-      done();
-    }
-  );
-
-});
-
-exports["test XPathResult"] = createProxyTest("", function (helper, assert) {
-  const XPathResultTypes = ["ANY_TYPE",
-                            "NUMBER_TYPE", "STRING_TYPE", "BOOLEAN_TYPE",
-                            "UNORDERED_NODE_ITERATOR_TYPE",
-                            "ORDERED_NODE_ITERATOR_TYPE",
-                            "UNORDERED_NODE_SNAPSHOT_TYPE",
-                            "ORDERED_NODE_SNAPSHOT_TYPE",
-                            "ANY_UNORDERED_NODE_TYPE",
-                            "FIRST_ORDERED_NODE_TYPE"];
-
-  // Check XPathResult bug with constants being undefined on XPCNativeWrapper
-  let xpcXPathResult = helper.xrayWindow.XPathResult;
-
-  XPathResultTypes.forEach(function(type, i) {
-    assert.equal(xpcXPathResult.wrappedJSObject[type],
-                     helper.rawWindow.XPathResult[type],
-                     "XPathResult's constants are valid on unwrapped node");
-
-    assert.equal(xpcXPathResult[type], i,
-                     "XPathResult's constants are defined on " +
-                     "XPCNativeWrapper (platform bug #)");
-  });
-
-  let value = helper.rawWindow.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      self.port.on("value", function (value) {
-        // Check that our work around is working:
-        assert(window.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE === value,
-               "XPathResult works correctly on Proxies");
-        done();
-      });
-    }
-  );
-  worker.port.emit("value", value);
-});
-
-exports["test Prototype Inheritance"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify that inherited prototype function like initEvent
-      // are handled correctly. (e2.type will return an error if it's not the case)
-      let event1 = document.createEvent( 'MouseEvents' );
-      event1.initEvent( "click", true, true );
-      let event2 = document.createEvent( 'MouseEvents' );
-      event2.initEvent( "click", true, true );
-      assert(event2.type == "click", "We are able to create an event");
-      done();
-    }
-  );
-
-});
-
-exports["test Functions"] = createProxyTest("", function (helper) {
-
-  helper.rawWindow.callFunction = function callFunction(f) {
-    return f();
-  };
-  helper.rawWindow.isEqual = function isEqual(a, b) {
-    return a == b;
-  };
-  // bug 784116: workaround in order to allow proxy code to cache proxies on
-  // these functions:
-  helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'};
-  helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'};
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check basic usage of functions
-      let closure2 = function () {return "ok";};
-      assert(window.wrappedJSObject.callFunction(closure2) == "ok", "Function references work");
-
-      // Ensure that functions are cached when being wrapped to native code
-      let closure = function () {};
-      assert(window.wrappedJSObject.isEqual(closure, closure), "Function references are cached before being wrapped to native");
-      done();
-    }
-  );
-
-});
-
-var html = '<input id="input2" type="checkbox" />';
-exports["test Listeners"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify listeners:
-      let input = document.getElementById("input2");
-      assert(input, "proxy.getElementById works");
-
-      function onclick() {};
-      input.onclick = onclick;
-      assert(input.onclick === onclick, "on* attributes are equal to original function set");
-
-      let addEventListenerCalled = false;
-      let expandoCalled = false;
-      input.addEventListener("click", function (event) {
-        assert(!addEventListenerCalled, "closure given to addEventListener is called once");
-        if (addEventListenerCalled)
-          return;
-        addEventListenerCalled = true;
-
-        assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
-
-        let input2 = document.getElementById("input2");
-
-        input.onclick = function (event) {
-          input.onclick = null;
-          assert(!expandoCalled, "closure set to expando is called once");
-          if (expandoCalled) return;
-          expandoCalled = true;
-
-          assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
-
-          setTimeout(function () {
-            input.click();
-            done();
-          }, 0);
-
-        }
-
-        setTimeout(function () {
-          input.click();
-        }, 0);
-
-      }, {capture: true, once: true});
-
-      input.click();
-    }
-  );
-
-});
-
-exports["test requestAnimationFrame"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      var self = (function() { return this; })();
-      window.requestAnimationFrame(function callback() {
-        assert(self == this, "self is equal to `this`");
-        done();
-      });
-    }
-  );
-
-});
-
-exports["testGlobalScope"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'let toplevelScope = true;' +
-    'assert(window.toplevelScope, "variables in toplevel scope are set to `window` object");' +
-    'assert(this.toplevelScope, "variables in toplevel scope are set to `this` object");' +
-    'done();'
-  );
-
-});
-
-// Bug 715755: proxy code throw an exception on COW
-// Create an http server in order to simulate real cross domain documents
-exports["test Cross Domain Iframe"] = createProxyTest("", function (helper) {
-  let serverPort = 8099;
-  let server = require("./httpd").startServerAsync(serverPort);
-  server.registerPathHandler("/", function handle(request, response) {
-    // Returns the webpage that receive a message and forward it back to its
-    // parent document by appending ' world'.
-    let content = "<html><head><meta charset='utf-8'></head>\n";
-    content += "<script>\n";
-    content += "  window.addEventListener('message', function (event) {\n";
-    content += "    parent.postMessage(event.data + ' world', '*');\n";
-    content += "  }, true);\n";
-    content += "</script>\n";
-    content += "<body></body>\n";
-    content += "</html>\n";
-    response.write(content);
-  });
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Waits for the server page url
-      self.on("message", function (url) {
-        // Creates an iframe with this page
-        let iframe = document.createElement("iframe");
-        iframe.addEventListener("load", function() {
-          try {
-            // Try to communicate with iframe's content
-            window.addEventListener("message", function(event) {
-              assert(event.data == "hello world", "COW works properly");
-              self.port.emit("end");
-            }, {capture: true, once: true});
-            iframe.contentWindow.postMessage("hello", "*");
-          } catch(e) {
-            assert(false, "COW fails : "+e.message);
-          }
-        }, {capture: true, once: true});
-        iframe.setAttribute("src", url);
-        document.body.appendChild(iframe);
-      });
-    }
-  );
-
-  worker.port.on("end", function () {
-    server.stop(helper.done);
-  });
-
-  worker.postMessage("http://localhost:" + serverPort + "/");
-
-});
-
-// Bug 769006: Ensure that MutationObserver works fine with proxies
-var html = '<a href="foo">link</a>';
-exports["test MutationObvserver"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      if (typeof MutationObserver == "undefined") {
-        assert(true, "No MutationObserver for this FF version");
-        done();
-        return;
-      }
-      let link = document.getElementsByTagName("a")[0];
-
-      // Register a Mutation observer
-      let obs = new MutationObserver(function(mutations){
-        // Ensure that mutation data are valid
-        assert(mutations.length == 1, "only one attribute mutation");
-        let mutation = mutations[0];
-        assert(mutation.type == "attributes", "check `type`");
-        assert(mutation.target == link, "check `target`");
-        assert(mutation.attributeName == "href", "check `attributeName`");
-        assert(mutation.oldValue == "foo", "check `oldValue`");
-        obs.disconnect();
-        done();
-      });
-      obs.observe(document, {
-        subtree: true,
-        attributes: true,
-        attributeOldValue: true,
-        attributeFilter: ["href"]
-      });
-
-      // Modify the DOM
-      link.setAttribute("href", "bar");
-    }
-  );
-
-});
-
-var html = '<script>' +
-  'var accessCheck = function() {' +
-  '  assert(true, "exporting function works");' +
-  '  try{' +
-  '    exportedObj.prop;' +
-  '    assert(false, "content should not have access to content-script");' +
-  '  } catch(e) {' +
-  '    assert(e.toString().indexOf("Permission denied") != -1,' +
-  '           "content should not have access to content-script");' +
-  '  }' +
-  '}</script>';
-exports["test nsEp for content-script"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'let glob = this; new ' + function ContentScriptScope() {
-
-      exportFunction(assert, unsafeWindow, { defineAs: "assert" });
-      window.wrappedJSObject.assert(true, "assert exported");
-      window.wrappedJSObject.exportedObj = { prop: 42 };
-      window.wrappedJSObject.accessCheck();
-      done();
-    }
-  );
-
-});
-
-// require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js
+++ /dev/null
@@ -1,1124 +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";
-
-// Skipping due to window creation being unsupported in Fennec
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require("chrome");
-const { on } = require("sdk/event/core");
-const { setTimeout } = require("sdk/timers");
-const { LoaderWithHookedConsole, Loader } = require("sdk/test/loader");
-const { Worker } = require("sdk/content/worker");
-const { close } = require("sdk/window/helpers");
-const { set: setPref } = require("sdk/preferences/service");
-const { isArray } = require("sdk/lang/type");
-const { URL } = require('sdk/url');
-const fixtures = require("./fixtures");
-const system = require("sdk/system/events");
-
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo";
-
-const WINDOW_SCRIPT_URL = "data:text/html;charset=utf-8," +
-                          "<script>window.addEventListener('message', function (e) {" +
-                          "  if (e.data === 'from -> content-script')" +
-                          "    window.postMessage('from -> window', '*');" +
-                          "});</script>";
-
-function makeWindow() {
-  let content =
-    "<?xml version=\"1.0\"?>" +
-    "<window " +
-    "xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">" +
-    "<script>var documentValue=true;</script>" +
-    "</window>";
-  var url = "data:application/vnd.mozilla.xul+xml;charset=utf-8," +
-            encodeURIComponent(content);
-  var features = ["chrome", "width=10", "height=10"];
-
-  return Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher).
-         openWindow(null, url, null, features.join(","), null);
-}
-
-// Listen for only first one occurence of DOM event
-function listenOnce(node, eventName, callback) {
-  node.addEventListener(eventName, function(event) {
-    callback(node);
-  }, {capture: true, once: true});
-}
-
-// Load a given url in a given browser and fires the callback when it is loaded
-function loadAndWait(browser, url, callback) {
-  listenOnce(browser, "load", callback);
-  // We have to wait before calling `loadURI` otherwise, if we call
-  // `loadAndWait` during browser load event, the history will be broken
-  setTimeout(function () {
-    browser.loadURI(url);
-  }, 0);
-}
-
-// Returns a test function that will automatically open a new chrome window
-// with a <browser> element loaded on a given content URL
-// The callback receive 3 arguments:
-// - test: reference to the jetpack test object
-// - browser: a reference to the <browser> xul node
-// - done: a callback to call when test is over
-function WorkerTest(url, callback) {
-  return function testFunction(assert, done) {
-    let chromeWindow = makeWindow();
-    chromeWindow.addEventListener("load", function() {
-      let browser = chromeWindow.document.createElement("browser");
-      browser.setAttribute("type", "content");
-      chromeWindow.document.documentElement.appendChild(browser);
-      // Wait for about:blank load event ...
-      listenOnce(browser, "load", function onAboutBlankLoad() {
-        // ... before loading the expected doc and waiting for its load event
-        loadAndWait(browser, url, function onDocumentLoaded() {
-          callback(assert, browser, function onTestDone() {
-
-            close(chromeWindow).then(done);
-          });
-        });
-      });
-    }, {capture: true, once: true});
-  };
-}
-
-exports["test:sample"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    assert.notEqual(browser.contentWindow.location.href, "about:blank",
-                        "window is now on the right document");
-
-    let window = browser.contentWindow
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        // window is accessible
-        let myLocation = window.location.toString();
-        self.on("message", function(data) {
-          if (data == "hi!")
-            self.postMessage("bye!");
-        });
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.equal("bye!", msg);
-        assert.equal(worker.url, window.location.href,
-                         "worker.url still works");
-        done();
-      }
-    });
-
-    assert.equal(worker.url, window.location.href,
-                     "worker.url works");
-    assert.equal(worker.contentURL, window.location.href,
-                     "worker.contentURL works");
-    worker.postMessage("hi!");
-  }
-);
-
-exports["test:emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (data) {
-            self.port.emit("content-to-addon", data);
-          });
-
-          // Check for global pollution
-          //if (typeof on != "undefined")
-          //  self.postMessage("`on` is in globals");
-          if (typeof once != "undefined")
-            self.postMessage("`once` is in globals");
-          if (typeof emit != "undefined")
-            self.postMessage("`emit` is in globals");
-
-        },
-        onMessage: function(msg) {
-          assert.fail("Got an unexpected message : "+msg);
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.port.emit("addon-to-content", "event data");
-  }
-);
-
-exports["test:emit hack message"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.port
-          self.port.on("message", function (data) {
-            self.port.emit("message", data);
-          });
-          // We should not receive message on self, but only on self.port
-          self.on("message", function (data) {
-            self.postMessage("message", data);
-          });
-        },
-        onError: function(e) {
-          assert.fail("Got exception: "+e);
-        }
-      });
-
-    worker.port.on("message", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.on("message", function (data) {
-      assert.fail("Got an unexpected message : "+msg);
-    });
-    worker.port.emit("message", "event data");
-  }
-);
-
-exports["test:n-arguments emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let repeat = 0;
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (a1, a2, a3) {
-            self.port.emit("content-to-addon", a1, a2, a3);
-          });
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (arg1, arg2, arg3) {
-      if (!repeat++) {
-        this.emit("addon-to-content", "first argument", "second", "third");
-      } else {
-        assert.equal(arg1, "first argument");
-        assert.equal(arg2, "second");
-        assert.equal(arg3, "third");
-        done();
-      }
-    });
-    worker.port.emit("addon-to-content", "first argument", "second", "third");
-  }
-);
-
-exports["test:post-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          self.on("message", function (message) {
-            self.postMessage([ message.fun === undefined,
-                               typeof message.w,
-                               message.w && "port" in message.w,
-                               message.w._url,
-                               Array.isArray(message.array),
-                               JSON.stringify(message.array)]);
-          });
-        }
-      });
-
-    // Validate worker.onMessage
-    let array = [1, 2, 3];
-    worker.on("message", function (message) {
-      assert.ok(message[0], "function becomes undefined");
-      assert.equal(message[1], "object", "object stays object");
-      assert.ok(message[2], "object's attributes are enumerable");
-      assert.equal(message[3], DEFAULT_CONTENT_URL,
-                       "jsonable attributes are accessible");
-      // See bug 714891, Arrays may be broken over compartements:
-      assert.ok(message[4], "Array keeps being an array");
-      assert.equal(message[5], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-
-    worker.postMessage({ fun: function () {}, w: worker, array: array });
-  }
-);
-
-exports["test:emit-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (fun, w, obj, array) {
-            self.port.emit("content-to-addon", [
-                            fun === null,
-                            typeof w,
-                            "port" in w,
-                            w._url,
-                            "fun" in obj,
-                            Object.keys(obj.dom).length,
-                            Array.isArray(array),
-                            JSON.stringify(array)
-                          ]);
-          });
-        }
-      });
-
-    // Validate worker.port
-    let array = [1, 2, 3];
-    worker.port.on("content-to-addon", function (result) {
-      assert.ok(result[0], "functions become null");
-      assert.equal(result[1], "object", "objects stay objects");
-      assert.ok(result[2], "object's attributes are enumerable");
-      assert.equal(result[3], DEFAULT_CONTENT_URL,
-                       "json attribute is accessible");
-      assert.ok(!result[4], "function as object attribute is removed");
-      assert.equal(result[5], 0, "DOM nodes are converted into empty object");
-      // See bug 714891, Arrays may be broken over compartments:
-      assert.ok(result[6], "Array keeps being an array");
-      assert.equal(result[7], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-
-    let obj = {
-      fun: function () {},
-      dom: browser.contentWindow.document.createElement("div")
-    };
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-    worker.port.emit("addon-to-content", function () {}, worker, obj, array);
-  }
-);
-
-exports["test:content is wrapped"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(!window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has a wrapped access to content document");
-        done();
-      }
-    });
-  }
-);
-
-// ContentWorker is not for chrome
-/*
-exports["test:chrome is unwrapped"] = function(assert, done) {
-  let window = makeWindow();
-
-  listenOnce(window, "load", function onload() {
-
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has an unwrapped access to chrome document");
-        close(window).then(done);
-      }
-    });
-
-  });
-}
-*/
-
-exports["test:nothing is leaked to content script"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage([
-          "ContentWorker" in window,
-          "UNWRAP_ACCESS_KEY" in window,
-          "getProxyForObject" in window
-        ]);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(list) {
-        assert.ok(!list[0], "worker API contrustor isn't leaked");
-        assert.ok(!list[1], "Proxy API stuff isn't leaked 1/2");
-        assert.ok(!list[2], "Proxy API stuff isn't leaked 2/2");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:ensure console.xxx works in cs"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    const EXPECTED = ["time", "log", "info", "warn", "error", "error", "timeEnd"];
-
-    let calls = [];
-    let levels = [];
-
-    system.on('console-api-log-event', onMessage);
-
-    function onMessage({ subject }) {
-      calls.push(subject.wrappedJSObject.arguments[0]);
-      levels.push(subject.wrappedJSObject.level);
-    }
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.time("time");
-        console.log("log");
-        console.info("info");
-        console.warn("warn");
-        console.error("error");
-        console.debug("debug");
-        console.exception("error");
-        console.timeEnd("timeEnd");
-        self.postMessage();
-      },
-      onMessage: function() {
-        system.off('console-api-log-event', onMessage);
-
-        assert.equal(JSON.stringify(calls),
-          JSON.stringify(EXPECTED),
-          "console methods have been called successfully, in expected order");
-
-        assert.equal(JSON.stringify(levels),
-          JSON.stringify(EXPECTED),
-          "console messages have correct log levels, in expected order");
-
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout works with string argument"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var docVal=5;</script>",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function ContentScriptScope() {
-        // must use "window.scVal" instead of "var csVal"
-        // since we are inside ContentScriptScope function.
-        // i'm NOT putting code-in-string inside code-in-string </YO DAWG>
-        window.csVal = 13;
-        setTimeout("self.postMessage([" +
-                      "csVal, " +
-                      "window.docVal, " +
-                      "'ContentWorker' in window, " +
-                      "'UNWRAP_ACCESS_KEY' in window, " +
-                      "'getProxyForObject' in window, " +
-                    "])", 1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function([csVal, docVal, chrome1, chrome2, chrome3]) {
-        // test timer code is executed in the correct context
-        assert.equal(csVal, 13, "accessing content-script values");
-        assert.notEqual(docVal, 5, "can't access document values (directly)");
-        assert.ok(!chrome1 && !chrome2 && !chrome3, "nothing is leaked from chrome");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval works with string argument"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval('self.postMessage(1)', 50)",
-      contentScriptWhen: "ready",
-      onMessage: function(one) {
-        count++;
-        assert.equal(one, 1, "got " + count + " message(s) from setInterval");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval(() => { throw Error('ubik') }, 50)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        count++;
-        assert.equal(err.message, "ubik",
-            "error (correctly) propagated  " + count + " time(s)");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout throws array, passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout(function() { throw ['array', 42] }, 1)",
-      contentScriptWhen: "ready",
-      onError: function(arr) {
-        assert.ok(isArray(arr),
-            "the type of thrown/propagated object is array");
-        assert.ok(arr.length==2,
-            "the propagated thrown array is the right length");
-        assert.equal(arr[1], 42,
-            "element inside the thrown array correctly propagated");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout string arg with SyntaxError to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout('syntax 123 error', 1)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        assert.equal(err.name, "SyntaxError",
-            "received SyntaxError thrown from bad code in string argument to setTimeout");
-        assert.ok('fileName' in err,
-            "propagated SyntaxError contains a fileName property");
-        assert.ok('stack' in err,
-            "propagated SyntaxError contains a stack property");
-        assert.equal(err.message, "missing ; before statement",
-            "propagated SyntaxError has the correct (helpful) message");
-        assert.equal(err.lineNumber, 1,
-            "propagated SyntaxError was thrown on the right lineNumber");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout can't be cancelled by content"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setTimeout(function () {
-          self.postMessage("timeout");
-        }, 100);
-        unsafeWindow.eval("clearTimeout("+id+");");
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content didn't managed to cancel our setTimeout");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:clearTimeout"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id1 = setTimeout(function() {
-          self.postMessage("failed");
-        }, 10);
-        let id2 = setTimeout(function() {
-          self.postMessage("done");
-        }, 100);
-        clearTimeout(id1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "failed") {
-          assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("timer cancelled");
-          done();
-        }
-      }
-    });
-  }
-);
-
-exports["test:clearInterval"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let called = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setInterval(function() {
-          self.postMessage("intreval")
-          clearInterval(id)
-          setTimeout(function() {
-            self.postMessage("done")
-          }, 100)
-        }, 10);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "intreval") {
-          called = called + 1;
-          if (called > 1) assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("interval cancelled");
-          done();
-        }
-      }
-    });
-  }
-)
-
-exports["test:setTimeout are unregistered on content unload"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let originalWindow = browser.contentWindow;
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        document.title = "ok";
-        let i = 0;
-        setInterval(function () {
-          document.title = i++;
-        }, 10);
-      },
-      contentScriptWhen: "ready"
-    });
-
-    // Change location so that content script is destroyed,
-    // and all setTimeout/setInterval should be unregistered.
-    // Wait some cycles in order to execute some intervals.
-    setTimeout(function () {
-      // Bug 689621: Wait for the new document load so that we are sure that
-      // previous document cancelled its intervals
-      let url2 = "data:text/html;charset=utf-8,<title>final</title>";
-      loadAndWait(browser, url2, function onload() {
-        let titleAfterLoad = originalWindow.document.title;
-        // Wait additional cycles to verify that intervals are really cancelled
-        setTimeout(function () {
-          assert.equal(browser.contentDocument.title, "final",
-                           "New document has not been modified");
-          assert.equal(originalWindow.document.title, titleAfterLoad,
-                           "Nor previous one");
-
-          done();
-        }, 100);
-      });
-    }, 100);
-  }
-);
-
-exports['test:check window attribute in iframes'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    // Create a first iframe and wait for its loading
-    let contentWin = browser.contentWindow;
-    let contentDoc = contentWin.document;
-    let iframe = contentDoc.createElement("iframe");
-    contentDoc.body.appendChild(iframe);
-
-    listenOnce(iframe, "load", function onload() {
-
-      // Create a second iframe inside the first one and wait for its loading
-      let iframeDoc = iframe.contentWindow.document;
-      let subIframe = iframeDoc.createElement("iframe");
-      iframeDoc.body.appendChild(subIframe);
-
-      listenOnce(subIframe, "load", function onload() {
-        subIframe.removeEventListener("load", onload, true);
-
-        // And finally create a worker against this second iframe
-        let worker =  Worker({
-          window: subIframe.contentWindow,
-          contentScript: 'new ' + function WorkerScope() {
-            self.postMessage([
-              window.top !== window,
-              frameElement,
-              window.parent !== window,
-              top.location.href,
-              parent.location.href,
-            ]);
-          },
-          onMessage: function(msg) {
-            assert.ok(msg[0], "window.top != window");
-            assert.ok(msg[1], "window.frameElement is defined");
-            assert.ok(msg[2], "window.parent != window");
-            assert.equal(msg[3], contentWin.location.href,
-                             "top.location refers to the toplevel content doc");
-            assert.equal(msg[4], iframe.contentWindow.location.href,
-                             "parent.location refers to the first iframe doc");
-            done();
-          }
-        });
-
-      });
-      subIframe.setAttribute("src", "data:text/html;charset=utf-8,bar");
-
-    });
-    iframe.setAttribute("src", "data:text/html;charset=utf-8,foo");
-  }
-);
-
-exports['test:check window attribute in toplevel documents'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage([
-          window.top === window,
-          frameElement,
-          window.parent === window
-        ]);
-      },
-      onMessage: function(msg) {
-        assert.ok(msg[0], "window.top == window");
-        assert.ok(!msg[1], "window.frameElement is null");
-        assert.ok(msg[2], "window.parent == window");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:check worker API with page history"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let url2 = "data:text/html;charset=utf-8,bar";
-
-    loadAndWait(browser, url2, function () {
-      let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Just before the content script is disable, we register a timeout
-          // that will be disable until the page gets visible again
-          self.on("pagehide", function () {
-            setTimeout(function () {
-              self.port.emit("timeout");
-            }, 0);
-          });
-
-          self.on("message", function() {
-            self.postMessage("saw message");
-          });
-
-          self.on("event", function() {
-            self.port.emit("event", "saw event");
-          });
-        },
-        contentScriptWhen: "start"
-      });
-
-      // postMessage works correctly when the page is visible
-      worker.postMessage("ok");
-
-      // We have to wait before going back into history,
-      // otherwise `goBack` won't do anything.
-      setTimeout(function () {
-        browser.goBack();
-      }, 0);
-
-      // Wait for the document to be hidden
-      browser.addEventListener("pagehide", function() {
-        // Now any event sent to this worker should be cached
-
-        worker.postMessage("message");
-        worker.port.emit("event");
-
-        // Display the page with attached content script back in order to resume
-        // its timeout and receive the expected message.
-        // We have to delay this in order to not break the history.
-        // We delay for a non-zero amount of time in order to ensure that we
-        // do not receive the message immediatly, so that the timeout is
-        // actually disabled
-        setTimeout(function () {
-          worker.on("pageshow", function() {
-            let promise = Promise.all([
-              new Promise(resolve => {
-                worker.port.on("event", () => {
-                  assert.pass("Saw event");
-                  resolve();
-                });
-              }),
-              new Promise(resolve => {
-                worker.on("message", () => {
-                  assert.pass("Saw message");
-                  resolve();
-                });
-              }),
-              new Promise(resolve => {
-                worker.port.on("timeout", () => {
-                  assert.pass("Timer fired");
-                  resolve();
-                });
-              })
-            ]);
-            promise.then(done);
-          });
-
-          browser.goForward();
-        }, 500);
-
-      }, {once: true});
-    });
-
-  }
-);
-
-exports['test:conentScriptFile as URL instance'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let url = new URL(fixtures.url("test-contentScriptFile.js"));
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScriptFile: url,
-      onMessage: function(msg) {
-        assert.equal(msg, "msg from contentScriptFile",
-            "received a wrong message from contentScriptFile");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:worker events"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function (assert, browser, done) {
-    let window = browser.contentWindow;
-    let events = [];
-    let worker = Worker({
-      window: window,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage('start');
-      },
-      onAttach: win => {
-        events.push('attach');
-        assert.pass('attach event called when attached');
-        assert.equal(window, win, 'attach event passes in attached window');
-      },
-      onError: err => {
-        assert.equal(err.message, 'Custom',
-          'Error passed into error event');
-        worker.detach();
-      },
-      onMessage: msg => {
-        assert.pass('`onMessage` handles postMessage')
-        throw new Error('Custom');
-      },
-      onDetach: _ => {
-        assert.pass('`onDetach` called when worker detached');
-        done();
-      }
-    });
-    // `attach` event is called synchronously during instantiation,
-    // so we can't listen to that, TODO FIX?
-    //  worker.on('attach', obj => console.log('attach', obj));
-  }
-);
-
-exports["test:onDetach in contentScript on destroy"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-    });
-    browser.contentWindow.addEventListener('hashchange', _ => {
-      assert.equal(browser.contentWindow.location.hash, '#detach!',
-                   "location.href is as expected");
-      done();
-    })
-    worker.destroy();
-  }
-);
-
-exports["test:onDetach in contentScript on unload"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker = loader.require("sdk/content/worker").Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-    });
-    browser.contentWindow.addEventListener('hashchange', _ => {
-      assert.equal(browser.contentWindow.location.hash, '#detach!shutdown',
-                   "location.href is as expected");
-      done();
-    })
-    loader.unload('shutdown');
-  }
-);
-
-exports["test:console method log functions properly"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let logs = [];
-
-    system.on('console-api-log-event', onMessage);
-
-    function onMessage({ subject }) {
-      logs.push(clean(subject.wrappedJSObject.arguments[0]));
-    }
-
-    let clean = message =>
-          message.trim().
-          replace(/[\r\n]/g, " ").
-          replace(/ +/g, " ");
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.log(Function);
-        console.log((foo) => foo * foo);
-        console.log(function foo(bar) { return bar + bar });
-
-        self.postMessage();
-      },
-      onMessage: () => {
-        system.off('console-api-log-event', onMessage);
-
-        assert.deepEqual(logs, [
-          "function Function() { [native code] }",
-          "(foo) => foo * foo",
-          "function foo(bar) { \"use strict\"; return bar + bar }"
-        ]);
-
-        done();
-      }
-    });
-  }
-);
-
-exports["test:global postMessage"] = WorkerTest(
-  WINDOW_SCRIPT_URL,
-  function(assert, browser, done) {
-    let contentScript = "window.addEventListener('message', function (e) {" +
-                        "  if (e.data === 'from -> window')" +
-                        "    self.port.emit('response', e.data, e.origin);" +
-                        "});" +
-                        "postMessage('from -> content-script', '*');";
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker =  loader.require("sdk/content/worker").Worker({
-      window: browser.contentWindow,
-      contentScriptWhen: "ready",
-      contentScript: contentScript
-    });
-
-    worker.port.on("response", (data, origin) => {
-      assert.equal(data, "from -> window", "Communication from content-script to window completed");
-      done();
-    });
-});
-
-exports["test:destroy unbinds listeners from port"] = WorkerTest(
-  "data:text/html;charset=utf-8,portdestroyer",
-  function(assert, browser, done) {
-    let destroyed = false;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.emit("destroy");
-        setInterval(self.port.emit, 10, "ping");
-      },
-      onDestroy: done
-    });
-    worker.port.on("ping", () => {
-      if (destroyed) {
-        assert.fail("Should not call events on port after destroy.");
-      }
-    });
-    worker.port.on("destroy", () => {
-      destroyed = true;
-      worker.destroy();
-      assert.pass("Worker destroyed, waiting for no future listeners handling events.");
-      setTimeout(done, 500);
-    });
-  }
-);
-
-
-exports["test:destroy kills child worker"] = WorkerTest(
-  "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>",
-  function(assert, browser, done) {
-    let worker1 = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.on("ping", detail => {
-          let event = document.createEvent("CustomEvent");
-          event.initCustomEvent("Test:Ping", true, true, detail);
-          document.dispatchEvent(event);
-          self.port.emit("pingsent");
-        });
-
-        let listener = function(event) {
-          self.port.emit("pong", event.detail);
-        };
-
-        self.port.on("detach", () => {
-          window.removeEventListener("Test:Pong", listener);
-        });
-        window.addEventListener("Test:Pong", listener);
-      },
-      onAttach: function() {
-        let worker2 = Worker({
-          window: browser.contentWindow,
-          contentScript: "new " + function WorkerScope() {
-            let listener = function(event) {
-              let newEvent = document.createEvent("CustomEvent");
-              newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-              document.dispatchEvent(newEvent);
-            };
-            self.port.on("detach", () => {
-              window.removeEventListener("Test:Ping", listener);
-            })
-            window.addEventListener("Test:Ping", listener);
-            self.postMessage();
-          },
-          onMessage: function() {
-            worker1.port.emit("ping", "test1");
-            worker1.port.once("pong", detail => {
-              assert.equal(detail, "test1", "Saw the right message");
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-
-                worker2.destroy();
-
-                worker1.port.emit("ping", "test2");
-                worker1.port.once("pong", detail => {
-                  assert.fail("worker2 shouldn't have responded");
-                })
-                worker1.port.once("pingsent", () => {
-                  assert.pass("The message was sent");
-                  worker1.destroy();
-                  done();
-                });
-              });
-            })
-          }
-        });
-      }
-    });
-  }
-);
-
-exports["test:unload kills child worker"] = WorkerTest(
-  "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>",
-  function(assert, browser, done) {
-    let loader = Loader(module);
-    let worker1 = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.on("ping", detail => {
-          let event = document.createEvent("CustomEvent");
-          event.initCustomEvent("Test:Ping", true, true, detail);
-          document.dispatchEvent(event);
-          self.port.emit("pingsent");
-        });
-
-        let listener = function(event) {
-          self.port.emit("pong", event.detail);
-        };
-
-        self.port.on("detach", () => {
-          window.removeEventListener("Test:Pong", listener);
-        });
-        window.addEventListener("Test:Pong", listener);
-      },
-      onAttach: function() {
-        let worker2 = loader.require("sdk/content/worker").Worker({
-          window: browser.contentWindow,
-          contentScript: "new " + function WorkerScope() {
-            let listener = function(event) {
-              let newEvent = document.createEvent("CustomEvent");
-              newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-              document.dispatchEvent(newEvent);
-            };
-            self.port.on("detach", () => {
-              window.removeEventListener("Test:Ping", listener);
-            })
-            window.addEventListener("Test:Ping", listener);
-            self.postMessage();
-          },
-          onMessage: function() {
-            worker1.port.emit("ping", "test1");
-            worker1.port.once("pong", detail => {
-              assert.equal(detail, "test1", "Saw the right message");
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-
-                loader.unload();
-
-                worker1.port.emit("ping", "test2");
-                worker1.port.once("pong", detail => {
-                  assert.fail("worker2 shouldn't have responded");
-                })
-                worker1.port.once("pingsent", () => {
-                  assert.pass("The message was sent");
-                  worker1.destroy();
-                  done();
-                });
-              });
-            })
-          }
-        });
-      }
-    });
-  }
-);
-
-// require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
+++ /dev/null
@@ -1,524 +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 { Loader } = require('sdk/test/loader');
-const { Page } = require("sdk/page-worker");
-const { URL } = require("sdk/url");
-const fixtures = require("./fixtures");
-const testURI = fixtures.url("test.html");
-
-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 Isolate = fn => "(" + fn + ")()";
-
-exports.testSimplePageCreation = function(assert, done) {
-  let page = new Page({
-    contentScript: "self.postMessage(window.location.href)",
-    contentScriptWhen: "end",
-    onMessage: function (message) {
-      assert.equal(message, "about:blank",
-                       "Page Worker should start with a blank page by default");
-      assert.equal(this, page, "The 'this' object is the page itself.");
-      done();
-    }
-  });
-}
-
-/*
- * Tests that we can't be tricked by document overloads as we have access
- * to wrapped nodes
- */
-exports.testWrappedDOM = function(assert, done) {
-  let page = Page({
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.getElementById=3;window.scrollTo=3;</script>",
-    contentScript: 'new ' + function() {
-      function send() {
-        self.postMessage([typeof(document.getElementById), typeof(window.scrollTo)]);
-      }
-      if (document.readyState !== 'complete')
-        window.addEventListener('load', send, true)
-      else
-        send();
-    },
-    onMessage: function (message) {
-      assert.equal(message[0],
-                       "function",
-                       "getElementById from content script is the native one");
-
-      assert.equal(message[1],
-                       "function",
-                       "scrollTo from content script is the native one");
-
-      done();
-    }
-  });
-}
-
-/*
-// We do not offer unwrapped access to DOM since bug 601295 landed
-// See 660780 to track progress of unwrap feature
-exports.testUnwrappedDOM = function(assert, done) {
-  let page = Page({
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.getElementById=3;window.scrollTo=3;</script>",
-    contentScript: "window.addEventListener('load', function () { " +
-                   "return self.postMessage([typeof(unsafeWindow.document.getElementById), " +
-                   "typeof(unsafeWindow.scrollTo)]); }, true)",
-    onMessage: function (message) {
-      assert.equal(message[0],
-                       "number",
-                       "document inside page is free to be changed");
-
-      assert.equal(message[1],
-                       "number",
-                       "window inside page is free to be changed");
-
-      done();
-    }
-  });
-}
-*/
-
-exports.testPageProperties = function(assert) {
-  let page = new Page();
-
-  for (let prop of ['contentURL', 'allow', 'contentScriptFile',
-                         'contentScript', 'contentScriptWhen', 'on',
-                         'postMessage', 'removeListener']) {
-    assert.ok(prop in page, prop + " property is defined on page.");
-  }
-
-  assert.ok(() => page.postMessage("foo") || true,
-              "postMessage doesn't throw exception on page.");
-}
-
-exports.testConstructorAndDestructor = function(assert, done) {
-  let loader = Loader(module);
-  let { Page } = loader.require("sdk/page-worker");
-  let global = loader.sandbox("sdk/page-worker");
-
-  let pagesReady = 0;
-
-  let page1 = Page({
-    contentScript:      "self.postMessage('')",
-    contentScriptWhen:  "end",
-    onMessage:          pageReady
-  });
-  let page2 = Page({
-    contentScript:      "self.postMessage('')",
-    contentScriptWhen:  "end",
-    onMessage:          pageReady
-  });
-
-  assert.notEqual(page1, page2,
-                      "Page 1 and page 2 should be different objects.");
-
-  function pageReady() {
-    if (++pagesReady == 2) {
-      page1.destroy();
-      page2.destroy();
-
-      assert.ok(isDestroyed(page1), "page1 correctly unloaded.");
-      assert.ok(isDestroyed(page2), "page2 correctly unloaded.");
-
-      loader.unload();
-      done();
-    }
-  }
-}
-
-exports.testAutoDestructor = function(assert, done) {
-  let loader = Loader(module);
-  let { Page } = loader.require("sdk/page-worker");
-
-  let page = Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: function() {
-      loader.unload();
-      assert.ok(isDestroyed(page), "Page correctly unloaded.");
-      done();
-    }
-  });
-}
-
-exports.testValidateOptions = function(assert) {
-  assert.throws(
-    () => Page({ contentURL: 'home' }),
-    /The `contentURL` option must be a valid URL\./,
-    "Validation correctly denied a non-URL contentURL"
-  );
-
-  assert.throws(
-    () => Page({ onMessage: "This is not a function."}),
-    /The option "onMessage" must be one of the following types: function/,
-    "Validation correctly denied a non-function onMessage."
-  );
-
-  assert.pass("Options validation is working.");
-}
-
-exports.testContentAndAllowGettersAndSetters = function(assert, done) {
-  let content = "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=3;</script>";
-
-  // Load up the page with testURI initially for the resource:// principal,
-  // then load the actual data:* content, as data:* URIs no longer
-  // have localStorage
-  let page = Page({
-    contentURL: testURI,
-    contentScript: "if (window.location.href==='"+testURI+"')" +
-      "  self.postMessage('reload');" +
-      "else " +
-      "  self.postMessage(window.localStorage.allowScript)",
-    contentScriptWhen: "end",
-    onMessage: step0
-  });
-
-  function step0(message) {
-    if (message === 'reload')
-      return page.contentURL = content;
-    assert.equal(message, "3",
-                     "Correct value expected for allowScript - 3");
-    assert.equal(page.contentURL, content,
-                     "Correct content expected");
-    page.removeListener('message', step0);
-    page.on('message', step1);
-    page.allow = { script: false };
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript='f'</script>";
-  }
-
-  function step1(message) {
-    assert.equal(message, "3",
-                     "Correct value expected for allowScript - 3");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step1);
-    page.on('message', step2);
-    page.allow = { script: true };
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript='g'</script>";
-  }
-
-  function step2(message) {
-    assert.equal(message, "g",
-                     "Correct value expected for allowScript - g");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step2);
-    page.on('message', step3);
-    page.allow.script = false;
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=3</script>";
-  }
-
-  function step3(message) {
-    assert.equal(message, "g",
-                     "Correct value expected for allowScript - g");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step3);
-    page.on('message', step4);
-    page.allow.script = true;
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=4</script>";
-  }
-
-  function step4(message) {
-    assert.equal(message, "4",
-                     "Correct value expected for allowScript - 4");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    done();
-  }
-
-}
-
-exports.testOnMessageCallback = function(assert, done) {
-  Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: function() {
-      assert.pass("onMessage callback called");
-      done();
-    }
-  });
-}
-
-exports.testMultipleOnMessageCallbacks = function(assert, done) {
-  let count = 0;
-  let page = Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: () => count += 1
-  });
-  page.on('message', () => count += 2);
-  page.on('message', () => count *= 3);
-  page.on('message', () =>
-    assert.equal(count, 9, "All callbacks were called, in order."));
-  page.on('message', done);
-};
-
-exports.testLoadContentPage = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      // The message is an array whose first item is the test method to call
-      // and the rest of whose items are arguments to pass it.
-      let msg = message.shift();
-      if (msg == "done")
-        return done();
-      assert[msg].apply(assert, message);
-    },
-    contentURL: fixtures.url("test-page-worker.html"),
-    contentScriptFile: fixtures.url("test-page-worker.js"),
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testLoadContentPageRelativePath = function(assert, done) {
-  let page = require("sdk/page-worker").Page({
-    onMessage: function(message) {
-      // The message is an array whose first item is the test method to call
-      // and the rest of whose items are arguments to pass it.
-      let msg = message.shift();
-      if (msg == "done")
-        return done();
-      assert[msg].apply(assert, message);
-    },
-    contentURL: "./test-page-worker.html",
-    contentScriptFile: "./test-page-worker.js",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testAllowScriptDefault = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      assert.ok(message, "Script is allowed to run by default.");
-      done();
-    },
-    contentURL: "data:text/html;charset=utf-8,<script>document.documentElement.setAttribute('foo', 3);</script>",
-    contentScript: "self.postMessage(document.documentElement.getAttribute('foo'))",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testAllowScript = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      assert.ok(message, "Script runs when allowed to do so.");
-      done();
-    },
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.documentElement.setAttribute('foo', 3);</script>",
-    contentScript: "self.postMessage(document.documentElement.hasAttribute('foo') && " +
-                   "                 document.documentElement.getAttribute('foo') == 3)",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testPingPong = function(assert, done) {
-  let page = Page({
-    contentURL: 'data:text/html;charset=utf-8,ping-pong',
-    contentScript: 'self.on("message", function(message) { return self.postMessage("pong"); });'
-      + 'self.postMessage("ready");',
-    onMessage: function(message) {
-      if ('ready' == message) {
-        page.postMessage('ping');
-      }
-      else {
-        assert.ok(message, 'pong', 'Callback from contentScript');
-        done();
-      }
-    }
-  });
-};
-
-exports.testRedirect = function (assert, done) {
-  let page = Page({
-    contentURL: 'data:text/html;charset=utf-8,first-page',
-    contentScriptWhen: "end",
-    contentScript: '' +
-      'if (/first-page/.test(document.location.href)) ' +
-      '  document.location.href = "data:text/html;charset=utf-8,redirect";' +
-      'else ' +
-      '  self.port.emit("redirect", document.location.href);'
-  });
-
-  page.port.on('redirect', function (url) {
-    assert.equal(url, 'data:text/html;charset=utf-8,redirect', 'Reinjects contentScript on reload');
-    done();
-  });
-};
-
-exports.testRedirectIncludeArrays = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '  self.port.on("redirect", function (url) {' +
-      '   document.location.href = url;' +
-      '  })' +
-      '})();',
-    include: ['about:blank', 'data:*']
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.port.emit('redirect', 'about:blank');
-    } else if (url === 'about:blank') {
-      page.port.emit('redirect', 'about:mozilla');
-      assert.ok('`include` property handles arrays');
-      assert.equal(url, 'about:blank', 'Redirects work with accepted domains');
-      done();
-    } else if (url === 'about:mozilla') {
-      assert.fail('Should not redirect to restricted domain');
-    }
-  });
-};
-
-exports.testRedirectFromWorker = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let secondURL = 'data:text/html;charset=utf-8,second-page';
-  let thirdURL = 'data:text/html;charset=utf-8,third-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '  self.port.on("redirect", function (url) {' +
-      '   document.location.href = url;' +
-      '  })' +
-      '})();',
-    include: 'data:*'
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.port.emit('redirect', secondURL);
-    } else if (url === secondURL) {
-      page.port.emit('redirect', thirdURL);
-    } else if (url === thirdURL) {
-      page.port.emit('redirect', 'about:mozilla');
-      assert.equal(url, thirdURL, 'Redirects work with accepted domains on include strings');
-      done();
-    } else {
-      assert.fail('Should not redirect to unauthorized domains');
-    }
-  });
-};
-
-exports.testRedirectWithContentURL = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let secondURL = 'data:text/html;charset=utf-8,second-page';
-  let thirdURL = 'data:text/html;charset=utf-8,third-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '})();',
-    include: 'data:*'
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.contentURL = secondURL;
-    } else if (url === secondURL) {
-      page.contentURL = thirdURL;
-    } else if (url === thirdURL) {
-      page.contentURL = 'about:mozilla';
-      assert.equal(url, thirdURL, 'Redirects work with accepted domains on include strings');
-      done();
-    } else {
-      assert.fail('Should not redirect to unauthorized domains');
-    }
-  });
-};
-
-
-exports.testMultipleDestroys = function(assert) {
-  let page = Page();
-  page.destroy();
-  page.destroy();
-  assert.pass("Multiple destroys should not cause an error");
-};
-
-exports.testContentScriptOptionsOption = function(assert, done) {
-  let page = new Page({
-    contentScript: "self.postMessage( [typeof self.options.d, self.options] );",
-    contentScriptWhen: "end",
-    contentScriptOptions: {a: true, b: [1,2,3], c: "string", d: function(){ return 'test'}},
-    onMessage: function(msg) {
-      assert.equal(msg[0], 'undefined', 'functions are stripped from contentScriptOptions');
-      assert.equal(typeof msg[1], 'object', 'object as contentScriptOptions');
-      assert.equal(msg[1].a, true, 'boolean in contentScriptOptions');
-      assert.equal(msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions');
-      assert.equal(msg[1].c, 'string', 'string in contentScriptOptions');
-      done();
-    }
-  });
-};
-
-exports.testMessageQueue = function (assert, done) {
-  let page = new Page({
-    contentScript: 'self.on("message", function (m) {' +
-      'self.postMessage(m);' +
-      '});',
-    contentURL: 'data:text/html;charset=utf-8,',
-  });
-  page.postMessage('ping');
-  page.on('message', function (m) {
-    assert.equal(m, 'ping', 'postMessage should queue messages');
-    done();
-  });
-};
-
-exports.testWindowStopDontBreak = function (assert, done) {
-  const { Ci, Cc } = require('chrome');
-  const consoleService = Cc['@mozilla.org/consoleservice;1'].
-                            getService(Ci.nsIConsoleService);
-  const listener = {
-    observe: ({message}) => {
-      if (message.includes('contentWorker is null'))
-        assert.fail('contentWorker is null');
-    }
-  };
-  consoleService.registerListener(listener)
-
-  let page = new Page({
-    contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
-    contentScriptWhen: 'ready',
-    contentScript: Isolate(() => {
-      window.stop();
-      self.port.on('ping', () => self.port.emit('pong'));
-    })
-  });
-
-  page.port.on('pong', () => {
-    assert.pass('page-worker works after window.stop');
-    page.destroy();
-    consoleService.unregisterListener(listener);
-    done();
-  });
-
-  page.port.emit("ping");
-};
-
-
-function isDestroyed(page) {
-  try {
-    page.postMessage("foo");
-  }
-  catch (err) {
-    if (err.message == ERR_DESTROYED) {
-      return true;
-    }
-    else {
-      throw err;
-    }
-  }
-  return false;
-}
-
-// require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-content/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "e10s-content",
-  "title": "e10s-content",
-  "id": "jid1-ZZaXFHAPlHDDD@jetpack",
-  "description": "run content worker tests in e10s mode",
-  "author": "Tomislav Jovanovic",
-  "license": "MPL-2.0",
-  "version": "0.1.0",
-  "main": "./lib/main.js",
-  "e10s": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/data/test-localization.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>HTML Localization</title>
-  </head>
-  <body>
-    <div data-l10n-id="Not translated">Kept as-is</div>
-    <ul data-l10n-id="Translated">
-      <li>Inner html content is replaced,</li>
-      <li data-l10n-id="text-content">
-        Elements with data-l10n-id attribute whose parent element is translated
-        will be replaced by the content of the translation.
-      </li>
-    </ul>
-    <div data-l10n-id="text-content">No</div>
-    <div data-l10n-id="Translated">
-      A data-l10n-id value can be used in multiple elements
-    </div>
-    <a data-l10n-id="link-attributes" title="Certain whitelisted attributes get translated too" alt="No" accesskey="A"></a>
-    <input data-l10n-id="input" type="text" placeholder="Form placeholders are translateable">
-    <menu>
-      <menuitem data-l10n-id="contextitem" label="Labels of select options and context menus are translateable">
-    </menu>
-  </body>
-</html
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/locale/en.properties
+++ /dev/null
@@ -1,38 +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/.
-
-Translated= Yes
-
-text-content=no <b>HTML</b> injection
-
-downloadsCount=%d downloads
-downloadsCount[one]=one download
-
-pluralTest=fallback to other
-pluralTest[zero]=optional zero form
-
-explicitPlural[one]=one
-explicitPlural[other]=other
-
-# You can use unicode char escaping in order to inject space at the beginning/
-# end of your string. (Regular spaces are automatically ignore by .properties
-# file parser)
-unicodeEscape = \u0020\u0040\u0020
-# this string equals to " @ "
-
-# bug 1033309 plurals with multiple placeholders
-first_identifier[one]=first entry is %s and the second one is %s.
-first_identifier=the entries are %s and %s.
-second_identifier[other]=first entry is %s and the second one is %s.
-third_identifier=first entry is %s and the second one is %s.
-
-# bug 824489 allow translation of element attributes
-link-attributes.title=Yes
-link-attributes.alt=Yes
-link-attributes.accesskey=B
-input.placeholder=Yes
-contextitem.label=Yes
-link-attributes.ariaLabel=Yes
-link-attributes.ariaValueText=Value
-link-attributes.ariaMozHint=Hint
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/locale/eo.properties
+++ /dev/null
@@ -1,5 +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/.
-
-Translated= jes
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/locale/fr-FR.properties
+++ /dev/null
@@ -1,14 +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/.
-
-Translated= Oui
-
-placeholderString= Placeholder %s
-
-# Plural forms
-%d downloads=%d téléchargements
-%d downloads[one]=%d téléchargement
-
-downloadsCount=%d téléchargements
-downloadsCount[one]=%d téléchargement
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/main.js
+++ /dev/null
@@ -1,289 +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 prefs = require("sdk/preferences/service");
-const { Loader } = require('sdk/test/loader');
-const { resolveURI } = require('toolkit/loader');
-const { rootURI, isNative } = require("@loader/options");
-const { usingJSON } = require('sdk/l10n/json/core');
-
-const PREF_MATCH_OS_LOCALE  = "intl.locale.matchOS";
-const PREF_SELECTED_LOCALE  = "general.useragent.locale";
-
-function setLocale(locale) {
-  prefs.set(PREF_MATCH_OS_LOCALE, false);
-  prefs.set(PREF_SELECTED_LOCALE, locale);
-}
-
-function resetLocale() {
-  prefs.reset(PREF_MATCH_OS_LOCALE);
-  prefs.reset(PREF_SELECTED_LOCALE);
-}
-
-function definePseudo(loader, id, exports) {
-  let uri = resolveURI(id, loader.mapping);
-  loader.modules[uri] = { exports: exports };
-}
-
-function createTest(locale, testFunction) {
-  return function (assert, done) {
-    let loader = Loader(module);
-    // Change the locale before loading new l10n modules in order to load
-    // the right .json file
-    setLocale(locale);
-    // Initialize main l10n module in order to load new locale files
-    loader.require("sdk/l10n/loader").
-      load(rootURI).
-      then(null, function failure(error) {
-        if (!isNative)
-          assert.fail("Unable to load locales: " + error);
-      }).
-      then(function success(data) {
-             definePseudo(loader, '@l10n/data', data ? data : null);
-             // Execute the given test function
-             try {
-               testFunction(assert, loader, function onDone() {
-                 loader.unload();
-                 resetLocale();
-                 done();
-               });
-             }
-             catch(e) {
-              console.exception(e);
-             }
-           },
-           function failure(error) {
-             assert.fail("Unable to load locales: " + error);
-           });
-  };
-}
-
-exports.testExactMatching = createTest("fr-FR", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-                   "Key not translated");
-  assert.equal(_("Translated"), "Oui",
-                   "Simple key translated");
-
-  // Placeholders
-  assert.equal(_("placeholderString", "works"), "Placeholder works",
-                   "Value with placeholder");
-  assert.equal(_("Placeholder %s", "works"), "Placeholder works",
-                   "Key without value but with placeholder");
-  assert.equal(_("Placeholders %2s %1s %s.", "working", "are", "correctly"),
-                   "Placeholders are working correctly.",
-                   "Multiple placeholders");
-
-  // Plurals
-   assert.equal(_("downloadsCount", 0),
-                   "0 téléchargement",
-                   "PluralForm form 'one' for 0 in french");
-  assert.equal(_("downloadsCount", 1),
-                   "1 téléchargement",
-                   "PluralForm form 'one' for 1 in french");
-  assert.equal(_("downloadsCount", 2),
-                   "2 téléchargements",
-                   "PluralForm form 'other' for n > 1 in french");
-
-  done();
-});
-
-exports.testHtmlLocalizationPageWorker = createTest("en-GB", function(assert, loader, done) {
-  // Ensure initing html component that watch document creations
-  // Note that this module is automatically initialized in
-  // cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
-  let loaderHtmlL10n = loader.require("sdk/l10n/html");
-  loaderHtmlL10n.enable();
-
-  let uri = require("sdk/self").data.url("test-localization.html");
-  let worker = loader.require("sdk/page-worker").Page({
-    contentURL: uri,
-    contentScript: "new " + function ContentScriptScope() {
-      let nodes = document.body.querySelectorAll("*[data-l10n-id]");
-      self.postMessage([nodes[0].innerHTML,
-                        nodes[1].innerHTML,
-                        nodes[2].innerHTML,
-                        nodes[3].innerHTML,
-                        nodes[4].title,
-                        nodes[4].getAttribute("alt"),
-                        nodes[4].getAttribute("accesskey"),
-                        nodes[4].getAttribute("aria-label"),
-                        nodes[4].getAttribute("aria-valuetext"),
-                        nodes[4].getAttribute("aria-moz-hint"),
-                        nodes[5].placeholder,
-                        nodes[6].label]);
-    },
-    onMessage: function (data) {
-      assert.equal(
-        data[0],
-        "Kept as-is",
-        "Nodes with unknown id in .properties are kept 'as-is'"
-      );
-      assert.equal(data[1], "Yes", "HTML is translated");
-      assert.equal(
-        data[2],
-        "no &lt;b&gt;HTML&lt;/b&gt; injection",
-        "Content from .properties is text content; HTML can't be injected."
-      );
-      assert.equal(data[3], "Yes", "Multiple elements with same data-l10n-id are accepted.");
-
-      // Attribute translation tests
-      assert.equal(data[4], "Yes", "Title attributes gets translated.");
-      assert.equal(data[5], "Yes", "Alt attributes gets translated.");
-      assert.equal(data[6], "B", "Accesskey gets translated.");
-      
-      assert.equal(data[7], "Yes", "Aria-Label gets translated.");
-      assert.equal(data[8], "Value", "Aria-valuetext gets translated.");
-      assert.equal(data[9], "Hint", "Aria-moz-hint gets translated.");
-      
-      assert.equal(data[10], "Yes", "Form placeholders are translateable.");
-      
-      assert.equal(data[11], "Yes", "Labels of select options and context menus are translateable.");
-
-      done();
-    }
-  });
-});
-
-exports.testHtmlLocalization = createTest("en-GB", function(assert, loader, done) {
-  // Ensure initing html component that watch document creations
-  // Note that this module is automatically initialized in
-  // cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
-  let loaderHtmlL10n = loader.require("sdk/l10n/html");
-  loaderHtmlL10n.enable();
-
-  let uri = require("sdk/self").data.url("test-localization.html");
-  loader.require("sdk/tabs").open({
-    url: uri,
-    onReady: function(tab) {
-      tab.attach({
-        contentURL: uri,
-        contentScript: "new " + function ContentScriptScope() {
-          let nodes = document.body.querySelectorAll("*[data-l10n-id]");
-          self.postMessage([nodes[0].innerHTML,
-                            nodes[1].innerHTML,
-                            nodes[2].innerHTML,
-                            nodes[3].innerHTML,
-                            nodes[4].title,
-                            nodes[4].getAttribute("alt"),
-                            nodes[4].getAttribute("accesskey"),
-                            nodes[4].getAttribute("aria-label"),
-                            nodes[4].getAttribute("aria-valuetext"),
-                            nodes[4].getAttribute("aria-moz-hint"),
-                            nodes[5].placeholder,
-                            nodes[6].label]);
-        },
-        onMessage: function (data) {
-          assert.equal(
-            data[0],
-            "Kept as-is",
-            "Nodes with unknown id in .properties are kept 'as-is'"
-          );
-          assert.equal(data[1], "Yes", "HTML is translated");
-          assert.equal(
-            data[2],
-            "no &lt;b&gt;HTML&lt;/b&gt; injection",
-            "Content from .properties is text content; HTML can't be injected."
-          );
-          assert.equal(data[3], "Yes", "Multiple elements with same data-l10n-id are accepted.");
-
-          // Attribute translation tests
-          assert.equal(data[4], "Yes", "Title attributes gets translated.");
-          assert.equal(data[5], "Yes", "Alt attributes gets translated.");
-          assert.equal(data[6], "B", "Accesskey gets translated.");
-      
-          assert.equal(data[7], "Yes", "Aria-Label gets translated.");
-          assert.equal(data[8], "Value", "Aria-valuetext gets translated.");
-          assert.equal(data[9], "Hint", "Aria-moz-hint gets translated.");
-      
-          assert.equal(data[10], "Yes", "Form placeholders are translateable.");
-      
-          assert.equal(data[11], "Yes", "Labels of select options and context menus are translateable.");
-
-          tab.close(done);
-        }
-      });
-    }
-  });
-});
-
-exports.testEnUsLocaleName = createTest("en-US", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "Yes",
-               "String with translation is correctly translated");
-
-  // Check Unicode char escaping sequences
-  assert.equal(_("unicodeEscape"), " @ ",
-               "Unicode escaped sequances are correctly converted");
-
-  // Check plural forms regular matching
-  assert.equal(_("downloadsCount", 0),
-                   "0 downloads",
-                   "PluralForm form 'other' for 0 in english");
-  assert.equal(_("downloadsCount", 1),
-                   "one download",
-                   "PluralForm form 'one' for 1 in english");
-  assert.equal(_("downloadsCount", 2),
-                   "2 downloads",
-                   "PluralForm form 'other' for n != 1 in english");
-
-  // Check optional plural forms
-  assert.equal(_("pluralTest", 0),
-                   "optional zero form",
-                   "PluralForm form 'zero' can be optionaly specified. (Isn't mandatory in english)");
-  assert.equal(_("pluralTest", 1),
-                   "fallback to other",
-                   "If the specific plural form is missing, we fallback to 'other'");
-
-  // Ensure that we can omit specifying the generic key without [other]
-  // key[one] = ...
-  // key[other] = ...  # Instead of `key = ...`
-  assert.equal(_("explicitPlural", 1),
-                   "one",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-  assert.equal(_("explicitPlural", 10),
-                   "other",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-
-  assert.equal(_("first_identifier", "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier no count");
-  assert.equal(_("first_identifier", 0, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 0");
-  assert.equal(_("first_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "first_identifier with count = 1");
-  assert.equal(_("first_identifier", 2, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 2");
-
-  assert.equal(_("second_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with no count");
-  assert.equal(_("second_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 0");
-  assert.equal(_("second_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 1");
-  assert.equal(_("second_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 2");
-
-  assert.equal(_("third_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with no count");
-  assert.equal(_("third_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 0");
-  assert.equal(_("third_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 2");
-
-  done();
-});
-
-exports.testUsingJSON = function(assert) {
-  assert.equal(usingJSON, !isNative, 'using json');
-}
-
-exports.testShortLocaleName = createTest("eo", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "jes",
-               "String with translation is correctly translated");
-
-  done();
-});
-
-
-// Before running tests, disable HTML service which is automatially enabled
-// in api-utils/addon/runner.js
-require('sdk/l10n/html').disable();
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-l10n/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "e10s-l10n@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-remote/main.js
+++ /dev/null
@@ -1,578 +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 LOCAL_URI = "about:robots";
-const REMOTE_URI = "data:text/html;charset=utf-8,remote";
-
-const { Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const { getTabs, openTab, closeTab, setTabURL, getBrowserForTab, getURI } = require('sdk/tabs/utils');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { cleanUI } = require("sdk/test/utils");
-const { setTimeout } = require("sdk/timers");
-const { promiseEvent, promiseDOMEvent, promiseEventOnItemAndContainer,
-        waitForProcesses, getChildFrameCount, isE10S } = require("./utils");
-const { after } = require('sdk/test/utils');
-const { processID } = require('sdk/system/runtime');
-
-const { set } = require('sdk/preferences/service');
-// The hidden preload browser messes up our frame counts
-set('browser.newtab.preload', false);
-
-function promiseTabFrameAttach(frames) {
-  return new Promise(resolve => {
-    let listener = function(frame, ...args) {
-      if (!frame.isTab)
-        return;
-      frames.off("attach", listener);
-      resolve([frame, ...args]);
-    }
-
-    frames.on("attach", listener);
-  });
-}
-
-// Check that we see a process stop and start
-exports["test process restart"] = function*(assert) {
-  if (!isE10S) {
-    assert.pass("Skipping test in non-e10s mode");
-    return;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-  let tab = tabs[0];
-  let browser = getBrowserForTab(tab);
-
-  let loader = new Loader(module);
-  let { processes, frames } = yield waitForProcesses(loader);
-
-  let remoteProcess = Array.filter(processes, p => p.isRemote)[0];
-  let localProcess = Array.filter(processes, p => !p.isRemote)[0];
-  let remoteFrame = Array.filter(frames, f => f.process == remoteProcess)[0];
-
-  // Switch the remote tab to a local URI which should kill the remote process
-
-  let frameDetach = promiseEventOnItemAndContainer(assert, remoteFrame, frames, 'detach');
-  let frameAttach = promiseTabFrameAttach(frames);
-  let processDetach = promiseEventOnItemAndContainer(assert, remoteProcess, processes, 'detach');
-  let browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, LOCAL_URI);
-  // The load should kill the remote frame
-  yield frameDetach;
-  // And create a new frame in the local process
-  let [newFrame] = yield frameAttach;
-  assert.equal(newFrame.process, localProcess, "New frame should be in the local process");
-  // And kill the process
-  yield processDetach;
-  yield browserLoad;
-
-  frameDetach = promiseEventOnItemAndContainer(assert, newFrame, frames, 'detach');
-  let processAttach = promiseEvent(processes, 'attach');
-  frameAttach = promiseTabFrameAttach(frames);
-  browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, REMOTE_URI);
-  // The load should kill the remote frame
-  yield frameDetach;
-  // And create a new remote process
-  [remoteProcess] = yield processAttach;
-  assert.ok(remoteProcess.isRemote, "Process should be remote");
-  // And create a new frame in the remote process
-  [newFrame] = yield frameAttach;
-  assert.equal(newFrame.process, remoteProcess, "New frame should be in the remote process");
-  yield browserLoad;
-
-  browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, "about:blank");
-  yield browserLoad;
-
-  loader.unload();
-};
-
-// Test that we find the right number of processes and that messaging between
-// them works and none of the streams cross
-exports["test process list"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = loader.require('sdk/remote/parent');
-
-  let processCount = 0;
-  processes.forEvery(processes => processCount++);
-
-  yield waitForProcesses(loader);
-
-  let remoteProcesses = Array.filter(processes, process => process.isRemote);
-  let localProcesses = Array.filter(processes, process => !process.isRemote);
-
-  assert.equal(localProcesses.length, 1, "Should always be one process");
-
-  if (isE10S) {
-    assert.equal(remoteProcesses.length, 1, "Should be one remote process");
-  }
-  else {
-    assert.equal(remoteProcesses.length, 0, "Should be no remote processes");
-  }
-
-  assert.equal(processCount, processes.length, "Should have seen all processes");
-
-  processCount = 0;
-  processes.forEvery(process => processCount++);
-
-  assert.equal(processCount, processes.length, "forEvery should send existing processes to the listener");
-
-  localProcesses[0].port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "local", "Should not have seen a pong from the local process with the wrong key");
-  });
-
-  if (isE10S) {
-    remoteProcesses[0].port.on('sdk/test/pong', (process, key) => {
-      assert.equal(key, "remote", "Should not have seen a pong from the remote process with the wrong key");
-    });
-  }
-
-  let promise = promiseEventOnItemAndContainer(assert, localProcesses[0].port, processes.port, 'sdk/test/pong', localProcesses[0]);
-  localProcesses[0].port.emit('sdk/test/ping', "local");
-
-  let reply = yield promise;
-  assert.equal(reply[0], "local", "Saw the process reply with the right key");
-
-  if (isE10S) {
-    promise = promiseEventOnItemAndContainer(assert, remoteProcesses[0].port, processes.port, 'sdk/test/pong', remoteProcesses[0]);
-    remoteProcesses[0].port.emit('sdk/test/ping', "remote");
-
-    reply = yield promise;
-    assert.equal(reply[0], "remote", "Saw the process reply with the right key");
-
-    assert.notEqual(localProcesses[0], remoteProcesses[0], "Processes should be different");
-  }
-
-  loader.unload();
-};
-
-// Test that the frame lists are kept up to date
-exports["test frame list"] = function*(assert) {
-  function browserFrames(list) {
-    return Array.filter(list, b => b.isTab).length;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-
-  let loader = new Loader(module);
-  let { processes, frames } = yield waitForProcesses(loader);
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab1 = openTab(window, LOCAL_URI);
-  let [frame1] = yield promise;
-  assert.ok(!!frame1, "Should have seen the new frame");
-  assert.ok(!frame1.process.isRemote, "Frame should not be remote");
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  promise = promiseTabFrameAttach(frames);
-  let tab2 = openTab(window, REMOTE_URI);
-  let [frame2] = yield promise;
-  assert.ok(!!frame2, "Should have seen the new frame");
-  if (isE10S)
-    assert.ok(frame2.process.isRemote, "Frame should be remote");
-  else
-    assert.ok(!frame2.process.isRemote, "Frame should not be remote");
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  frames.port.emit('sdk/test/ping')
-  yield new Promise(resolve => {
-    let count = 0;
-    let listener = () => {
-      console.log("Saw pong");
-      count++;
-      if (count == frames.length) {
-        frames.port.off('sdk/test/pong', listener);
-        resolve();
-      }
-    };
-    frames.port.on('sdk/test/pong', listener);
-  });
-
-  let badListener = () => {
-    assert.fail("Should not have seen a response through this frame");
-  }
-  frame1.port.on('sdk/test/pong', badListener);
-  frame2.port.emit('sdk/test/ping', 'b');
-  let [key] = yield promiseEventOnItemAndContainer(assert, frame2.port, frames.port, 'sdk/test/pong', frame2);
-  assert.equal(key, 'b', "Should have seen the right response");
-  frame1.port.off('sdk/test/pong', badListener);
-
-  frame2.port.on('sdk/test/pong', badListener);
-  frame1.port.emit('sdk/test/ping', 'b');
-  [key] = yield promiseEventOnItemAndContainer(assert, frame1.port, frames.port, 'sdk/test/pong', frame1);
-  assert.equal(key, 'b', "Should have seen the right response");
-  frame2.port.off('sdk/test/pong', badListener);
-
-  promise = promiseEventOnItemAndContainer(assert, frame1, frames, 'detach');
-  closeTab(tab1);
-  yield promise;
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  promise = promiseEventOnItemAndContainer(assert, frame2, frames, 'detach');
-  closeTab(tab2);
-  yield promise;
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  loader.unload();
-};
-
-// Test that multiple loaders get their own loaders in the child and messages
-// don't cross. Unload should work
-exports["test new loader"] = function*(assert) {
-  let loader1 = new Loader(module);
-  let { processes: processes1 } = yield waitForProcesses(loader1);
-
-  let loader2 = new Loader(module);
-  let { processes: processes2 } = yield waitForProcesses(loader2);
-
-  let process1 = [...processes1][0];
-  let process2 = [...processes2][0];
-
-  process1.port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "a", "Should have seen the right pong");
-  });
-
-  process2.port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "b", "Should have seen the right pong");
-  });
-
-  process1.port.emit('sdk/test/ping', 'a');
-  yield promiseEvent(process1.port, 'sdk/test/pong');
-
-  process2.port.emit('sdk/test/ping', 'b');
-  yield promiseEvent(process2.port, 'sdk/test/pong');
-
-  loader1.unload();
-
-  process2.port.emit('sdk/test/ping', 'b');
-  yield promiseEvent(process2.port, 'sdk/test/pong');
-
-  loader2.unload();
-};
-
-// Test that unloading the loader unloads the child instances
-exports["test unload"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:,<html/>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  promise = promiseDOMEvent(browser, 'hashchange');
-  frame.port.emit('sdk/test/testunload');
-  loader.unload("shutdown");
-  yield promise;
-
-  let hash = getURI(tab).replace(/.*#/, "");
-  assert.equal(hash, "unloaded:shutdown", "Saw the correct hash change.")
-
-  closeTab(tab);
-}
-
-// Test that unloading the loader causes the child to see frame detach events
-exports["test frame detach on unload"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:,<html/>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  promise = promiseDOMEvent(browser, 'hashchange');
-  frame.port.emit('sdk/test/testdetachonunload');
-  loader.unload("shutdown");
-  yield promise;
-
-  let hash = getURI(tab).replace(/.*#/, "");
-  assert.equal(hash, "unloaded", "Saw the correct hash change.")
-
-  closeTab(tab);
-}
-
-// Test that DOM event listener on the frame object works
-exports["test frame event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframeevent');
-  promise = Promise.all([
-    promiseEvent(frame.port, 'sdk/test/sawreply'),
-    promiseEvent(frame.port, 'sdk/test/eventsent')
-  ]);
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  frame.port.emit('sdk/test/unregisterframeevent');
-  promise = promiseEvent(frame.port, 'sdk/test/eventsent');
-  frame.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader.unload();
-}
-
-// Test that DOM event listener on the frames object works
-exports["test frames event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframesevent');
-  promise = Promise.all([
-    promiseEvent(frame.port, 'sdk/test/sawreply'),
-    promiseEvent(frame.port, 'sdk/test/eventsent')
-  ]);
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  frame.port.emit('sdk/test/unregisterframesevent');
-  promise = promiseEvent(frame.port, 'sdk/test/eventsent');
-  frame.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader.unload();
-}
-
-// Test that unloading unregisters frame DOM events
-exports["test unload removes frame event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let loader2 = new Loader(module);
-  let { frames: frames2 } = yield waitForProcesses(loader2);
-
-  let promise = promiseTabFrameAttach(frames);
-  let promise2 = promiseTabFrameAttach(frames2);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  let [frame2] = yield promise2;
-  assert.ok(!!frame && !!frame2, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframeevent');
-  promise = Promise.all([
-    promiseEvent(frame2.port, 'sdk/test/sawreply'),
-    promiseEvent(frame2.port, 'sdk/test/eventsent')
-  ]);
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  loader.unload();
-
-  promise = promiseEvent(frame2.port, 'sdk/test/eventsent');
-  frame2.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader2.unload();
-}
-
-// Test that unloading unregisters frames DOM events
-exports["test unload removes frames event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let loader2 = new Loader(module);
-  let { frames: frames2 } = yield waitForProcesses(loader2);
-
-  let promise = promiseTabFrameAttach(frames);
-  let promise2 = promiseTabFrameAttach(frames2);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  let [frame2] = yield promise2;
-  assert.ok(!!frame && !!frame2, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframesevent');
-  promise = Promise.all([
-    promiseEvent(frame2.port, 'sdk/test/sawreply'),
-    promiseEvent(frame2.port, 'sdk/test/eventsent')
-  ]);
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  loader.unload();
-
-  promise = promiseEvent(frame2.port, 'sdk/test/eventsent');
-  frame2.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader2.unload();
-}
-
-// Check that the child frame has the right properties
-exports["test frame properties"] = function*(assert) {
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = new Promise(resolve => {
-    let count = frames.length;
-    let listener = (frame, properties) => {
-      assert.equal(properties.isTab, frame.isTab,
-                   "Child frame should have the same isTab property");
-
-      if (--count == 0) {
-        frames.port.off('sdk/test/replyproperties', listener);
-        resolve();
-      }
-    }
-
-    frames.port.on('sdk/test/replyproperties', listener);
-  })
-
-  frames.port.emit('sdk/test/checkproperties');
-  yield promise;
-
-  loader.unload();
-}
-
-// Check that non-remote processes have the same process ID and remote processes
-// have different IDs
-exports["test processID"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  for (let process of processes) {
-    process.port.emit('sdk/test/getprocessid');
-    let [p, ID] = yield promiseEvent(process.port, 'sdk/test/processid');
-    if (process.isRemote) {
-      assert.notEqual(ID, processID, "Remote processes should have a different process ID");
-    }
-    else {
-      assert.equal(ID, processID, "Remote processes should have the same process ID");
-    }
-  }
-
-  loader.unload();
-}
-
-// Check that sdk/remote/parent and sdk/remote/child can only be loaded in the
-// appropriate loaders
-exports["test cannot load in wrong loader"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  try {
-    require('sdk/remote/child');
-    assert.fail("Should not have been able to load sdk/remote/child");
-  }
-  catch (e) {
-    assert.ok(/Cannot load sdk\/remote\/child in a main process loader/.test(e),
-              "Should have seen the right exception.");
-  }
-
-  for (let process of processes) {
-    processes.port.emit('sdk/test/parentload');
-    let [_, isChildLoader, loaded, message] = yield promiseEvent(processes.port, 'sdk/test/parentload');
-    assert.ok(isChildLoader, "Process should see itself in a child loader.");
-    assert.ok(!loaded, "Process couldn't load sdk/remote/parent.");
-    assert.ok(/Cannot load sdk\/remote\/parent in a child loader/.test(message),
-              "Should have seen the right exception.");
-  }
-
-  loader.unload();
-};
-
-exports["test send cpow"] = function*(assert) {
-  if (!isE10S) {
-    assert.pass("Skipping test in non-e10s mode");
-    return;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-  let tab = tabs[0];
-  let browser = getBrowserForTab(tab);
-
-  assert.ok(Cu.isCrossProcessWrapper(browser.contentWindow),
-            "Should have a CPOW for the browser content window");
-
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  processes.port.emitCPOW('sdk/test/cpow', ['foobar'], { window: browser.contentWindow });
-  let [process, arg, id] = yield promiseEvent(processes.port, 'sdk/test/cpow');
-
-  assert.ok(process.isRemote, "Response should come from the remote process");
-  assert.equal(arg, "foobar", "Argument should have passed through");
-  assert.equal(id, browser.outerWindowID, "Should have got the ID from the child");
-};
-
-after(exports, function*(name, assert) {
-  yield cleanUI();
-});
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-remote/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "e10s-remote",
-  "title": "e10s-remote",
-  "id": "remote@jetpack",
-  "description": "Run remote tests",
-  "version": "1.0.0",
-  "main": "main.js",
-  "e10s": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-remote/remote-module.js
+++ /dev/null
@@ -1,129 +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 { when } = require('sdk/system/unload');
-const { process, frames } = require('sdk/remote/child');
-const { loaderID } = require('@loader/options');
-const { processID } = require('sdk/system/runtime');
-const system = require('sdk/system/events');
-const { Cu } = require('chrome');
-const { isChildLoader } = require('sdk/remote/core');
-const { getOuterId } = require('sdk/window/utils');
-
-function log(str) {
-  console.log("remote[" + loaderID + "][" + processID + "]: " + str);
-}
-
-log("module loaded");
-
-process.port.emit('sdk/test/load');
-
-process.port.on('sdk/test/ping', (process, key) => {
-  log("received process ping");
-  process.port.emit('sdk/test/pong', key);
-});
-
-var frameCount = 0;
-frames.forEvery(frame => {
-  frameCount++;
-  frame.on('detach', () => {
-    frameCount--;
-  });
-
-  frame.port.on('sdk/test/ping', (frame, key) => {
-    log("received frame ping");
-    frame.port.emit('sdk/test/pong', key);
-  });
-});
-
-frames.port.on('sdk/test/checkproperties', frame => {
-  frame.port.emit('sdk/test/replyproperties', {
-    isTab: frame.isTab
-  });
-});
-
-process.port.on('sdk/test/count', () => {
-  log("received count ping");
-  process.port.emit('sdk/test/count', frameCount);
-});
-
-process.port.on('sdk/test/getprocessid', () => {
-  process.port.emit('sdk/test/processid', processID);
-});
-
-frames.port.on('sdk/test/testunload', (frame) => {
-  // Cache the content since the frame will have been destroyed by the time
-  // we see the unload event.
-  let content = frame.content;
-  when((reason) => {
-    content.location = "#unloaded:" + reason;
-  });
-});
-
-frames.port.on('sdk/test/testdetachonunload', (frame) => {
-  let content = frame.content;
-  frame.on('detach', () => {
-    console.log("Detach from " + frame.content.location);
-    frame.content.location = "#unloaded";
-  });
-});
-
-frames.port.on('sdk/test/sendevent', (frame) => {
-  let doc = frame.content.document;
-
-  let listener = () => {
-    frame.port.emit('sdk/test/sawreply');
-  }
-
-  system.on("Test:Reply", listener);
-  let event = new frame.content.CustomEvent("Test:Event");
-  doc.dispatchEvent(event);
-  system.off("Test:Reply", listener);
-  frame.port.emit('sdk/test/eventsent');
-});
-
-process.port.on('sdk/test/parentload', () => {
-  let loaded = false;
-  let message = "";
-  try {
-    require('sdk/remote/parent');
-    loaded = true;
-  }
-  catch (e) {
-    message = "" + e;
-  }
-
-  process.port.emit('sdk/test/parentload',
-    isChildLoader,
-    loaded,
-    message
-  )
-});
-
-function listener(event) {
-  // Use the raw observer service here since it will be usable even if the
-  // loader has unloaded
-  let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-  Services.obs.notifyObservers(null, "Test:Reply");
-}
-
-frames.port.on('sdk/test/registerframesevent', (frame) => {
-  frames.addEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/unregisterframesevent', (frame) => {
-  frames.removeEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/registerframeevent', (frame) => {
-  frame.addEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/unregisterframeevent', (frame) => {
-  frame.removeEventListener("Test:Event", listener, true);
-});
-
-process.port.on('sdk/test/cpow', (process, arg, cpows) => {
-  process.port.emit('sdk/test/cpow', arg, getOuterId(cpows.window));
-});
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-remote/utils.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Cu } = require('chrome');
-const { Task: { async } } = Cu.import('resource://gre/modules/Task.jsm', {});
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-
-const REMOTE_MODULE = "./remote-module";
-
-function promiseEvent(emitter, event) {
-  console.log("Waiting for " + event);
-  return new Promise(resolve => {
-    emitter.once(event, (...args) => {
-      console.log("Saw " + event);
-      resolve(args);
-    });
-  });
-}
-exports.promiseEvent = promiseEvent;
-
-function promiseDOMEvent(target, event, isCapturing = false) {
-  console.log("Waiting for " + event);
-  return new Promise(resolve => {
-    let listener = (event) => {
-      target.removeEventListener(event, listener, isCapturing);
-      resolve(event);
-    };
-    target.addEventListener(event, listener, isCapturing);
-  })
-}
-exports.promiseDOMEvent = promiseDOMEvent;
-
-const promiseEventOnItemAndContainer = async(function*(assert, itemport, container, event, item = itemport) {
-  let itemEvent = promiseEvent(itemport, event);
-  let containerEvent = promiseEvent(container, event);
-
-  let itemArgs = yield itemEvent;
-  let containerArgs = yield containerEvent;
-
-  assert.equal(containerArgs[0], item, "Should have seen a container event for the right item");
-  assert.equal(JSON.stringify(itemArgs), JSON.stringify(containerArgs), "Arguments should have matched");
-
-  // Strip off the item from the returned arguments
-  return itemArgs.slice(1);
-});
-exports.promiseEventOnItemAndContainer = promiseEventOnItemAndContainer;
-
-const waitForProcesses = async(function*(loader) {
-  console.log("Starting remote");
-  let { processes, frames, remoteRequire } = loader.require('sdk/remote/parent');
-  remoteRequire(REMOTE_MODULE, module);
-
-  let events = [];
-
-  // In e10s we should expect to see two processes
-  let expectedCount = isE10S ? 2 : 1;
-
-  yield new Promise(resolve => {
-    let count = 0;
-
-    // Wait for a process to be detected
-    let listener = process => {
-      console.log("Saw a process attach");
-      // Wait for the remote module to load in this process
-      process.port.once('sdk/test/load', () => {
-        console.log("Saw a remote module load");
-        count++;
-        if (count == expectedCount) {
-          processes.off('attach', listener);
-          resolve();
-        }
-      });
-    }
-    processes.on('attach', listener);
-  });
-
-  console.log("Remote ready");
-  return { processes, frames, remoteRequire };
-});
-exports.waitForProcesses = waitForProcesses;
-
-// Counts the frames in all the child processes
-const getChildFrameCount = async(function*(processes) {
-  let frameCount = 0;
-
-  for (let process of processes) {
-    process.port.emit('sdk/test/count');
-    let [p, count] = yield promiseEvent(process.port, 'sdk/test/count');
-    frameCount += count;
-  }
-
-  return frameCount;
-});
-exports.getChildFrameCount = getChildFrameCount;
-
-const mainWindow = getMostRecentBrowserWindow();
-const isE10S = mainWindow.gMultiProcessBrowser;
-exports.isE10S = isE10S;
-
-if (isE10S) {
-  console.log("Testing in E10S mode");
-  // We expect a child process to already be present, make sure that is the case
-  mainWindow.XULBrowserWindow.forceInitialBrowserRemote();
-}
-else {
-  console.log("Testing in non-E10S mode");
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/main.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/. */
-'use strict';
-
-const { merge } = require('sdk/util/object');
-const { version } = require('sdk/system');
-
-const SKIPPING_TESTS = {
-  "test skip": (assert) => assert.pass("nothing to test here")
-};
-
-merge(module.exports, require('./test-tab'));
-merge(module.exports, require('./test-tab-events'));
-merge(module.exports, require('./test-tab-observer'));
-merge(module.exports, require('./test-tab-utils'));
-
-// run e10s tests only on builds from trunk, fx-team, Nightly..
-if (!version.endsWith('a1')) {
-  module.exports = SKIPPING_TESTS;
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/private-browsing/helper.js
+++ /dev/null
@@ -1,91 +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 { Loader } = require('sdk/test/loader');
-
-const { loader } = LoaderWithHookedConsole(module);
-
-const pb = loader.require('sdk/private-browsing');
-const pbUtils = loader.require('sdk/private-browsing/utils');
-const xulApp = require("sdk/system/xul-app");
-const { open: openWindow, getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { openTab, getTabContentWindow, getActiveTab, setTabURL, closeTab } = require('sdk/tabs/utils');
-const promise = require("sdk/core/promise");
-const windowHelpers = require('sdk/window/helpers');
-const events = require("sdk/system/events");
-
-function LoaderWithHookedConsole(module) {
-  let globals = {};
-  let errors = [];
-
-  globals.console = Object.create(console, {
-    error: {
-      value: function(e) {
-        errors.push(e);
-        if (!/DEPRECATED:/.test(e)) {
-          console.error(e);
-        }
-      }
-    }
-  });
-
-  let loader = Loader(module, globals);
-
-  return {
-    loader: loader,
-    errors: errors
-  }
-}
-
-exports.pb = pb;
-exports.pbUtils = pbUtils;
-exports.LoaderWithHookedConsole = LoaderWithHookedConsole;
-
-exports.openWebpage = function openWebpage(url, enablePrivate) {
-  if (xulApp.is("Fennec")) {
-    let chromeWindow = getMostRecentBrowserWindow();
-    let rawTab = openTab(chromeWindow, url, {
-      isPrivate: enablePrivate
-    });
-
-    return {
-      ready: promise.resolve(getTabContentWindow(rawTab)),
-      close: function () {
-        closeTab(rawTab);
-        // Returns a resolved promise as there is no need to wait
-        return promise.resolve();
-      }
-    };
-  }
-  else {
-    let win = openWindow(null, {
-      features: {
-        private: enablePrivate
-      }
-    });
-    let deferred = promise.defer();
-
-    // Wait for delayed startup code to be executed, in order to ensure
-    // that the window is really ready
-    events.on("browser-delayed-startup-finished", function onReady({subject}) {
-      if (subject == win) {
-        events.off("browser-delayed-startup-finished", onReady);
-        deferred.resolve(win);
-
-        let rawTab = getActiveTab(win);
-        setTabURL(rawTab, url);
-        deferred.resolve(getTabContentWindow(rawTab));
-      }
-    }, true);
-
-    return {
-      ready: deferred.promise,
-      close: function () {
-        return windowHelpers.close(win);
-      }
-    };
-  }
-  return null;
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-events.js
+++ /dev/null
@@ -1,238 +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 { Loader } = require("sdk/test/loader");
-const utils = require("sdk/tabs/utils");
-const { open, close } = require("sdk/window/helpers");
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-const { events } = require("sdk/tab/events");
-const { on, off } = require("sdk/event/core");
-const { resolve, defer } = require("sdk/core/promise");
-
-var isFennec = require("sdk/system/xul-app").is("Fennec");
-
-function test(options) {
-  return function(assert, done) {
-    let tabEvents = [];
-    let tabs = [];
-    let { promise, resolve: resolveP } = defer();
-    let win = isFennec ? resolve(getMostRecentBrowserWindow()) :
-      open(null, {
-        features: { private: true, toolbar:true, chrome: true }
-      });
-    let window = null;
-
-    // Firefox events are fired sync; Fennec events async
-    // this normalizes the tests
-    function handler (event) {
-      tabEvents.push(event);
-      runIfReady();
-    }
-
-    function runIfReady () {
-      let releventEvents = getRelatedEvents(tabEvents, tabs);
-      if (options.readyWhen(releventEvents))
-        options.end({
-          tabs: tabs,
-          events: releventEvents,
-          assert: assert,
-          done: resolveP
-        });
-    }
-
-    win.then(function(w) {
-      window = w;
-      on(events, "data", handler);
-      options.start({ tabs: tabs, window: window });
-
-      // Execute here for synchronous FF events, as the handlers
-      // were called before tabs were pushed to `tabs`
-      runIfReady(); 
-      return promise;
-    }).then(function() {
-      off(events, "data", handler);
-      return isFennec ? null : close(window);
-    }).then(done, assert.fail);
-  };
-}
-
-// Just making sure that tab events work for already opened tabs not only
-// for new windows.
-exports["test current window"] = test({
-  readyWhen: events => events.length === 3,
-  start: ({ tabs, window }) => {
-    let tab = utils.openTab(window, 'data:text/plain,open');
-    tabs.push(tab);
-    utils.closeTab(tab);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, close] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    assert.equal(close.type, "TabClose");
-    assert.equal(close.target, tab);
-    done();
-  }
-});
-
-exports["test open"] = test({
-  readyWhen: events => events.length === 2,
-  start: ({ tabs, window }) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,open'));
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-    done();
-  }
-});
-
-exports["test open -> close"] = test({
-  readyWhen: events => events.length === 3,
-  start: ({ tabs, window }) => {
-    // First tab is useless we just open it so that closing second tab won't
-    // close window on some platforms.
-    utils.openTab(window, 'data:text/plain,ignore');
-    let tab = utils.openTab(window, 'data:text/plain,open-close');
-    tabs.push(tab);
-    utils.closeTab(tab);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, close] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    assert.equal(close.type, "TabClose");
-    assert.equal(close.target, tab);
-    done();
-  }
-});
-
-exports["test open -> open -> select"] = test({
-  readyWhen: events => events.length === 5,
-  start: ({tabs, window}) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-1'));
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-2'));
-    utils.activateTab(tabs[0], window);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [ tab1, tab2 ] = tabs;
-    let tab1Events = 0;
-    getRelatedEvents(events, tab1).map(event => {
-      tab1Events++;
-      if (tab1Events === 1)
-        assert.equal(event.type, "TabOpen", "first tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "first tab selected");
-      assert.equal(event.target, tab1);
-    });
-    assert.equal(tab1Events, 3, "first tab has 3 events");
-
-    let tab2Opened;
-    getRelatedEvents(events, tab2).map(event => {
-      if (!tab2Opened)
-        assert.equal(event.type, "TabOpen", "second tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "second tab selected");
-      tab2Opened = true;
-      assert.equal(event.target, tab2);
-    });
-    done();
-  }
-});
-
-exports["test open -> pin -> unpin"] = test({
-  readyWhen: events => events.length === (isFennec ? 2 : 5),
-  start: ({ tabs, window }) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,pin-unpin'));
-    utils.pin(tabs[0]);
-    utils.unpin(tabs[0]);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, move, pin, unpin] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    if (isFennec) {
-      assert.pass("Tab pin / unpin is not supported by Fennec");
-    }
-    else {
-      assert.equal(move.type, "TabMove");
-      assert.equal(move.target, tab);
-
-      assert.equal(pin.type, "TabPinned");
-      assert.equal(pin.target, tab);
-
-      assert.equal(unpin.type, "TabUnpinned");
-      assert.equal(unpin.target, tab);
-    }
-    done();
-  }
-});
-
-exports["test open -> open -> move "] = test({
-  readyWhen: events => events.length === (isFennec ? 4 : 5),
-  start: ({tabs, window}) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-1'));
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-2'));
-    utils.move(tabs[0], 2);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [ tab1, tab2 ] = tabs;
-    let tab1Events = 0;
-    getRelatedEvents(events, tab1).map(event => {
-      tab1Events++;
-      if (tab1Events === 1)
-        assert.equal(event.type, "TabOpen", "first tab opened");
-      else if (tab1Events === 2)
-        assert.equal(event.type, "TabSelect", "first tab selected");
-      else if (tab1Events === 3 && isFennec)
-        assert.equal(event.type, "TabMove", "first tab moved");
-      assert.equal(event.target, tab1);
-    });
-    assert.equal(tab1Events, isFennec ? 2 : 3,
-      "correct number of events for first tab");
-
-    let tab2Events = 0;
-    getRelatedEvents(events, tab2).map(event => {
-      tab2Events++;
-      if (tab2Events === 1)
-        assert.equal(event.type, "TabOpen", "second tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "second tab selected");
-      assert.equal(event.target, tab2);
-    });
-    done();
-  }
-});
-
-function getRelatedEvents (events, tabs) {
-  return events.filter(({target}) => ~([].concat(tabs)).indexOf(target));
-}
-
-// require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-observer.js
+++ /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/. */
-
-"use strict";
-
-// TODO Fennec support in Bug #894525
-module.metadata = {
-  "engines": {
-    "Firefox": "*"
-  }
-}
-
-const { openTab, closeTab } = require("sdk/tabs/utils");
-const { Loader } = require("sdk/test/loader");
-const { setTimeout } = require("sdk/timers");
-
-exports["test unload tab observer"] = function(assert, done) {
-  let loader = Loader(module);
-
-  let window = loader.require("sdk/deprecated/window-utils").activeBrowserWindow;
-  let observer = loader.require("sdk/tabs/observer").observer;
-  let opened = 0;
-  let closed = 0;
-
-  observer.on("open", function onOpen(window) { opened++; });
-  observer.on("close", function onClose(window) { closed++; });
-
-  // Open and close tab to trigger observers.
-  closeTab(openTab(window, "data:text/html;charset=utf-8,tab-1"));
-
-  // Unload the module so that all listeners set by observer are removed.
-  loader.unload();
-
-  // Open and close tab once again.
-  closeTab(openTab(window, "data:text/html;charset=utf-8,tab-2"));
-
-  // Enqueuing asserts to make sure that assertion is not performed early.
-  setTimeout(function () {
-    assert.equal(1, opened, "observer open was called before unload only");
-    assert.equal(1, closed, "observer close was called before unload only");
-    done();
-  }, 0);
-};
-
-// require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-utils.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/. */
-'use strict';
-
-const { getTabs } = require('sdk/tabs/utils');
-const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
-const { browserWindows } = require('sdk/windows');
-const tabs = require('sdk/tabs');
-const { isPrivate } = require('sdk/private-browsing');
-const { openTab, closeTab, getTabContentWindow, getOwnerWindow } = require('sdk/tabs/utils');
-const { open, close } = require('sdk/window/helpers');
-const { windows } = require('sdk/window/utils');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { fromIterator } = require('sdk/util/array');
-
-if (isWindowPBSupported) {
-  exports.testGetTabsPWPB = function(assert, done) {
-    let tabCount = getTabs().length;
-    let windowCount = browserWindows.length;
-
-    open(null, {
-        features: {
-        private: true,
-        toolbar: true,
-        chrome: true
-      }
-    }).then(function(window) {
-      assert.ok(isPrivate(window), 'new tab is private');
-
-      assert.equal(getTabs().length, tabCount, 'there are no new tabs found');
-      getTabs().forEach(function(tab) {
-        assert.equal(isPrivate(tab), false, 'all found tabs are not private');
-        assert.equal(isPrivate(getOwnerWindow(tab)), false, 'all found tabs are not private');
-        assert.equal(isPrivate(getTabContentWindow(tab)), false, 'all found tabs are not private');
-      });
-
-      assert.equal(browserWindows.length, windowCount, 'there are no new windows found');
-      fromIterator(browserWindows).forEach(function(window) {
-        assert.equal(isPrivate(window), false, 'all found windows are not private');
-      });
-
-      assert.equal(windows(null, {includePrivate: true}).length, 2, 'there are really two windows');
-
-      close(window).then(done);
-    });
-  };
-}
-else if (isTabPBSupported) {
-  exports.testGetTabsPTPB = function(assert, done) {
-    let startTabCount = getTabs().length;
-    let tab = openTab(getMostRecentBrowserWindow(), 'about:blank', {
-      isPrivate: true
-    });
-
-    assert.ok(isPrivate(getTabContentWindow(tab)), 'new tab is private');
-    let utils_tabs = getTabs();
-    assert.equal(utils_tabs.length, startTabCount + 1,
-                 'there are two tabs found');
-    assert.equal(utils_tabs[utils_tabs.length-1], tab,
-                 'the last tab is the opened tab');
-    assert.equal(browserWindows.length, 1, 'there is only one window');
-    closeTab(tab);
-
-    done();
-  };
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab.js
+++ /dev/null
@@ -1,87 +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 tabs = require("sdk/tabs"); // From addon-kit
-const windowUtils = require("sdk/deprecated/window-utils");
-const app = require("sdk/system/xul-app");
-const { viewFor } = require("sdk/view/core");
-const { modelFor } = require("sdk/model/core");
-const { getTabId, isTab } = require("sdk/tabs/utils");
-const { defer } = require("sdk/lang/functional");
-
-exports["test behavior on close"] = function(assert, done) {
-  tabs.open({
-    url: "about:mozilla",
-    onReady: function(tab) {
-      assert.equal(tab.url, "about:mozilla", "Tab has the expected url");
-      // if another test ends before closing a tab then index != 1 here
-      assert.ok(tab.index >= 1, "Tab has the expected index, a value greater than 0");
-      tab.close(function () {
-        assert.equal(tab.url, undefined,
-                     "After being closed, tab attributes are undefined (url)");
-        assert.equal(tab.index, undefined,
-                     "After being closed, tab attributes are undefined (index)");
-        if (app.is("Firefox")) {
-          // Ensure that we can call destroy multiple times without throwing;
-          // Fennec doesn't use this internal utility
-          tab.destroy();
-          tab.destroy();
-        }
-
-        done();
-      });
-    }
-  });
-};
-
-exports["test viewFor(tab)"] = (assert, done) => {
-  // Note we defer handlers as length collection is updated after
-  // handler is invoked, so if test is finished before counnts are
-  // updated wrong length will show up in followup tests.
-  tabs.once("open", defer(tab => {
-    const view = viewFor(tab);
-    assert.ok(view, "view is returned");
-    assert.equal(getTabId(view), tab.id, "tab has a same id");
-
-    tab.close(defer(done));
-  }));
-
-  tabs.open({ url: "about:mozilla" });
-};
-
-exports["test modelFor(xulTab)"] = (assert, done) => {
-  tabs.open({
-    url: "about:mozilla",
-    onReady: tab => {
-      const view = viewFor(tab);
-      assert.ok(view, "view is returned");
-      assert.ok(isTab(view), "view is underlaying tab");
-      assert.equal(getTabId(view), tab.id, "tab has a same id");
-      assert.equal(modelFor(view), tab, "modelFor(view) is SDK tab");
-
-      tab.close(defer(done));
-    }
-  });
-};
-
-exports["test tab.readyState"] = (assert, done) => {
-  tabs.open({
-    url: "data:text/html;charset=utf-8,test_readyState",
-    onOpen: (tab) => {
-      assert.notEqual(["uninitialized", "loading"].indexOf(tab.readyState), -1,
-        "tab is either uninitialized or loading when onOpen");
-    },
-    onReady: (tab) => {
-      assert.notEqual(["interactive", "complete"].indexOf(tab.readyState), -1,
-        "tab is either interactive or complete when onReady");
-    },
-    onLoad: (tab) => {
-      assert.equal(tab.readyState, "complete", "tab is complete onLoad");
-      tab.close(defer(done));
-    }
-  });
-}
-
-// require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s-tabs/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "e10s-tabs",
-  "title": "e10s-tabs",
-  "id": "jid1-ZZaXFHAPlHwbgw@jetpack",
-  "description": "run tab tests in e10s mode",
-  "author": "Tomislav Jovanovic",
-  "license": "MPL-2.0",
-  "version": "0.1.0",
-  "main": "./lib/main.js",
-  "e10s": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s/lib/main.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { getMostRecentBrowserWindow, isBrowser } = require('sdk/window/utils');
-const { promise: windowPromise, close, focus } = require('sdk/window/helpers');
-const { openTab, closeTab, getBrowserForTab } = require('sdk/tabs/utils');
-const { WindowTracker } = require('sdk/deprecated/window-utils');
-const { version, platform } = require('sdk/system');
-const { when } = require('sdk/system/unload');
-const tabs = require('sdk/tabs');
-
-const SKIPPING_TESTS = {
-  "test skip": (assert) => assert.pass("nothing to test here")
-};
-
-exports.testTabIsRemote = function(assert, done) {
-  const url = 'data:text/html,test-tab-is-remote';
-  let tab = openTab(getMostRecentBrowserWindow(), url);
-  assert.ok(tab.linkedBrowser.isRemoteBrowser, "The new tab should be remote");
-
-  // can't simply close a remote tab before it is loaded, bug 1006043
-  let mm = getBrowserForTab(tab).messageManager;
-  mm.addMessageListener('7', function listener() {
-    mm.removeMessageListener('7', listener);
-    tabs.once('close', done);
-    closeTab(tab);
-  })
-  mm.loadFrameScript('data:,sendAsyncMessage("7")', true);
-}
-
-// run e10s tests only on builds from trunk, fx-team, Nightly..
-if (!version.endsWith('a1')) {
-  module.exports = {};
-}
-
-function replaceWindow(remote) {
-  let next = null;
-  let old = getMostRecentBrowserWindow();
-  let promise = new Promise(resolve => {
-    let tracker = WindowTracker({
-      onTrack: window => {
-        if (window !== next)
-          return;
-        resolve(window);
-        tracker.unload();
-      }
-    });
-  })
-  next = old.OpenBrowserWindow({ remote });
-  return promise.then(focus).then(_ => close(old));
-}
-
-// bug 1054482 - e10s test addons time out on linux
-if (platform === 'linux') {
-  module.exports = SKIPPING_TESTS;
-  require('sdk/test/runner').runTestsFromModule(module);
-}
-else {
-  replaceWindow(true).then(_ =>
-    require('sdk/test/runner').runTestsFromModule(module));
-
-  when(_ => replaceWindow(false));
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/e10s/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "name": "e10s",
-  "title": "e10s",
-  "id": "jid1-DYaXFHAPlHwbgw@jetpack",
-  "description": "a basic e10s test add-on",
-  "author": "Tomislav Jovanovic",
-  "license": "MPL-2.0",
-  "version": "0.1.0",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/embedded-webextension/main.js
+++ /dev/null
@@ -1,159 +0,0 @@
-const tabs = require("sdk/tabs");
-const webExtension = require('sdk/webextension');
-
-exports.testEmbeddedWebExtensionModuleInitializedException = function (assert) {
-  let actualErr;
-
-  assert.throws(
-    () => webExtension.initFromBootstrapAddonParam({webExtension: null}),
-    /'sdk\/webextension' module has been already initialized/,
-    "Got the expected exception if the module is initialized twice"
-  );
-};
-
-exports.testEmbeddedWebExtensionBackgroungPage = function* (assert) {
-  try {
-    const api = yield webExtension.startup();
-    assert.ok(api, `webextension waitForStartup promise successfully resolved`);
-
-    const apiSecondStartup = yield webExtension.startup();
-    assert.equal(api, apiSecondStartup, "Got the same API object from the second startup call");
-
-    const {browser} = api;
-
-    let messageListener;
-    let waitForBackgroundPageMessage = new Promise((resolve, reject) => {
-      let numExpectedMessage = 2;
-      messageListener = (msg, sender, sendReply) => {
-        numExpectedMessage -= 1;
-        if (numExpectedMessage == 1) {
-          assert.equal(msg, "bg->sdk message",
-                       "Got the expected message from the background page");
-          sendReply("sdk reply");
-        } else if (numExpectedMessage == 0) {
-          assert.equal(msg, "sdk reply",
-                       "The background page received the expected reply message");
-          resolve();
-        } else {
-          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
-          assert.ok(false, `unexpected message received`);
-          reject();
-        }
-      };
-      browser.runtime.onMessage.addListener(messageListener);
-    });
-
-    let portListener;
-    let waitForBackgroundPagePort = new Promise((resolve, reject) => {
-      portListener = (port) => {
-        let numExpectedMessages = 2;
-        port.onMessage.addListener((msg) => {
-          numExpectedMessages -= 1;
-
-          if (numExpectedMessages == 1) {
-            // Check that the legacy context has been able to receive the first port message
-            // and reply with a port message to the background page.
-            assert.equal(msg, "bg->sdk port message",
-                         "Got the expected port message from the background page");
-            port.postMessage("sdk->bg port message");
-          } else if (numExpectedMessages == 0) {
-            // Check that the background page has received the above port message.
-            assert.equal(msg, "bg received sdk->bg port message",
-                         "The background page received the expected port message");
-          }
-        });
-
-        port.onDisconnect.addListener(() => {
-          assert.equal(numExpectedMessages, 0, "Got the expected number of port messages");
-          resolve();
-        });
-      };
-      browser.runtime.onConnect.addListener(portListener);
-    });
-
-    yield Promise.all([
-      waitForBackgroundPageMessage,
-      waitForBackgroundPagePort,
-    ]).then(() => {
-      browser.runtime.onMessage.removeListener(messageListener);
-      browser.runtime.onConnect.removeListener(portListener);
-    });
-
-  } catch (err) {
-    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
-  }
-};
-
-exports.testEmbeddedWebExtensionContentScript = function* (assert, done) {
-  try {
-    const {browser} = yield webExtension.startup();
-    assert.ok(browser, `webextension startup promise resolved successfully to the API object`);
-
-    let messageListener;
-    let waitForContentScriptMessage = new Promise((resolve, reject) => {
-      let numExpectedMessage = 2;
-      messageListener = (msg, sender, sendReply) => {
-        numExpectedMessage -= 1;
-        if (numExpectedMessage == 1) {
-          assert.equal(msg, "content script->sdk message",
-                       "Got the expected message from the content script");
-          sendReply("sdk reply");
-        } else if (numExpectedMessage == 0) {
-          assert.equal(msg, "sdk reply",
-                       "The content script received the expected reply message");
-          resolve();
-        } else {
-          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
-          assert.ok(false, `unexpected message received`);
-          reject();
-        }
-      };
-      browser.runtime.onMessage.addListener(messageListener);
-    });
-
-    let portListener;
-    let waitForContentScriptPort = new Promise((resolve, reject) => {
-      portListener = (port) => {
-        let numExpectedMessages = 2;
-        port.onMessage.addListener((msg) => {
-          numExpectedMessages -= 1;
-
-          if (numExpectedMessages == 1) {
-            assert.equal(msg, "content script->sdk port message",
-                         "Got the expected message from the content script port");
-            port.postMessage("sdk->content script port message");
-          } else if (numExpectedMessages == 0) {
-            assert.equal(msg, "content script received sdk->content script port message",
-                         "The content script received the expected port message");
-          }
-        });
-        port.onDisconnect.addListener(() => {
-          assert.equal(numExpectedMessages, 0, "Got the epected number of port messages");
-          resolve();
-        });
-      };
-      browser.runtime.onConnect.addListener(portListener);
-    });
-
-    let url = "http://example.org/";
-
-    var openedTab;
-    tabs.once('open', function onOpen(tab) {
-      openedTab = tab;
-    });
-    tabs.open(url);
-
-    yield Promise.all([
-      waitForContentScriptMessage,
-      waitForContentScriptPort,
-    ]).then(() => {
-      browser.runtime.onMessage.removeListener(messageListener);
-      browser.runtime.onConnect.removeListener(portListener);
-      openedTab.close();
-    });
-  } catch (err) {
-    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
-  }
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/embedded-webextension/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "embedded-webextension@jetpack",
-  "version": "0.1.0",
-  "main": "./main.js",
-  "hasEmbeddedWebExtension": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/embedded-webextension/webextension/background-page.js
+++ /dev/null
@@ -1,10 +0,0 @@
-browser.runtime.sendMessage("bg->sdk message", (reply) => {
-  browser.runtime.sendMessage(reply);
-});
-
-let port = browser.runtime.connect();
-port.onMessage.addListener((msg) => {
-  port.postMessage(`bg received ${msg}`);
-  port.disconnect();
-});
-port.postMessage("bg->sdk port message");
deleted file mode 100644
--- a/addon-sdk/source/test/addons/embedded-webextension/webextension/content-script.js
+++ /dev/null
@@ -1,10 +0,0 @@
-browser.runtime.sendMessage("content script->sdk message", (reply) => {
-  browser.runtime.sendMessage(reply);
-});
-
-let port = browser.runtime.connect();
-port.onMessage.addListener((msg) => {
-  port.postMessage(`content script received ${msg}`);
-  port.disconnect();
-});
-port.postMessage("content script->sdk port message");
deleted file mode 100644
--- a/addon-sdk/source/test/addons/embedded-webextension/webextension/manifest.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "name": "Test SDK Embedded WebExtension",
-  "description": "",
-  "version": "0.1.0",
-  "applications": {
-    "gecko": {
-      "id": "embedded-webextension@jetpack"
-    }
-  },
-  "manifest_version": 2,
-  "permissions": ["tabs"],
-  "background": {
-    "scripts": ["background-page.js"]
-  },
-  "content_scripts": [
-    {"matches": ["<all_urls>"], "js": ["content-script.js"]}
-  ]
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/jetpack-addon.ini
+++ /dev/null
@@ -1,48 +0,0 @@
-[addon-manager.xpi]
-[author-email.xpi]
-[child_process.xpi]
-skip-if = true
-[chrome.xpi]
-[content-permissions.xpi]
-[content-script-messages-latency.xpi]
-[contributors.xpi]
-[curly-id.xpi]
-[developers.xpi]
-[e10s.xpi]
-skip-if = true
-[e10s-content.xpi]
-skip-if = true
-[e10s-l10n.xpi]
-skip-if = true
-[e10s-remote.xpi]
-skip-if = true
-[e10s-tabs.xpi]
-skip-if = true
-[embedded-webextension.xpi]
-[l10n.xpi]
-[l10n-properties.xpi]
-[layout-change.xpi]
-[main.xpi]
-[name-in-numbers.xpi]
-[name-in-numbers-plus.xpi]
-[packaging.xpi]
-[packed.xpi]
-[page-mod-debugger-post.xpi]
-[page-mod-debugger-pre.xpi]
-[page-worker.xpi]
-[places.xpi]
-[predefined-id-with-at.xpi]
-[preferences-branch.xpi]
-[private-browsing-supported.xpi]
-skip-if = true
-[remote.xpi]
-[require.xpi]
-[self.xpi]
-[simple-prefs.xpi]
-[simple-prefs-l10n.xpi]
-[simple-prefs-regression.xpi]
-[standard-id.xpi]
-[tab-close-on-startup.xpi]
-[toolkit-require-reload.xpi]
-[translators.xpi]
-[unsafe-content-script.xpi]
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/application.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[App]
-Vendor=Varma
-Name=Test App
-Version=1.0
-BuildID=20060101
-Copyright=Copyright (c) 2009 Atul Varma
-ID=xulapp@toolness.com
-
-[Gecko]
-MinVersion=1.9.2.0
-MaxVersion=2.0.*
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/bootstrap.js
+++ /dev/null
@@ -1,339 +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/. */
-
-// @see http://dxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp
-
-'use strict';
-
-// IMPORTANT: Avoid adding any initialization tasks here, if you need to do
-// something before add-on is loaded consider addon/runner module instead!
-
-const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
-        results: Cr, manager: Cm } = Components;
-const ioService = Cc['@mozilla.org/network/io-service;1'].
-                  getService(Ci.nsIIOService);
-const resourceHandler = ioService.getProtocolHandler('resource').
-                        QueryInterface(Ci.nsIResProtocolHandler);
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const prefService = Cc['@mozilla.org/preferences-service;1'].
-                    getService(Ci.nsIPrefService).
-                    QueryInterface(Ci.nsIPrefBranch);
-const appInfo = Cc["@mozilla.org/xre/app-info;1"].
-                getService(Ci.nsIXULAppInfo);
-const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
-           getService(Ci.nsIVersionComparator);
-
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm");
-
-const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
-                 'install', 'uninstall', 'upgrade', 'downgrade' ];
-
-const bind = Function.call.bind(Function.bind);
-
-var loader = null;
-var unload = null;
-var cuddlefishSandbox = null;
-var nukeTimer = null;
-
-// Utility function that synchronously reads local resource from the given
-// `uri` and returns content string.
-function readURI(uri) {
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, "UTF-8"),
-    loadUsingSystemPrincipal: true
-  });
-  let stream = channel.open2();
-
-  let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
-    createInstance(Ci.nsIConverterInputStream);
-  cstream.init(stream, 'UTF-8', 0, 0);
-
-  let str = {};
-  let data = '';
-  let read = 0;
-  do {
-    read = cstream.readString(0xffffffff, str);
-    data += str.value;
-  } while (read != 0);
-
-  cstream.close();
-
-  return data;
-}
-
-// We don't do anything on install & uninstall yet, but in a future
-// we should allow add-ons to cleanup after uninstall.
-function install(data, reason) {}
-function uninstall(data, reason) {}
-
-function startup(data, reasonCode) {
-  try {
-    let reason = REASON[reasonCode];
-    // URI for the root of the XPI file.
-    // 'jar:' URI if the addon is packed, 'file:' URI otherwise.
-    // (Used by l10n module in order to fetch `locale` folder)
-    let rootURI = data.resourceURI.spec;
-
-    // TODO: Maybe we should perform read harness-options.json asynchronously,
-    // since we can't do anything until 'sessionstore-windows-restored' anyway.
-    let options = JSON.parse(readURI(rootURI + './harness-options.json'));
-
-    let id = options.jetpackID;
-    let name = options.name;
-
-    // Clean the metadata
-    options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {};
-
-    // freeze the permissionss
-    Object.freeze(options.metadata[name]['permissions']);
-    // freeze the metadata
-    Object.freeze(options.metadata[name]);
-
-    // Register a new resource 'domain' for this addon which is mapping to
-    // XPI's `resources` folder.
-    // Generate the domain name by using jetpack ID, which is the extension ID
-    // by stripping common characters that doesn't work as a domain name:
-    let uuidRe =
-      /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
-
-    let domain = id.
-      toLowerCase().
-      replace(/@/g, '-at-').
-      replace(/\./g, '-dot-').
-      replace(uuidRe, '$1');
-
-    let prefixURI = 'resource://' + domain + '/';
-    let resourcesURI = ioService.newURI(rootURI + '/resources/');
-    resourceHandler.setSubstitution(domain, resourcesURI);
-
-    // Create path to URLs mapping supported by loader.
-    let paths = {
-      // Relative modules resolve to add-on package lib
-      './': prefixURI + name + '/lib/',
-      './tests/': prefixURI + name + '/tests/',
-      '': 'resource://gre/modules/commonjs/'
-    };
-
-    // Maps addon lib and tests ressource folders for each package
-    paths = Object.keys(options.metadata).reduce(function(result, name) {
-      result[name + '/'] = prefixURI + name + '/lib/'
-      result[name + '/tests/'] = prefixURI + name + '/tests/'
-      return result;
-    }, paths);
-
-    // We need to map tests folder when we run sdk tests whose package name
-    // is stripped
-    if (name == 'addon-sdk')
-      paths['tests/'] = prefixURI + name + '/tests/';
-
-    let useBundledSDK = options['force-use-bundled-sdk'];
-    if (!useBundledSDK) {
-      try {
-        useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK");
-      }
-      catch (e) {
-        // Pref doesn't exist, allow using Firefox shipped SDK
-      }
-    }
-
-    // Starting with Firefox 21.0a1, we start using modules shipped into firefox
-    // Still allow using modules from the xpi if the manifest tell us to do so.
-    // And only try to look for sdk modules in xpi if the xpi actually ship them
-    if (options['is-sdk-bundled'] &&
-        (vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) {
-      // Maps sdk module folders to their resource folder
-      paths[''] = prefixURI + 'addon-sdk/lib/';
-      // test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
-      // so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
-      // until we no longer support SDK modules in XPI:
-      paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
-    }
-
-    // Retrieve list of module folder overloads based on preferences in order to
-    // eventually used a local modules instead of files shipped into Firefox.
-    let branch = prefService.getBranch('extensions.modules.' + id + '.path');
-    paths = branch.getChildList('', {}).reduce(function (result, name) {
-      // Allows overloading of any sub folder by replacing . by / in pref name
-      let path = name.substr(1).split('.').join('/');
-      // Only accept overloading folder by ensuring always ending with `/`
-      if (path) path += '/';
-      let fileURI = branch.getCharPref(name);
-
-      // On mobile, file URI has to end with a `/` otherwise, setSubstitution
-      // takes the parent folder instead.
-      if (fileURI[fileURI.length-1] !== '/')
-        fileURI += '/';
-
-      // Maps the given file:// URI to a resource:// in order to avoid various
-      // failure that happens with file:// URI and be close to production env
-      let resourcesURI = ioService.newURI(fileURI);
-      let resName = 'extensions.modules.' + domain + '.commonjs.path' + name;
-      resourceHandler.setSubstitution(resName, resourcesURI);
-
-      result[path] = 'resource://' + resName + '/';
-      return result;
-    }, paths);
-
-    // Make version 2 of the manifest
-    let manifest = options.manifest;
-
-    // Import `cuddlefish.js` module using a Sandbox and bootstrap loader.
-    let cuddlefishPath = 'loader/cuddlefish.js';
-    let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath;
-    if (paths['sdk/']) { // sdk folder has been overloaded
-                         // (from pref, or cuddlefish is still in the xpi)
-      cuddlefishURI = paths['sdk/'] + cuddlefishPath;
-    }
-    else if (paths['']) { // root modules folder has been overloaded
-      cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath;
-    }
-
-    cuddlefishSandbox = loadSandbox(cuddlefishURI);
-    let cuddlefish = cuddlefishSandbox.exports;
-
-    // Normalize `options.mainPath` so that it looks like one that will come
-    // in a new version of linker.
-    let main = options.mainPath;
-
-    unload = cuddlefish.unload;
-    loader = cuddlefish.Loader({
-      paths: paths,
-      // modules manifest.
-      manifest: manifest,
-
-      // Add-on ID used by different APIs as a unique identifier.
-      id: id,
-      // Add-on name.
-      name: name,
-      // Add-on version.
-      version: options.metadata[name].version,
-      // Add-on package descriptor.
-      metadata: options.metadata[name],
-      // Add-on load reason.
-      loadReason: reason,
-
-      prefixURI: prefixURI,
-      // Add-on URI.
-      rootURI: rootURI,
-      // options used by system module.
-      // File to write 'OK' or 'FAIL' (exit code emulation).
-      resultFile: options.resultFile,
-      // Arguments passed as --static-args
-      staticArgs: options.staticArgs,
-
-      // Arguments related to test runner.
-      modules: {
-        '@test/options': {
-          allTestModules: options.allTestModules,
-          iterations: options.iterations,
-          filter: options.filter,
-          profileMemory: options.profileMemory,
-          stopOnError: options.stopOnError,
-          verbose: options.verbose,
-          parseable: options.parseable,
-          checkMemory: options.check_memory,
-        }
-      }
-    });
-
-    let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI);
-    let require = cuddlefish.Require(loader, module);
-
-    require('sdk/addon/runner').startup(reason, {
-      loader: loader,
-      main: main,
-      prefsURI: rootURI + 'defaults/preferences/prefs.js'
-    });
-  } catch (error) {
-    dump('Bootstrap error: ' +
-         (error.message ? error.message : String(error)) + '\n' +
-         (error.stack || error.fileName + ': ' + error.lineNumber) + '\n');
-    throw error;
-  }
-};
-
-function loadSandbox(uri) {
-  let proto = {
-    sandboxPrototype: {
-      loadSandbox: loadSandbox,
-      ChromeWorker: ChromeWorker
-    }
-  };
-  let sandbox = Cu.Sandbox(systemPrincipal, proto);
-  // Create a fake commonjs environnement just to enable loading loader.js
-  // correctly
-  sandbox.exports = {};
-  sandbox.module = { uri: uri, exports: sandbox.exports };
-  sandbox.require = function (id) {
-    if (id !== "chrome")
-      throw new Error("Bootstrap sandbox `require` method isn't implemented.");
-
-    return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
-      CC: bind(CC, Components), components: Components,
-      ChromeWorker: ChromeWorker });
-  };
-  scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
-  return sandbox;
-}
-
-function unloadSandbox(sandbox) {
-  if (Cu.getClassName(sandbox, true) == "Sandbox")
-    Cu.nukeSandbox(sandbox);
-}
-
-function setTimeout(callback, delay) {
-  let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-  timer.initWithCallback({ notify: callback }, delay,
-                         Ci.nsITimer.TYPE_ONE_SHOT);
-  return timer;
-}
-
-function shutdown(data, reasonCode) {
-  let reason = REASON[reasonCode];
-  if (loader) {
-    unload(loader, reason);
-    unload = null;
-
-    // Don't waste time cleaning up if the application is shutting down
-    if (reason != "shutdown") {
-      // Avoid leaking all modules when something goes wrong with one particular
-      // module. Do not clean it up immediatly in order to allow executing some
-      // actions on addon disabling.
-      // We need to keep a reference to the timer, otherwise it is collected
-      // and won't ever fire.
-      nukeTimer = setTimeout(nukeModules, 1000);
-    }
-  }
-};
-
-function nukeModules() {
-  nukeTimer = null;
-  // module objects store `exports` which comes from sandboxes
-  // We should avoid keeping link to these object to avoid leaking sandboxes
-  for (let key in loader.modules) {
-    delete loader.modules[key];
-  }
-  // Direct links to sandboxes should be removed too
-  for (let key in loader.sandboxes) {
-    let sandbox = loader.sandboxes[key];
-    delete loader.sandboxes[key];
-    // Bug 775067: From FF17 we can kill all CCW from a given sandbox
-    unloadSandbox(sandbox);
-  }
-  loader = null;
-
-  // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
-  // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when
-  // the addon is unload.
-
-  unloadSandbox(cuddlefishSandbox.loaderSandbox);
-  unloadSandbox(cuddlefishSandbox.xulappSandbox);
-
-  // Bug 764840: We need to unload cuddlefish otherwise it will stay alive
-  // and keep a reference to this compartment.
-  unloadSandbox(cuddlefishSandbox);
-  cuddlefishSandbox = null;
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/install.rdf
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.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/. -->
-
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>xulapp@toolness.com</em:id>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-    <em:unpack>false</em:unpack>
-
-    <!-- Firefox -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>21.0</em:minVersion>
-        <em:maxVersion>25.0a1</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Test App</em:name>
-    <em:description>Harness for tests.</em:description>
-    <em:creator>Mozilla Corporation</em:creator>
-    <em:homepageURL></em:homepageURL>
-    <em:optionsType></em:optionsType>
-    <em:updateURL></em:updateURL>
-  </Description>
-</RDF>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/locale/en-GB.properties
+++ /dev/null
@@ -1,28 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-Translated= Yes
-
-text-content=no <b>HTML</b> injection
-
-downloadsCount=%d downloads
-downloadsCount[one]=one download
-
-pluralTest=fallback to other
-pluralTest[zero]=optional zero form
-
-explicitPlural[one]=one
-explicitPlural[other]=other
-
-# You can use unicode char escaping in order to inject space at the beginning/
-# end of your string. (Regular spaces are automatically ignore by .properties
-# file parser)
-unicodeEscape = \u0020\u0040\u0020
-# this string equals to " @ "
-
-# bug 1033309 plurals with multiple placeholders
-first_identifier[one]=first entry is %s and the second one is %s.
-first_identifier=the entries are %s and %s.
-second_identifier[other]=first entry is %s and the second one is %s.
-third_identifier=first entry is %s and the second one is %s.
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/locale/en-US.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-Translated= Yes
-
-text-content=no <b>HTML</b> injection
-
-downloadsCount=%d downloads
-downloadsCount[one]=one download
-
-pluralTest=fallback to other
-pluralTest[zero]=optional zero form
-
-explicitPlural[one]=one
-explicitPlural[other]=other
-
-# You can use unicode char escaping in order to inject space at the beginning/
-# end of your string. (Regular spaces are automatically ignore by .properties
-# file parser)
-unicodeEscape = \u0020\u0040\u0020
-# this string equals to " @ "
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/locale/eo.properties
+++ /dev/null
@@ -1,5 +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/.
-
-Translated= jes
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/app-extension/locale/fr-FR.properties
+++ /dev/null
@@ -1,14 +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/.
-
-Translated= Oui
-
-placeholderString= Placeholder %s
-
-# Plural forms
-%d downloads=%d téléchargements
-%d downloads[one]=%d téléchargement
-
-downloadsCount=%d téléchargements
-downloadsCount[one]=%d téléchargement
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/data/test-localization.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>HTML Localization</title>
-  </head>
-  <body>
-    <div data-l10n-id="Not translated">Kept as-is</div>
-    <ul data-l10n-id="Translated">
-      <li>Inner html content is replaced,</li>
-      <li data-l10n-id="text-content">
-        Elements with data-l10n-id attribute whose parent element is translated
-        will be replaced by the content of the translation.
-      </li>
-    </ul>
-    <div data-l10n-id="text-content">No</div>
-    <div data-l10n-id="Translated">
-      A data-l10n-id value can be used in multiple elements
-    </div>
-  </body>
-</html
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/main.js
+++ /dev/null
@@ -1,202 +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 prefs = require("sdk/preferences/service");
-const { Loader } = require('sdk/test/loader');
-const { resolveURI } = require('toolkit/loader');
-const { rootURI } = require("@loader/options");
-const { usingJSON } = require('sdk/l10n/json/core');
-
-const PREF_MATCH_OS_LOCALE  = "intl.locale.matchOS";
-const PREF_SELECTED_LOCALE  = "general.useragent.locale";
-
-function setLocale(locale) {
-  prefs.set(PREF_MATCH_OS_LOCALE, false);
-  prefs.set(PREF_SELECTED_LOCALE, locale);
-}
-
-function resetLocale() {
-  prefs.reset(PREF_MATCH_OS_LOCALE);
-  prefs.reset(PREF_SELECTED_LOCALE);
-}
-
-function definePseudo(loader, id, exports) {
-  let uri = resolveURI(id, loader.mapping);
-  loader.modules[uri] = { exports: exports };
-}
-
-function createTest(locale, testFunction) {
-  return function (assert, done) {
-    let loader = Loader(module);
-    // Change the locale before loading new l10n modules in order to load
-    // the right .json file
-    setLocale(locale);
-    // Initialize main l10n module in order to load new locale files
-    loader.require("sdk/l10n/loader").
-      load(rootURI).
-      then(function success(data) {
-             definePseudo(loader, '@l10n/data', data);
-             // Execute the given test function
-             try {
-               testFunction(assert, loader, function onDone() {
-                 loader.unload();
-                 resetLocale();
-                 done();
-               });
-             }
-             catch(e) {
-              console.exception(e);
-             }
-           },
-           function failure(error) {
-             assert.fail("Unable to load locales: " + error);
-           });
-  };
-}
-
-exports.testExactMatching = createTest("fr-FR", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-                   "Key not translated");
-  assert.equal(_("Translated"), "Oui",
-                   "Simple key translated");
-
-  // Placeholders
-  assert.equal(_("placeholderString", "works"), "Placeholder works",
-                   "Value with placeholder");
-  assert.equal(_("Placeholder %s", "works"), "Placeholder works",
-                   "Key without value but with placeholder");
-  assert.equal(_("Placeholders %2s %1s %s.", "working", "are", "correctly"),
-                   "Placeholders are working correctly.",
-                   "Multiple placeholders");
-
-  // Plurals
-   assert.equal(_("downloadsCount", 0),
-                   "0 téléchargement",
-                   "PluralForm form 'one' for 0 in french");
-  assert.equal(_("downloadsCount", 1),
-                   "1 téléchargement",
-                   "PluralForm form 'one' for 1 in french");
-  assert.equal(_("downloadsCount", 2),
-                   "2 téléchargements",
-                   "PluralForm form 'other' for n > 1 in french");
-
-  done();
-});
-
-exports.testHtmlLocalization = createTest("en-GB", function(assert, loader, done) {
-  // Ensure initing html component that watch document creations
-  // Note that this module is automatically initialized in
-  // cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
-  let loaderHtmlL10n = loader.require("sdk/l10n/html");
-  loaderHtmlL10n.enable();
-
-  let uri = require("sdk/self").data.url("test-localization.html");
-  let worker = loader.require("sdk/page-worker").Page({
-    contentURL: uri,
-    contentScript: "new " + function ContentScriptScope() {
-      let nodes = document.body.querySelectorAll("*[data-l10n-id]");
-      self.postMessage([nodes[0].innerHTML,
-                        nodes[1].innerHTML,
-                        nodes[2].innerHTML,
-                        nodes[3].innerHTML]);
-    },
-    onMessage: function (data) {
-      assert.equal(
-        data[0],
-        "Kept as-is",
-        "Nodes with unknown id in .properties are kept 'as-is'"
-      );
-      assert.equal(data[1], "Yes", "HTML is translated");
-      assert.equal(
-        data[2],
-        "no &lt;b&gt;HTML&lt;/b&gt; injection",
-        "Content from .properties is text content; HTML can't be injected."
-      );
-      assert.equal(data[3], "Yes", "Multiple elements with same data-l10n-id are accepted.");
-
-      done();
-    }
-  });
-});
-
-exports.testEnUsLocaleName = createTest("en-GB", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "Yes",
-               "String with translation is correctly translated");
-
-  // Check Unicode char escaping sequences
-  assert.equal(_("unicodeEscape"), " @ ",
-               "Unicode escaped sequances are correctly converted");
-
-  // Check plural forms regular matching
-  assert.equal(_("downloadsCount", 0),
-                   "0 downloads",
-                   "PluralForm form 'other' for 0 in english");
-  assert.equal(_("downloadsCount", 1),
-                   "one download",
-                   "PluralForm form 'one' for 1 in english");
-  assert.equal(_("downloadsCount", 2),
-                   "2 downloads",
-                   "PluralForm form 'other' for n != 1 in english");
-
-  // Check optional plural forms
-  assert.equal(_("pluralTest", 0),
-                   "optional zero form",
-                   "PluralForm form 'zero' can be optionaly specified. (Isn't mandatory in english)");
-  assert.equal(_("pluralTest", 1),
-                   "fallback to other",
-                   "If the specific plural form is missing, we fallback to 'other'");
-
-  // Ensure that we can omit specifying the generic key without [other]
-  // key[one] = ...
-  // key[other] = ...  # Instead of `key = ...`
-  assert.equal(_("explicitPlural", 1),
-                   "one",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-  assert.equal(_("explicitPlural", 10),
-                   "other",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-
-  assert.equal(_("first_identifier", "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier no count");
-  assert.equal(_("first_identifier", 0, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 0");
-  assert.equal(_("first_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "first_identifier with count = 1");
-  assert.equal(_("first_identifier", 2, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 2");
-
-  assert.equal(_("second_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with no count");
-  assert.equal(_("second_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 0");
-  assert.equal(_("second_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 1");
-  assert.equal(_("second_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 2");
-
-  assert.equal(_("third_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with no count");
-  assert.equal(_("third_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 0");
-  assert.equal(_("third_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 2");
-
-  done();
-});
-
-exports.testUsingJSON = function(assert) {
-  assert.equal(usingJSON, false, 'not using json');
-}
-
-exports.testShortLocaleName = createTest("eo", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "jes",
-               "String with translation is correctly translated");
-
-  done();
-});
-
-
-// Before running tests, disable HTML service which is automatially enabled
-// in api-utils/addon/runner.js
-require('sdk/l10n/html').disable();
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n-properties/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-l10n@jetpack",
-  "title": "Test L10n",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/data/test-localization.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>HTML Localization</title>
-  </head>
-  <body>
-    <div data-l10n-id="Not translated">Kept as-is</div>
-    <ul data-l10n-id="Translated">
-      <li>Inner html content is replaced,</li>
-      <li data-l10n-id="text-content">
-        Elements with data-l10n-id attribute whose parent element is translated
-        will be replaced by the content of the translation.
-      </li>
-    </ul>
-    <div data-l10n-id="text-content">No</div>
-    <div data-l10n-id="Translated">
-      A data-l10n-id value can be used in multiple elements
-    </div>
-    <a data-l10n-id="link-attributes" title="Certain whitelisted attributes get translated too" alt="No" accesskey="A"></a>
-    <input data-l10n-id="input" type="text" placeholder="Form placeholders are translateable">
-    <menu>
-      <menuitem data-l10n-id="contextitem" label="Labels of select options and context menus are translateable">
-    </menu>
-  </body>
-</html
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/locale/en.properties
+++ /dev/null
@@ -1,38 +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/.
-
-Translated= Yes
-
-text-content=no <b>HTML</b> injection
-
-downloadsCount=%d downloads
-downloadsCount[one]=one download
-
-pluralTest=fallback to other
-pluralTest[zero]=optional zero form
-
-explicitPlural[one]=one
-explicitPlural[other]=other
-
-# You can use unicode char escaping in order to inject space at the beginning/
-# end of your string. (Regular spaces are automatically ignore by .properties
-# file parser)
-unicodeEscape = \u0020\u0040\u0020
-# this string equals to " @ "
-
-# bug 1033309 plurals with multiple placeholders
-first_identifier[one]=first entry is %s and the second one is %s.
-first_identifier=the entries are %s and %s.
-second_identifier[other]=first entry is %s and the second one is %s.
-third_identifier=first entry is %s and the second one is %s.
-
-# bug 824489 allow translation of element attributes
-link-attributes.title=Yes
-link-attributes.alt=Yes
-link-attributes.accesskey=B
-input.placeholder=Yes
-contextitem.label=Yes
-link-attributes.ariaLabel=Yes
-link-attributes.ariaValueText=Value
-link-attributes.ariaMozHint=Hint
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/locale/eo.properties
+++ /dev/null
@@ -1,5 +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/.
-
-Translated= jes
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/locale/fr-FR.properties
+++ /dev/null
@@ -1,14 +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/.
-
-Translated= Oui
-
-placeholderString= Placeholder %s
-
-# Plural forms
-%d downloads=%d téléchargements
-%d downloads[one]=%d téléchargement
-
-downloadsCount=%d téléchargements
-downloadsCount[one]=%d téléchargement
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/main.js
+++ /dev/null
@@ -1,289 +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 prefs = require("sdk/preferences/service");
-const { Loader } = require('sdk/test/loader');
-const { resolveURI } = require('toolkit/loader');
-const { rootURI, isNative } = require("@loader/options");
-const { usingJSON } = require('sdk/l10n/json/core');
-
-const PREF_MATCH_OS_LOCALE  = "intl.locale.matchOS";
-const PREF_SELECTED_LOCALE  = "general.useragent.locale";
-
-function setLocale(locale) {
-  prefs.set(PREF_MATCH_OS_LOCALE, false);
-  prefs.set(PREF_SELECTED_LOCALE, locale);
-}
-
-function resetLocale() {
-  prefs.reset(PREF_MATCH_OS_LOCALE);
-  prefs.reset(PREF_SELECTED_LOCALE);
-}
-
-function definePseudo(loader, id, exports) {
-  let uri = resolveURI(id, loader.mapping);
-  loader.modules[uri] = { exports: exports };
-}
-
-function createTest(locale, testFunction) {
-  return function (assert, done) {
-    let loader = Loader(module);
-    // Change the locale before loading new l10n modules in order to load
-    // the right .json file
-    setLocale(locale);
-    // Initialize main l10n module in order to load new locale files
-    loader.require("sdk/l10n/loader").
-      load(rootURI).
-      then(null, function failure(error) {
-        if (!isNative)
-          assert.fail("Unable to load locales: " + error);
-      }).
-      then(function success(data) {
-             definePseudo(loader, '@l10n/data', data ? data : null);
-             // Execute the given test function
-             try {
-               testFunction(assert, loader, function onDone() {
-                 loader.unload();
-                 resetLocale();
-                 done();
-               });
-             }
-             catch(e) {
-              console.exception(e);
-             }
-           },
-           function failure(error) {
-             assert.fail("Unable to load locales: " + error);
-           });
-  };
-}
-
-exports.testExactMatching = createTest("fr-FR", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-                   "Key not translated");
-  assert.equal(_("Translated"), "Oui",
-                   "Simple key translated");
-
-  // Placeholders
-  assert.equal(_("placeholderString", "works"), "Placeholder works",
-                   "Value with placeholder");
-  assert.equal(_("Placeholder %s", "works"), "Placeholder works",
-                   "Key without value but with placeholder");
-  assert.equal(_("Placeholders %2s %1s %s.", "working", "are", "correctly"),
-                   "Placeholders are working correctly.",
-                   "Multiple placeholders");
-
-  // Plurals
-   assert.equal(_("downloadsCount", 0),
-                   "0 téléchargement",
-                   "PluralForm form 'one' for 0 in french");
-  assert.equal(_("downloadsCount", 1),
-                   "1 téléchargement",
-                   "PluralForm form 'one' for 1 in french");
-  assert.equal(_("downloadsCount", 2),
-                   "2 téléchargements",
-                   "PluralForm form 'other' for n > 1 in french");
-
-  done();
-});
-
-exports.testHtmlLocalizationPageWorker = createTest("en-GB", function(assert, loader, done) {
-  // Ensure initing html component that watch document creations
-  // Note that this module is automatically initialized in
-  // cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
-  let loaderHtmlL10n = loader.require("sdk/l10n/html");
-  loaderHtmlL10n.enable();
-
-  let uri = require("sdk/self").data.url("test-localization.html");
-  let worker = loader.require("sdk/page-worker").Page({
-    contentURL: uri,
-    contentScript: "new " + function ContentScriptScope() {
-      let nodes = document.body.querySelectorAll("*[data-l10n-id]");
-      self.postMessage([nodes[0].innerHTML,
-                        nodes[1].innerHTML,
-                        nodes[2].innerHTML,
-                        nodes[3].innerHTML,
-                        nodes[4].title,
-                        nodes[4].getAttribute("alt"),
-                        nodes[4].getAttribute("accesskey"),
-                        nodes[4].getAttribute("aria-label"),
-                        nodes[4].getAttribute("aria-valuetext"),
-                        nodes[4].getAttribute("aria-moz-hint"),
-                        nodes[5].placeholder,
-                        nodes[6].label]);
-    },
-    onMessage: function (data) {
-      assert.equal(
-        data[0],
-        "Kept as-is",
-        "Nodes with unknown id in .properties are kept 'as-is'"
-      );
-      assert.equal(data[1], "Yes", "HTML is translated");
-      assert.equal(
-        data[2],
-        "no &lt;b&gt;HTML&lt;/b&gt; injection",
-        "Content from .properties is text content; HTML can't be injected."
-      );
-      assert.equal(data[3], "Yes", "Multiple elements with same data-l10n-id are accepted.");
-      
-      // Attribute translation tests
-      assert.equal(data[4], "Yes", "Title attributes gets translated.");
-      assert.equal(data[5], "Yes", "Alt attributes gets translated.");
-      assert.equal(data[6], "B", "Accesskey gets translated.");
-      
-      assert.equal(data[7], "Yes", "Aria-Label gets translated.");
-      assert.equal(data[8], "Value", "Aria-valuetext gets translated.");
-      assert.equal(data[9], "Hint", "Aria-moz-hint gets translated.");
-      
-      assert.equal(data[10], "Yes", "Form placeholders are translateable.");
-      
-      assert.equal(data[11], "Yes", "Labels of select options and context menus are translateable.");
-
-      done();
-    }
-  });
-});
-
-exports.testHtmlLocalization = createTest("en-GB", function(assert, loader, done) {
-  // Ensure initing html component that watch document creations
-  // Note that this module is automatically initialized in
-  // cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
-  let loaderHtmlL10n = loader.require("sdk/l10n/html");
-  loaderHtmlL10n.enable();
-
-  let uri = require("sdk/self").data.url("test-localization.html");
-  loader.require("sdk/tabs").open({
-    url: uri,
-    onReady: function(tab) {
-      tab.attach({
-        contentURL: uri,
-        contentScript: "new " + function ContentScriptScope() {
-          let nodes = document.body.querySelectorAll("*[data-l10n-id]");
-          self.postMessage([nodes[0].innerHTML,
-                            nodes[1].innerHTML,
-                            nodes[2].innerHTML,
-                            nodes[3].innerHTML,
-                            nodes[4].title,
-                            nodes[4].getAttribute("alt"),
-                            nodes[4].getAttribute("accesskey"),
-                            nodes[4].getAttribute("aria-label"),
-                            nodes[4].getAttribute("aria-valuetext"),
-                            nodes[4].getAttribute("aria-moz-hint"),
-                            nodes[5].placeholder,
-                            nodes[6].label]);
-        },
-        onMessage: function (data) {
-          assert.equal(
-            data[0],
-            "Kept as-is",
-            "Nodes with unknown id in .properties are kept 'as-is'"
-          );
-          assert.equal(data[1], "Yes", "HTML is translated");
-          assert.equal(
-            data[2],
-            "no &lt;b&gt;HTML&lt;/b&gt; injection",
-            "Content from .properties is text content; HTML can't be injected."
-          );
-          assert.equal(data[3], "Yes", "Multiple elements with same data-l10n-id are accepted.");
-
-          // Attribute translation tests
-          assert.equal(data[4], "Yes", "Title attributes gets translated.");
-          assert.equal(data[5], "Yes", "Alt attributes gets translated.");
-          assert.equal(data[6], "B", "Accesskey gets translated.");
-          
-          assert.equal(data[7], "Yes", "Aria-Label gets translated.");
-          assert.equal(data[8], "Value", "Aria-valuetext gets translated.");
-          assert.equal(data[9], "Hint", "Aria-moz-hint gets translated.");
-          
-          assert.equal(data[10], "Yes", "Form placeholders are translateable.");
-          
-          assert.equal(data[11], "Yes", "Labels of select options and context menus are translateable.");
-
-          tab.close(done);
-        }
-      });
-    }
-  });
-});
-
-exports.testEnUsLocaleName = createTest("en-US", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "Yes",
-               "String with translation is correctly translated");
-
-  // Check Unicode char escaping sequences
-  assert.equal(_("unicodeEscape"), " @ ",
-               "Unicode escaped sequances are correctly converted");
-
-  // Check plural forms regular matching
-  assert.equal(_("downloadsCount", 0),
-                   "0 downloads",
-                   "PluralForm form 'other' for 0 in english");
-  assert.equal(_("downloadsCount", 1),
-                   "one download",
-                   "PluralForm form 'one' for 1 in english");
-  assert.equal(_("downloadsCount", 2),
-                   "2 downloads",
-                   "PluralForm form 'other' for n != 1 in english");
-
-  // Check optional plural forms
-  assert.equal(_("pluralTest", 0),
-                   "optional zero form",
-                   "PluralForm form 'zero' can be optionaly specified. (Isn't mandatory in english)");
-  assert.equal(_("pluralTest", 1),
-                   "fallback to other",
-                   "If the specific plural form is missing, we fallback to 'other'");
-
-  // Ensure that we can omit specifying the generic key without [other]
-  // key[one] = ...
-  // key[other] = ...  # Instead of `key = ...`
-  assert.equal(_("explicitPlural", 1),
-                   "one",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-  assert.equal(_("explicitPlural", 10),
-                   "other",
-                   "PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
-
-  assert.equal(_("first_identifier", "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier no count");
-  assert.equal(_("first_identifier", 0, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 0");
-  assert.equal(_("first_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "first_identifier with count = 1");
-  assert.equal(_("first_identifier", 2, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 2");
-
-  assert.equal(_("second_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with no count");
-  assert.equal(_("second_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 0");
-  assert.equal(_("second_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 1");
-  assert.equal(_("second_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 2");
-
-  assert.equal(_("third_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with no count");
-  assert.equal(_("third_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 0");
-  assert.equal(_("third_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 2");
-
-  done();
-});
-
-exports.testUsingJSON = function(assert) {
-  assert.equal(usingJSON, !isNative, 'using json');
-}
-
-exports.testShortLocaleName = createTest("eo", function(assert, loader, done) {
-  let _ = loader.require("sdk/l10n").get;
-  assert.equal(_("Not translated"), "Not translated",
-               "String w/o translation is kept as-is");
-  assert.equal(_("Translated"), "jes",
-               "String with translation is correctly translated");
-
-  done();
-});
-
-
-// Before running tests, disable HTML service which is automatially enabled
-// in api-utils/addon/runner.js
-require('sdk/l10n/html').disable();
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/l10n/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-l10n@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/layout-change/lib/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { isNative } = require("@loader/options");
-
-if (isNative) {
-  module.exports = require("./test-toolkit-loader");
-}
-else {
-  module.exports = require("./test-cuddlefish-loader");
-}
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/layout-change/lib/test-cuddlefish-loader.js
+++ /dev/null
@@ -1,164 +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 { LoaderWithHookedConsole } = require('sdk/test/loader');
-const { loader } = LoaderWithHookedConsole(module);
-const app = require("sdk/system/xul-app");
-
-// This test makes sure that require statements used by all AMO hosted
-// add-ons will be able to use old require statements.
-// Tests are based on following usage data:
-// https://docs.google.com/spreadsheet/ccc?key=0ApEBy-GRnGxzdHlRMHJ5RXN1aWJ4RGhINkxSd0FCQXc#gid=0
-
-exports["test compatibility"] = function(assert) {
-  let { require } = loader;
-
-  assert.equal(require("self"),
-               require("sdk/self"), "sdk/self -> self");
-
-  assert.equal(require("tabs"),
-               require("sdk/tabs"), "sdk/tabs -> tabs");
-
-  if (app.is("Firefox")) {
-    assert.throws(() => require("widget"),
-      /Module `widget` is not found at/,
-      "There is no widget module");
-
-    assert.throws(() => require("sdk/widget"),
-      /Module `sdk\/widget` is not found at/,
-      "There is no sdk/widget module");
-  }
-
-  assert.equal(require("page-mod"),
-               require("sdk/page-mod"), "sdk/page-mod -> page-mod");
-
-  if (app.is("Firefox")) {
-    assert.equal(require("panel"),
-                 require("sdk/panel"), "sdk/panel -> panel");
-  }
-
-  assert.equal(require("request"),
-               require("sdk/request"), "sdk/request -> request");
-
-  assert.equal(require("chrome"),
-               require("chrome"), "chrome -> chrome");
-
-  assert.equal(require("simple-storage"),
-               require("sdk/simple-storage"), "sdk/simple-storage -> simple-storage");
-
-  if (app.is("Firefox")) {
-    assert.equal(require("context-menu"),
-                 require("sdk/context-menu"), "sdk/context-menu -> context-menu");
-  }
-
-  assert.equal(require("notifications"),
-               require("sdk/notifications"), "sdk/notifications -> notifications");
-
-  assert.equal(require("preferences-service"),
-               require("sdk/preferences/service"), "sdk/preferences/service -> preferences-service");
-
-  assert.equal(require("window-utils"),
-               require("sdk/deprecated/window-utils"), "sdk/deprecated/window-utils -> window-utils");
-
-  assert.equal(require("url"),
-               require("sdk/url"), "sdk/url -> url");
-
-  if (app.is("Firefox")) {
-    assert.equal(require("selection"),
-                 require("sdk/selection"), "sdk/selection -> selection");
-  }
-
-  assert.equal(require("timers"),
-               require("sdk/timers"), "sdk/timers -> timers");
-
-  assert.equal(require("simple-prefs"),
-               require("sdk/simple-prefs"), "sdk/simple-prefs -> simple-prefs");
-
-  assert.equal(require("traceback"),
-               require("sdk/console/traceback"), "sdk/console/traceback -> traceback");
-
-  assert.equal(require("unload"),
-               require("sdk/system/unload"), "sdk/system/unload -> unload");
-
-  assert.equal(require("hotkeys"),
-               require("sdk/hotkeys"), "sdk/hotkeys -> hotkeys");
-
-  if (app.is("Firefox")) {
-    assert.equal(require("clipboard"),
-                 require("sdk/clipboard"), "sdk/clipboard -> clipboard");
-  }
-
-  assert.equal(require("windows"),
-               require("sdk/windows"), "sdk/windows -> windows");
-
-  assert.equal(require("page-worker"),
-               require("sdk/page-worker"), "sdk/page-worker -> page-worker");
-
-  assert.equal(require("timer"),
-               require("sdk/timers"), "sdk/timers -> timer");
-
-  assert.equal(require("xhr"),
-               require("sdk/net/xhr"), "sdk/io/xhr -> xhr");
-
-  assert.equal(require("private-browsing"),
-               require("sdk/private-browsing"), "sdk/private-browsing -> private-browsing");
-
-  assert.equal(require("passwords"),
-               require("sdk/passwords"), "sdk/passwords -> passwords");
-
-  assert.equal(require("match-pattern"),
-               require("sdk/util/match-pattern"), "sdk/util/match-pattern -> match-pattern");
-
-  assert.equal(require("file"),
-               require("sdk/io/file"), "sdk/io/file -> file");
-
-  assert.equal(require("xul-app"),
-               require("sdk/system/xul-app"), "sdk/system/xul-app -> xul-app");
-
-  assert.equal(require("api-utils"),
-               require("sdk/deprecated/api-utils"), "sdk/deprecated/api-utils -> api-utils");
-
-  assert.equal(require("runtime"),
-               require("sdk/system/runtime"), "sdk/system/runtime -> runtime");
-
-  assert.equal(require("base64"),
-               require("sdk/base64"), "sdk/base64 -> base64");
-
-  assert.equal(require("xpcom"),
-               require("sdk/platform/xpcom"), "sdk/platform/xpcom -> xpcom");
-
-  assert.equal(require("keyboard/utils"),
-               require("sdk/keyboard/utils"), "sdk/keyboard/utils -> keyboard/utils");
-
-  assert.equal(require("system"),
-               require("sdk/system"), "sdk/system -> system");
-
-  assert.equal(require("querystring"),
-               require("sdk/querystring"), "sdk/querystring -> querystring");
-
-  assert.equal(require("tabs/utils"),
-               require("sdk/tabs/utils"), "sdk/tabs/utils -> tabs/utils");
-
-  assert.equal(require("dom/events"),
-               require("sdk/dom/events-shimmed"), "sdk/dom/events-shimmed -> dom/events");
-
-  assert.equal(require("tabs/tab.js"),
-               require("sdk/tabs/tab"), "sdk/tabs/tab -> tabs/tab.js");
-
-  assert.equal(require("environment"),
-               require("sdk/system/environment"), "sdk/system/environment -> environment");
-
-  assert.equal(require("test/assert"),
-               require("sdk/test/assert"), "sdk/test/assert -> test/assert");
-
-  assert.equal(require("hidden-frame"),
-               require("sdk/frame/hidden-frame"), "sdk/frame/hidden-frame -> hidden-frame");
-
-  assert.equal(require("collection"),
-               require("sdk/util/collection"), "sdk/util/collection -> collection");
-
-  assert.equal(require("array"),
-               require("sdk/util/array"), "sdk/util/array -> array");
-};
deleted file mode 100644
--- a/addon-sdk/source/test/addons/layout-change/lib/test-toolkit-loader.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["test compatibility"] = function(assert) {
-  assert.throws(() => require("self"),
-                /^Module `self` is not found/,
-                "sdk/self -> self");
-};
deleted file mode 100644
--- a/addon-sdk/source/test/addons/layout-change/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "id": "test-layout-change@jetpack",
-  "name": "test-layout-change",
-  "ignore-deprecated-path": true,
-  "version": "0.0.2",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/main/main.js
+++ /dev/null
@@ -1,37 +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 { setTimeout } = require('sdk/timers');
-
-var mainStarted = false;
-
-exports.main = function main(options, callbacks) {
-  mainStarted = true;
-
-  let tests = {};
-
-  tests.testMainArguments = function(assert) {
-  	assert.ok(!!options, 'options argument provided to main');
-    assert.ok('loadReason' in options, 'loadReason is in options provided by main');
-    assert.equal(typeof callbacks.print, 'function', 'callbacks.print is a function');
-    assert.equal(typeof callbacks.quit, 'function', 'callbacks.quit is a function');
-
-    // Re-enable when bug 1251664 is fixed
-    //assert.equal(options.loadReason, 'install', 'options.loadReason is install');
-  }
-
-  require('sdk/test/runner').runTestsFromModule({exports: tests});
-}
-
-// this causes a fail if main does not start
-setTimeout(function() {
-  if (mainStarted)
-  	return;
-
-  // main didn't start, fail..
-  require("sdk/test/runner").runTestsFromModule({exports: {
-  	testFail: assert => assert.fail('Main did not start..')
-  }});
-}, 500);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/main/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-main@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/name-in-numbers-plus/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { name } = require("sdk/self");
-
-exports["test self.name"] = (assert) => {
-  assert.equal(name, "0-0", "using '0-0' works.");
-}
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/name-in-numbers-plus/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "name-in-numbers-plus@jetpack",
-  "name": "0-0",
-  "main": "./index.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/name-in-numbers/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { name } = require("sdk/self");
-
-exports["test self.name"] = (assert) => {
-  assert.equal(name, "5", "using '5' works.");
-}
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/name-in-numbers/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "name-in-numbers@jetpack",
-  "name": "5",
-  "main": "./index.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/packaging/main.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var options = require("@loader/options");
-var metadata = {};
-if (options.isNative) {
-  metadata = require("./package.json");
-  metadata.permissions = {};
-  Object.freeze(metadata);
-}
-else {
-  metadata = options.metadata;
-}
-
-exports.testPackaging = function(assert) {
-  assert.equal(metadata.description,
-               "Add-on development made easy.",
-               "packaging metadata should be available");
-  try {
-    metadata.description = 'new description';
-    assert.fail('should not have been able to set options.metadata property');
-  }
-  catch (e) {}
-
-  assert.equal(metadata.description,
-               "Add-on development made easy.",
-               "packaging metadata should be frozen");
-
-  assert.equal(metadata.permissions['private-browsing'], undefined,
-               "private browsing metadata should be undefined");
-
-  assert.equal(metadata['private-browsing'], undefined,
-               "private browsing metadata should be be frozen");
-
-  assert.equal(options['private-browsing'], undefined,
-               "private browsing metadata should be be frozen");
-
-  try {
-    metadata['private-browsing'] = true;
-    assert.fail('should not have been able to set options.metadata property');
-  }
-  catch(e) {}
-  assert.equal(metadata['private-browsing'], undefined,
-               "private browsing metadata should be be frozen");
-
-  try {
-    options.permissions['private-browsing'] = true;
-    assert.fail('should not have been able to set options.metadata.permissions property');
-  }
-  catch (e) {}
-  assert.equal(metadata.permissions['private-browsing'], undefined,
-               "private browsing metadata should be be frozen");
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/packaging/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-packaging@jetpack",
-  "description": "Add-on development made easy.",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/packed/main.js
+++ /dev/null
@@ -1,20 +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 { packed } = require("sdk/self");
-const url = require("sdk/url");
-
-exports["test self.packed"] = function (assert) {
-  assert.ok(packed, "require('sdk/self').packed is correct");
-}
-
-exports["test url.toFilename"] = function (assert) {
-  assert.throws(
-      function() { url.toFilename(module.uri); },
-      /cannot map to filename: /,
-      "url.toFilename() can fail for packed XPIs");
-}
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/packed/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-url@jetpack",
-  "unpack": false,
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-post/data/index.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>Page Mod Debugger Test</title>
-  </head>
-  <body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-post/data/script.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-function runDebuggerStatement () {
-  window.document.body.setAttribute('style', 'background-color: red');
-  debugger;
-  window.document.body.setAttribute('style', 'background-color: green');
-}
-
-exportFunction(
-  runDebuggerStatement,
-  document.defaultView,
-  { defineAs: "runDebuggerStatement" }
-);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-post/main.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require('chrome');
-const { PageMod } = require('sdk/page-mod');
-const tabs = require('sdk/tabs');
-const { closeTab } = require('sdk/tabs/utils');
-const promise = require('sdk/core/promise')
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { data } = require('sdk/self');
-const { set } = require('sdk/preferences/service');
-
-const { DevToolsShim } = Cu.import("chrome://devtools-shim/content/DevToolsShim.jsm", {});
-
-var gClient;
-var ok;
-var testName = 'testDebugger';
-var iframeURL = 'data:text/html;charset=utf-8,' + testName;
-var TAB_URL = 'data:text/html;charset=utf-8,' + encodeURIComponent('<iframe src="' + iframeURL + '" />');
-TAB_URL = data.url('index.html');
-var mod;
-
-exports.testDebugger = function(assert, done) {
-  ok = assert.ok.bind(assert);
-  assert.pass('starting test');
-  set('devtools.debugger.log', true);
-
-  gClient = DevToolsShim.createDebuggerClient();
-  gClient.connect((aType, aTraits) => {
-    tabs.open({
-      url: TAB_URL,
-      onLoad: function(tab) {
-        assert.pass('tab loaded');
-
-        attachTabActorForUrl(gClient, TAB_URL).
-          then(_ => { assert.pass('attachTabActorForUrl called'); return _; }).
-          then(attachThread).
-          then(testDebuggerStatement).
-          then(_ => { assert.pass('testDebuggerStatement called') }).
-          then(closeConnection).
-          then(_ => { assert.pass('closeConnection called') }).
-          then(_ => { tab.close() }).
-          then(done).
-          catch(aError => {
-            ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
-          });
-      }
-    });
-  });
-}
-
-function attachThread([aGrip, aResponse]) {
-  let deferred = promise.defer();
-
-  // Now attach and resume...
-  gClient.request({ to: aResponse.threadActor, type: "attach" }, () => {
-    gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
-      ok(true, "Pause wasn't called before we've attached.");
-      deferred.resolve([aGrip, aResponse]);
-    });
-  });
-
-  return deferred.promise;
-}
-
-function testDebuggerStatement([aGrip, aResponse]) {
-  let deferred = promise.defer();
-  ok(aGrip, 'aGrip existss')
-
-  gClient.addListener("paused", (aEvent, aPacket) => {
-    ok(true, 'there was a pause event');
-    gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
-      ok(true, "The pause handler was triggered on a debugger statement.");
-      deferred.resolve();
-    });
-  });
-
-  mod = PageMod({
-    include: TAB_URL,
-    attachTo: ['existing', 'top', 'frame'],
-    contentScriptFile: data.url('script.js'),
-    onAttach: function(mod) {
-      ok(true, 'the page-mod was attached to ' + mod.tab.url);
-
-      require('sdk/timers').setTimeout(function() {
-        let debuggee = getMostRecentBrowserWindow().gBrowser.selectedBrowser.contentWindow.wrappedJSObject;
-        debuggee.runDebuggerStatement();
-        ok(true, 'called runDebuggerStatement');
-      }, 500)
-    }
-  });
-  ok(true, 'PageMod was created');
-
-  return deferred.promise;
-}
-
-function getTabActorForUrl(aClient, aUrl) {
-  let deferred = promise.defer();
-
-  aClient.listTabs(aResponse => {
-    let tabActor = aResponse.tabs.filter(aGrip => aGrip.url == aUrl).pop();
-    deferred.resolve(tabActor);
-  });
-
-  return deferred.promise;
-}
-
-function attachTabActorForUrl(aClient, aUrl) {
-  let deferred = promise.defer();
-
-  getTabActorForUrl(aClient, aUrl).then(aGrip => {
-    aClient.attachTab(aGrip.actor, aResponse => {
-      deferred.resolve([aGrip, aResponse]);
-    });
-  });
-
-  return deferred.promise;
-}
-
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-post/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-page-mod-debugger@jetpack",
-  "author": "Erik Vold",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-pre/data/index.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>Page Mod Debugger Test</title>
-  </head>
-  <body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-pre/data/script.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-function runDebuggerStatement () {
-  window.document.body.setAttribute('style', 'background-color: red');
-  debugger;
-  window.document.body.setAttribute('style', 'background-color: green');
-}
-
-exportFunction(
-  runDebuggerStatement,
-  document.defaultView,
-  { defineAs: "runDebuggerStatement" }
-);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-pre/main.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require('chrome');
-const { PageMod } = require('sdk/page-mod');
-const tabs = require('sdk/tabs');
-const { closeTab } = require('sdk/tabs/utils');
-const promise = require('sdk/core/promise')
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { data } = require('sdk/self');
-const { set } = require('sdk/preferences/service');
-
-const { DevToolsShim } = Cu.import("chrome://devtools-shim/content/DevToolsShim.jsm", {});
-
-var gClient;
-var ok;
-var testName = 'testDebugger';
-var iframeURL = 'data:text/html;charset=utf-8,' + testName;
-var TAB_URL = 'data:text/html;charset=utf-8,' + encodeURIComponent('<iframe src="' + iframeURL + '" />');
-TAB_URL = data.url('index.html');
-var mod;
-
-exports.testDebugger = function(assert, done) {
-  ok = assert.ok.bind(assert);
-  assert.pass('starting test');
-  set('devtools.debugger.log', true);
-
-  mod = PageMod({
-    include: TAB_URL,
-    attachTo: ['existing', 'top', 'frame'],
-    contentScriptFile: data.url('script.js'),
-  });
-  ok(true, 'PageMod was created');
-
-  gClient = DevToolsShim.createDebuggerClient();
-  gClient.connect((aType, aTraits) => {
-    tabs.open({
-      url: TAB_URL,
-      onLoad: function(tab) {
-        assert.pass('tab loaded');
-
-        attachTabActorForUrl(gClient, TAB_URL).
-          then(_ => { assert.pass('attachTabActorForUrl called'); return _; }).
-          then(attachThread).
-          then(testDebuggerStatement).
-          then(_ => { assert.pass('testDebuggerStatement called') }).
-          then(closeConnection).
-          then(_ => { assert.pass('closeConnection called') }).
-          then(_ => { tab.close() }).
-          then(done).
-          catch(aError => {
-            ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
-          });
-      }
-    });
-  });
-}
-
-function attachThread([aGrip, aResponse]) {
-  let deferred = promise.defer();
-
-  // Now attach and resume...
-  gClient.request({ to: aResponse.threadActor, type: "attach" }, () => {
-    gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
-      ok(true, "Pause wasn't called before we've attached.");
-      deferred.resolve([aGrip, aResponse]);
-    });
-  });
-
-  return deferred.promise;
-}
-
-function testDebuggerStatement([aGrip, aResponse]) {
-  let deferred = promise.defer();
-  ok(aGrip, 'aGrip existss')
-
-  gClient.addListener("paused", (aEvent, aPacket) => {
-    ok(true, 'there was a pause event');
-    gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
-      ok(true, "The pause handler was triggered on a debugger statement.");
-      deferred.resolve();
-    });
-  });
-
-  let debuggee = getMostRecentBrowserWindow().gBrowser.selectedBrowser.contentWindow.wrappedJSObject;
-  debuggee.runDebuggerStatement();
-  ok(true, 'called runDebuggerStatement');
-
-  return deferred.promise;
-}
-
-function getTabActorForUrl(aClient, aUrl) {
-  let deferred = promise.defer();
-
-  aClient.listTabs(aResponse => {
-    let tabActor = aResponse.tabs.filter(aGrip => aGrip.url == aUrl).pop();
-    deferred.resolve(tabActor);
-  });
-
-  return deferred.promise;
-}
-
-function attachTabActorForUrl(aClient, aUrl) {
-  let deferred = promise.defer();
-
-  getTabActorForUrl(aClient, aUrl).then(aGrip => {
-    aClient.attachTab(aGrip.actor, aResponse => {
-      deferred.resolve([aGrip, aResponse]);
-    });
-  });
-
-  return deferred.promise;
-}
-
-function closeConnection() {
-  let deferred = promise.defer();
-  gClient.close(deferred.resolve);
-  return deferred.promise;
-}
-
-// bug 1042976 - temporary test disable
-module.exports = {};
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-mod-debugger-pre/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "id": "test-page-mod-debugger@jetpack",
-  "author": "Erik Vold",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-worker/data/page.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<script type="text/javascript" src="page.js"></script>
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-worker/data/page.js
+++ /dev/null
@@ -1,13 +0,0 @@
-window.addEventListener("load", function() {
-  addon.port.emit("load", "ok");
-});
-
-addon.postMessage("first message");
-addon.on("message", function(msg) {
-  if (msg == "ping")
-    addon.postMessage("pong");
-});
-
-addon.port.on("ping", function() {
-  addon.port.emit("pong");
-});
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-worker/main.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Page } = require("sdk/page-worker");
-const { data } = require("sdk/self");
-
-exports["test page load"] = function(assert, done) {
-  let page = Page({
-    contentURL: data.url("page.html")
-  });
-
-  page.port.on("load", function(check) {
-    assert.equal(check, "ok", "saw the load message");
-    page.destroy();
-    done();
-  });
-};
-
-exports["test postMessage"] = function(assert, done) {
-  let page = Page({
-    contentURL: data.url("page.html"),
-    onMessage: function(msg) {
-      if (msg == "pong") {
-        assert.ok(true, "saw the second message");
-        page.destroy();
-        done();
-        return;
-      }
-
-      assert.equal(msg, "first message", "saw the first message");
-      this.postMessage("ping");
-    }
-  });
-};
-
-exports["test port"] = function(assert, done) {
-  let page = Page({
-    contentURL: data.url("page.html")
-  });
-
-  page.port.on("pong", function() {
-    assert.ok(true, "saw the response");
-    page.destroy();
-    done();
-  });
-
-  page.port.emit("ping");
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/page-worker/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "id": "test-page-worker"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/favicon-helpers.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { Cc, Ci, Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const loader = Loader(module);
-const httpd = loader.require('./httpd');
-const { pathFor } = require('sdk/system');
-const { startServerAsync } = httpd;
-const basePath = pathFor('ProfD');
-const { atob } = Cu.import("resource://gre/modules/Services.jsm", {});
-const historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
-                       .getService(Ci.nsINavHistoryService);
-const { events } = require('sdk/places/events');
-const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-
-function onFaviconChange (url) {
-  return new Promise(resolve => {
-    function handler ({data, type}) {
-      if (type !== 'history-page-changed' ||
-          data.url !== url ||
-          data.property !== Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
-        return;
-      events.off('data', handler);
-      resolve(data.value);
-    }
-
-    events.on('data', handler);
-  });
-}
-exports.onFaviconChange = onFaviconChange;
-
-/*
- * Takes page content, a page path, and favicon binary data
- */
-function serve ({name, favicon, port, host}) {
-  let faviconTag = '<link rel="icon" type="image/x-icon" href="/'+ name +'.ico"/>';
-  let content = '<html><head>' + faviconTag + '<title>'+name+'</title></head><body></body></html>';
-  let srv = startServerAsync(port, basePath);
-
-  let pagePath = OS.Path.join(basePath, name + '.html');
-  let iconPath = OS.Path.join(basePath, name + '.ico');
-
-
-  return OS.File.writeAtomic(iconPath, favicon).
-    then(() => {
-      return OS.File.writeAtomic(pagePath, content);
-    }).
-    then(() => srv);
-}
-exports.serve = serve;
-
-var binFavicon = exports.binFavicon = atob('AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgICAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYzAABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZzABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkAmQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwAAACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaGhgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8ACgoKCgoKCgoKCgoKCgoKCgoKCgoHAQEMbQoKCgoKCgoAAAdDH/kgHRIAAAAAAAAAAADrHfn5ASQQAAAAAAAAAArsBx0B+fkgHesAAAAAAAD/Cgwf+fn5IA4dEus/IvcACgcMAfkg+QEB+SABHushbf8QHR/5HQH5+QEdHetEHx4K7B/5+QH5+fkdDBL5+SBE/wwdJfkf+fn5AR8g+fkfEArsCh/5+QEeJR/5+SAeBwAACgoe+SAlHwFAEhAfAAAAAPcKHh8eASYBHhAMAAAAAAAA9EMdIB8gHh0dBwAAAAAAAAAA7BAdQ+wHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AADwfwAAwH8AAMB/AAAAPwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAcAAIAPAADADwAA8D8AAP//AAA');
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/httpd.js
+++ /dev/null
@@ -1,5205 +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/. */
-
-/*
-*  NOTE: do not edit this file, this is copied from:
-*  https://github.com/mozilla/addon-sdk/blob/master/test/lib/httpd.js
-*/
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { components, CC, Cc, Ci, Cr, Cu } = require("chrome");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
-const PR_UINT32_MAX = Math.pow(2, 32) - 1;
-
-/** True if debugging output is enabled, false otherwise. */
-var DEBUG = false; // non-const *only* so tweakable in server tests
-
-/** True if debugging output should be timestamped. */
-var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests
-
-var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance();
-
-/**
-* Asserts that the given condition holds. If it doesn't, the given message is
-* dumped, a stack trace is printed, and an exception is thrown to attempt to
-* stop execution (which unfortunately must rely upon the exception not being
-* accidentally swallowed by the code that uses it).
-*/
-function NS_ASSERT(cond, msg)
-{
-  if (DEBUG && !cond)
-  {
-    dumpn("###!!!");
-    dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!"));
-    dumpn("###!!! Stack follows:");
-
-    var stack = new Error().stack.split(/\n/);
-    dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n"));
-
-    throw Cr.NS_ERROR_ABORT;
-  }
-}
-
-/** Constructs an HTTP error object. */
-function HttpError(code, description)
-{
-  this.code = code;
-  this.description = description;
-}
-HttpError.prototype =
-{
-  toString: function()
-  {
-    return this.code + " " + this.description;
-  }
-};
-
-/**
-* Errors thrown to trigger specific HTTP server responses.
-*/
-const HTTP_400 = new HttpError(400, "Bad Request");
-const HTTP_401 = new HttpError(401, "Unauthorized");
-const HTTP_402 = new HttpError(402, "Payment Required");
-const HTTP_403 = new HttpError(403, "Forbidden");
-const HTTP_404 = new HttpError(404, "Not Found");
-const HTTP_405 = new HttpError(405, "Method Not Allowed");
-const HTTP_406 = new HttpError(406, "Not Acceptable");
-const HTTP_407 = new HttpError(407, "Proxy Authentication Required");
-const HTTP_408 = new HttpError(408, "Request Timeout");
-const HTTP_409 = new HttpError(409, "Conflict");
-const HTTP_410 = new HttpError(410, "Gone");
-const HTTP_411 = new HttpError(411, "Length Required");
-const HTTP_412 = new HttpError(412, "Precondition Failed");
-const HTTP_413 = new HttpError(413, "Request Entity Too Large");
-const HTTP_414 = new HttpError(414, "Request-URI Too Long");
-const HTTP_415 = new HttpError(415, "Unsupported Media Type");
-const HTTP_417 = new HttpError(417, "Expectation Failed");
-
-const HTTP_500 = new HttpError(500, "Internal Server Error");
-const HTTP_501 = new HttpError(501, "Not Implemented");
-const HTTP_502 = new HttpError(502, "Bad Gateway");
-const HTTP_503 = new HttpError(503, "Service Unavailable");
-const HTTP_504 = new HttpError(504, "Gateway Timeout");
-const HTTP_505 = new HttpError(505, "HTTP Version Not Supported");
-
-/** Creates a hash with fields corresponding to the values in arr. */
-function array2obj(arr)
-{
-  var obj = {};
-  for (var i = 0; i < arr.length; i++)
-    obj[arr[i]] = arr[i];
-  return obj;
-}
-
-/** Returns an array of the integers x through y, inclusive. */
-function range(x, y)
-{
-  var arr = [];
-  for (var i = x; i <= y; i++)
-    arr.push(i);
-  return arr;
-}
-
-/** An object (hash) whose fields are the numbers of all HTTP error codes. */
-const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505)));
-
-
-/**
-* The character used to distinguish hidden files from non-hidden files, a la
-* the leading dot in Apache. Since that mechanism also hides files from
-* easy display in LXR, ls output, etc. however, we choose instead to use a
-* suffix character. If a requested file ends with it, we append another
-* when getting the file on the server. If it doesn't, we just look up that
-* file. Therefore, any file whose name ends with exactly one of the character
-* is "hidden" and available for use by the server.
-*/
-const HIDDEN_CHAR = "^";
-
-/**
-* The file name suffix indicating the file containing overridden headers for
-* a requested file.
-*/
-const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
-
-/** Type used to denote SJS scripts for CGI-like functionality. */
-const SJS_TYPE = "sjs";
-
-/** Base for relative timestamps produced by dumpn(). */
-var firstStamp = 0;
-
-/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */
-function dumpn(str)
-{
-  if (DEBUG)
-  {
-    var prefix = "HTTPD-INFO | ";
-    if (DEBUG_TIMESTAMP)
-    {
-      if (firstStamp === 0)
-        firstStamp = Date.now();
-
-      var elapsed = Date.now() - firstStamp; // milliseconds
-      var min = Math.floor(elapsed / 60000);
-      var sec = (elapsed % 60000) / 1000;
-
-      if (sec < 10)
-        prefix += min + ":0" + sec.toFixed(3) + " | ";
-      else
-        prefix += min + ":" + sec.toFixed(3) + " | ";
-    }
-
-    dump(prefix + str + "\n");
-  }
-}
-
-/** Dumps the current JS stack if DEBUG. */
-function dumpStack()
-{
-  // peel off the frames for dumpStack() and Error()
-  var stack = new Error().stack.split(/\n/).slice(2);
-  stack.forEach(dumpn);
-}
-
-
-/** The XPCOM thread manager. */
-var gThreadManager = null;
-
-/** The XPCOM prefs service. */
-var gRootPrefBranch = null;
-function getRootPrefBranch()
-{
-  if (!gRootPrefBranch)
-  {
-    gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"]
-                        .getService(Ci.nsIPrefBranch);
-  }
-  return gRootPrefBranch;
-}
-
-/**
-* JavaScript constructors for commonly-used classes; precreating these is a
-* speedup over doing the same from base principles. See the docs at
-* http://developer.mozilla.org/en/docs/components.Constructor for details.
-*/
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
-                                 "nsIScriptableInputStream",
-                                 "init");
-const Pipe = CC("@mozilla.org/pipe;1",
-                "nsIPipe",
-                "init");
-const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
-                           "nsIFileInputStream",
-                           "init");
-const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1",
-                                "nsIConverterInputStream",
-                                "init");
-const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
-                               "nsIWritablePropertyBag2");
-const SupportsString = CC("@mozilla.org/supports-string;1",
-                          "nsISupportsString");
-
-/* These two are non-const only so a test can overwrite them. */
-var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
-                            "nsIBinaryOutputStream",
-                            "setOutputStream");
-
-/**
-* Returns the RFC 822/1123 representation of a date.
-*
-* @param date : Number
-* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT
-* @returns string
-* the representation of the given date
-*/
-function toDateString(date)
-{
-  //
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // date1 = 2DIGIT SP month SP 4DIGIT
-  // ; day month year (e.g., 02 Jun 1982)
-  // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  // ; 00:00:00 - 23:59:59
-  // wkday = "Mon" | "Tue" | "Wed"
-  // | "Thu" | "Fri" | "Sat" | "Sun"
-  // month = "Jan" | "Feb" | "Mar" | "Apr"
-  // | "May" | "Jun" | "Jul" | "Aug"
-  // | "Sep" | "Oct" | "Nov" | "Dec"
-  //
-
-  const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-  const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-  /**
-* Processes a date and returns the encoded UTC time as a string according to
-* the format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toTime(date)
-  {
-    var hrs = date.getUTCHours();
-    var rv = (hrs < 10) ? "0" + hrs : hrs;
-
-    var mins = date.getUTCMinutes();
-    rv += ":";
-    rv += (mins < 10) ? "0" + mins : mins;
-
-    var secs = date.getUTCSeconds();
-    rv += ":";
-    rv += (secs < 10) ? "0" + secs : secs;
-
-    return rv;
-  }
-
-  /**
-* Processes a date and returns the encoded UTC date as a string according to
-* the date1 format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toDate1(date)
-  {
-    var day = date.getUTCDate();
-    var month = date.getUTCMonth();
-    var year = date.getUTCFullYear();
-
-    var rv = (day < 10) ? "0" + day : day;
-    rv += " " + monthStrings[month];
-    rv += " " + year;
-
-    return rv;
-  }
-
-  date = new Date(date);
-
-  const fmtString = "%wkday%, %date1% %time% GMT";
-  var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]);
-  rv = rv.replace("%time%", toTime(date));
-  return rv.replace("%date1%", toDate1(date));
-}
-
-/**
-* Prints out a human-readable representation of the object o and its fields,
-* omitting those whose names begin with "_" if showMembers != true (to ignore
-* "private" properties exposed via getters/setters).
-*/
-function printObj(o, showMembers)
-{
-  var s = "******************************\n";
-  s += "o = {\n";
-  for (var i in o)
-  {
-    if (typeof(i) != "string" ||
-        (showMembers || (i.length > 0 && i[0] != "_")))
-      s+= " " + i + ": " + o[i] + ",\n";
-  }
-  s += " };\n";
-  s += "******************************";
-  dumpn(s);
-}
-
-/**
-* Instantiates a new HTTP server.
-*/
-function nsHttpServer()
-{
-  if (!gThreadManager)
-    gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-
-  /** The port on which this server listens. */
-  this._port = undefined;
-
-  /** The socket associated with this. */
-  this._socket = null;
-
-  /** The handler used to process requests to this server. */
-  this._handler = new ServerHandler(this);
-
-  /** Naming information for this server. */
-  this._identity = new ServerIdentity();
-
-  /**
-* Indicates when the server is to be shut down at the end of the request.
-*/
-  this._doQuit = false;
-
-  /**
-* True if the socket in this is closed (and closure notifications have been
-* sent and processed if the socket was ever opened), false otherwise.
-*/
-  this._socketClosed = true;
-
-  /**
-* Used for tracking existing connections and ensuring that all connections
-* are properly cleaned up before server shutdown; increases by 1 for every
-* new incoming connection.
-*/
-  this._connectionGen = 0;
-
-  /**
-* Hash of all open connections, indexed by connection number at time of
-* creation.
-*/
-  this._connections = {};
-}
-nsHttpServer.prototype =
-{
-  classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"),
-
-  // NSISERVERSOCKETLISTENER
-
-  /**
-* Processes an incoming request coming in on the given socket and contained
-* in the given transport.
-*
-* @param socket : nsIServerSocket
-* the socket through which the request was served
-* @param trans : nsISocketTransport
-* the transport for the request/response
-* @see nsIServerSocketListener.onSocketAccepted
-*/
-  onSocketAccepted: function(socket, trans)
-  {
-    dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")");
-
-    dumpn(">>> new connection on " + trans.host + ":" + trans.port);
-
-    const SEGMENT_SIZE = 8192;
-    const SEGMENT_COUNT = 1024;
-    try
-    {
-      var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
-                       .QueryInterface(Ci.nsIAsyncInputStream);
-      var output = trans.openOutputStream(0, 0, 0);
-    }
-    catch (e)
-    {
-      dumpn("*** error opening transport streams: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    var connectionNumber = ++this._connectionGen;
-
-    try
-    {
-      var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
-      var reader = new RequestReader(conn);
-
-      // XXX add request timeout functionality here!
-
-      // Note: must use main thread here, or we might get a GC that will cause
-      // threadsafety assertions. We really need to fix XPConnect so that
-      // you can actually do things in multi-threaded JS. :-(
-      input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
-    }
-    catch (e)
-    {
-      // Assume this connection can't be salvaged and bail on it completely;
-      // don't attempt to close it so that we can assert that any connection
-      // being closed is in this._connections.
-      dumpn("*** error in initial request-processing stages: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    this._connections[connectionNumber] = conn;
-    dumpn("*** starting connection " + connectionNumber);
-  },
-
-  /**
-* Called when the socket associated with this is closed.
-*
-* @param socket : nsIServerSocket
-* the socket being closed
-* @param status : nsresult
-* the reason the socket stopped listening (NS_BINDING_ABORTED if the server
-* was stopped using nsIHttpServer.stop)
-* @see nsIServerSocketListener.onStopListening
-*/
-  onStopListening: function(socket, status)
-  {
-    dumpn(">>> shutting down server on port " + socket.port);
-    this._socketClosed = true;
-    if (!this._hasOpenConnections())
-    {
-      dumpn("*** no open connections, notifying async from onStopListening");
-
-      // Notify asynchronously so that any pending teardown in stop() has a
-      // chance to run first.
-      var self = this;
-      var stopEvent =
-        {
-          run: function()
-          {
-            dumpn("*** _notifyStopped async callback");
-            self._notifyStopped();
-          }
-        };
-      gThreadManager.dispatchToMainThread(stopEvent);
-    }
-  },
-
-  // NSIHTTPSERVER
-
-  //
-  // see nsIHttpServer.start
-  //
-  start: function(port)
-  {
-    this._start(port, "localhost")
-  },
-
-  _start: function(port, host)
-  {
-    if (this._socket)
-      throw Cr.NS_ERROR_ALREADY_INITIALIZED;
-
-    this._port = port;
-    this._doQuit = this._socketClosed = false;
-
-    this._host = host;
-
-    // The listen queue needs to be long enough to handle
-    // network.http.max-persistent-connections-per-server concurrent connections,
-    // plus a safety margin in case some other process is talking to
-    // the server as well.
-    var prefs = getRootPrefBranch();
-    var maxConnections;
-    try {
-      // Bug 776860: The original pref was removed in favor of this new one:
-      maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server") + 5;
-    }
-    catch(e) {
-      maxConnections = prefs.getIntPref("network.http.max-connections-per-server") + 5;
-    }
-
-    try
-    {
-      var loopback = true;
-      if (this._host != "127.0.0.1" && this._host != "localhost") {
-        var loopback = false;
-      }
-
-      var socket = new ServerSocket(this._port,
-                                    loopback, // true = localhost, false = everybody
-                                    maxConnections);
-      dumpn(">>> listening on port " + socket.port + ", " + maxConnections +
-            " pending connections");
-      socket.asyncListen(this);
-      this._identity._initialize(socket.port, host, true);
-      this._socket = socket;
-    }
-    catch (e)
-    {
-      dumpn("!!! could not start server on port " + port + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-  },
-
-  //
-  // see nsIHttpServer.stop
-  //
-  stop: function(callback)
-  {
-    if (!callback)
-      throw Cr.NS_ERROR_NULL_POINTER;
-    if (!this._socket)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    this._stopCallback = typeof callback === "function"
-                       ? callback
-                       : function() { callback.onStopped(); };
-
-    dumpn(">>> stopping listening on port " + this._socket.port);
-    this._socket.close();
-    this._socket = null;
-
-    // We can't have this identity any more, and the port on which we're running
-    // this server now could be meaningless the next time around.
-    this._identity._teardown();
-
-    this._doQuit = false;
-
-    // socket-close notification and pending request completion happen async
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (file && (!file.exists() || file.isDirectory()))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handler.registerFile(path, file);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/" ||
-        path.charAt(path.length - 1) != "/" ||
-        (directory &&
-         (!directory.exists() || !directory.isDirectory())))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping
-    // exists!
-
-    this._handler.registerDirectory(path, directory);
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    this._handler.registerPathHandler(path, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    this._handler.registerPrefixHandler(prefix, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(code, handler)
-  {
-    this._handler.registerErrorHandler(code, handler);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    this._handler.setIndexHandler(handler);
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    this._handler.registerContentType(ext, type);
-  },
-
-  //
-  // see nsIHttpServer.serverIdentity
-  //
-  get identity()
-  {
-    return this._identity;
-  },
-
-  //
-  // see nsIHttpServer.getState
-  //
-  getState: function(path, k)
-  {
-    return this._handler._getState(path, k);
-  },
-
-  //
-  // see nsIHttpServer.setState
-  //
-  setState: function(path, k, v)
-  {
-    return this._handler._setState(path, k, v);
-  },
-
-  //
-  // see nsIHttpServer.getSharedState
-  //
-  getSharedState: function(k)
-  {
-    return this._handler._getSharedState(k);
-  },
-
-  //
-  // see nsIHttpServer.setSharedState
-  //
-  setSharedState: function(k, v)
-  {
-    return this._handler._setSharedState(k, v);
-  },
-
-  //
-  // see nsIHttpServer.getObjectState
-  //
-  getObjectState: function(k)
-  {
-    return this._handler._getObjectState(k);
-  },
-
-  //
-  // see nsIHttpServer.setObjectState
-  //
-  setObjectState: function(k, v)
-  {
-    return this._handler._setObjectState(k, v);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NON-XPCOM PUBLIC API
-
-  /**
-* Returns true iff this server is not running (and is not in the process of
-* serving any requests still to be processed when the server was last
-* stopped after being run).
-*/
-  isStopped: function()
-  {
-    return this._socketClosed && !this._hasOpenConnections();
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /** True if this server has any open connections to it, false otherwise. */
-  _hasOpenConnections: function()
-  {
-    //
-    // If we have any open connections, they're tracked as numeric properties on
-    // |this._connections|. The non-standard __count__ property could be used
-    // to check whether there are any properties, but standard-wise, even
-    // looking forward to ES5, there's no less ugly yet still O(1) way to do
-    // this.
-    //
-    for (var n in this._connections)
-      return true;
-    return false;
-  },
-
-  /** Calls the server-stopped callback provided when stop() was called. */
-  _notifyStopped: function()
-  {
-    NS_ASSERT(this._stopCallback !== null, "double-notifying?");
-    NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now");
-
-    //
-    // NB: We have to grab this now, null out the member, *then* call the
-    // callback here, or otherwise the callback could (indirectly) futz with
-    // this._stopCallback by starting and immediately stopping this, at
-    // which point we'd be nulling out a field we no longer have a right to
-    // modify.
-    //
-    var callback = this._stopCallback;
-    this._stopCallback = null;
-    try
-    {
-      callback();
-    }
-    catch (e)
-    {
-      // not throwing because this is specified as being usually (but not
-      // always) asynchronous
-      dump("!!! error running onStopped callback: " + e + "\n");
-    }
-  },
-
-  /**
-* Notifies this server that the given connection has been closed.
-*
-* @param connection : Connection
-* the connection that was closed
-*/
-  _connectionClosed: function(connection)
-  {
-    NS_ASSERT(connection.number in this._connections,
-              "closing a connection " + this + " that we never added to the " +
-              "set of open connections?");
-    NS_ASSERT(this._connections[connection.number] === connection,
-              "connection number mismatch? " +
-              this._connections[connection.number]);
-    delete this._connections[connection.number];
-
-    // Fire a pending server-stopped notification if it's our responsibility.
-    if (!this._hasOpenConnections() && this._socketClosed)
-      this._notifyStopped();
-  },
-
-  /**
-* Requests that the server be shut down when possible.
-*/
-  _requestQuit: function()
-  {
-    dumpn(">>> requesting a quit");
-    dumpStack();
-    this._doQuit = true;
-  }
-};
-
-
-//
-// RFC 2396 section 3.2.2:
-//
-// host = hostname | IPv4address
-// hostname = *( domainlabel "." ) toplabel [ "." ]
-// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-//
-
-const HOST_REGEX =
-  new RegExp("^(?:" +
-               // *( domainlabel "." )
-               "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
-               // toplabel
-               "[a-z](?:[a-z0-9-]*[a-z0-9])?" +
-             "|" +
-               // IPv4 address
-               "\\d+\\.\\d+\\.\\d+\\.\\d+" +
-             ")$",
-             "i");
-
-
-/**
-* Represents the identity of a server. An identity consists of a set of
-* (scheme, host, port) tuples denoted as locations (allowing a single server to
-* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any
-* host/port). Any incoming request must be to one of these locations, or it
-* will be rejected with an HTTP 400 error. One location, denoted as the
-* primary location, is the location assigned in contexts where a location
-* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests.
-*
-* A single identity may contain at most one location per unique host/port pair;
-* other than that, no restrictions are placed upon what locations may
-* constitute an identity.
-*/
-function ServerIdentity()
-{
-  /** The scheme of the primary location. */
-  this._primaryScheme = "http";
-
-  /** The hostname of the primary location. */
-  this._primaryHost = "127.0.0.1"
-
-  /** The port number of the primary location. */
-  this._primaryPort = -1;
-
-  /**
-* The current port number for the corresponding server, stored so that a new
-* primary location can always be set if the current one is removed.
-*/
-  this._defaultPort = -1;
-
-  /**
-* Maps hosts to maps of ports to schemes, e.g. the following would represent
-* https://example.com:789/ and http://example.org/:
-*
-* {
-* "xexample.com": { 789: "https" },
-* "xexample.org": { 80: "http" }
-* }
-*
-* Note the "x" prefix on hostnames, which prevents collisions with special
-* JS names like "prototype".
-*/
-  this._locations = { "xlocalhost": {} };
-}
-ServerIdentity.prototype =
-{
-  // NSIHTTPSERVERIDENTITY
-
-  //
-  // see nsIHttpServerIdentity.primaryScheme
-  //
-  get primaryScheme()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryScheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryHost
-  //
-  get primaryHost()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryHost;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryPort
-  //
-  get primaryPort()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryPort;
-  },
-
-  //
-  // see nsIHttpServerIdentity.add
-  //
-  add: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      this._locations["x" + host] = entry = {};
-
-    entry[port] = scheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.remove
-  //
-  remove: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return false;
-
-    var present = port in entry;
-    delete entry[port];
-
-    if (this._primaryScheme == scheme &&
-        this._primaryHost == host &&
-        this._primaryPort == port &&
-        this._defaultPort !== -1)
-    {
-      // Always keep at least one identity in existence at any time, unless
-      // we're in the process of shutting down (the last condition above).
-      this._primaryPort = -1;
-      this._initialize(this._defaultPort, host, false);
-    }
-
-    return present;
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  has: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    return "x" + host in this._locations &&
-           scheme === this._locations["x" + host][port];
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  getScheme: function(host, port)
-  {
-    this._validate("http", host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return "";
-
-    return entry[port] || "";
-  },
-
-  //
-  // see nsIHttpServerIdentity.setPrimary
-  //
-  setPrimary: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    this.add(scheme, host, port);
-
-    this._primaryScheme = scheme;
-    this._primaryHost = host;
-    this._primaryPort = port;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Initializes the primary name for the corresponding server, based on the
-* provided port number.
-*/
-  _initialize: function(port, host, addSecondaryDefault)
-  {
-    this._host = host;
-    if (this._primaryPort !== -1)
-      this.add("http", host, port);
-    else
-      this.setPrimary("http", "localhost", port);
-    this._defaultPort = port;
-
-    // Only add this if we're being called at server startup
-    if (addSecondaryDefault && host != "127.0.0.1")
-      this.add("http", "127.0.0.1", port);
-  },
-
-  /**
-* Called at server shutdown time, unsets the primary location only if it was
-* the default-assigned location and removes the default location from the
-* set of locations used.
-*/
-  _teardown: function()
-  {
-    if (this._host != "127.0.0.1") {
-      // Not the default primary location, nothing special to do here
-      this.remove("http", "127.0.0.1", this._defaultPort);
-    }
-
-    // This is a *very* tricky bit of reasoning here; make absolutely sure the
-    // tests for this code pass before you commit changes to it.
-    if (this._primaryScheme == "http" &&
-        this._primaryHost == this._host &&
-        this._primaryPort == this._defaultPort)
-    {
-      // Make sure we don't trigger the readding logic in .remove(), then remove
-      // the default location.
-      var port = this._defaultPort;
-      this._defaultPort = -1;
-      this.remove("http", this._host, port);
-
-      // Ensure a server start triggers the setPrimary() path in ._initialize()
-      this._primaryPort = -1;
-    }
-    else
-    {
-      // No reason not to remove directly as it's not our primary location
-      this.remove("http", this._host, this._defaultPort);
-    }
-  },
-
-  /**
-* Ensures scheme, host, and port are all valid with respect to RFC 2396.
-*
-* @throws NS_ERROR_ILLEGAL_VALUE
-* if any argument doesn't match the corresponding production
-*/
-  _validate: function(scheme, host, port)
-  {
-    if (scheme !== "http" && scheme !== "https")
-    {
-      dumpn("*** server only supports http/https schemes: '" + scheme + "'");
-      dumpStack();
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (!HOST_REGEX.test(host))
-    {
-      dumpn("*** unexpected host: '" + host + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (port < 0 || port > 65535)
-    {
-      dumpn("*** unexpected port: '" + port + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-  }
-};
-
-
-/**
-* Represents a connection to the server (and possibly in the future the thread
-* on which the connection is processed).
-*
-* @param input : nsIInputStream
-* stream from which incoming data on the connection is read
-* @param output : nsIOutputStream
-* stream to write data out the connection
-* @param server : nsHttpServer
-* the server handling the connection
-* @param port : int
-* the port on which the server is running
-* @param outgoingPort : int
-* the outgoing port used by this connection
-* @param number : uint
-* a serial number used to uniquely identify this connection
-*/
-function Connection(input, output, server, port, outgoingPort, number)
-{
-  dumpn("*** opening new connection " + number + " on port " + outgoingPort);
-
-  /** Stream of incoming data. */
-  this.input = input;
-
-  /** Stream for outgoing data. */
-  this.output = output;
-
-  /** The server associated with this request. */
-  this.server = server;
-
-  /** The port on which the server is running. */
-  this.port = port;
-
-  /** The outgoing poort used by this connection. */
-  this._outgoingPort = outgoingPort;
-
-  /** The serial number of this connection. */
-  this.number = number;
-
-  /**
-* The request for which a response is being generated, null if the
-* incoming request has not been fully received or if it had errors.
-*/
-  this.request = null;
-
-  /** State variables for debugging. */
-  this._closed = this._processed = false;
-}
-Connection.prototype =
-{
-  /** Closes this connection's input/output streams. */
-  close: function()
-  {
-    dumpn("*** closing connection " + this.number +
-          " on port " + this._outgoingPort);
-
-    this.input.close();
-    this.output.close();
-    this._closed = true;
-
-    var server = this.server;
-    server._connectionClosed(this);
-
-    // If an error triggered a server shutdown, act on it now
-    if (server._doQuit)
-      server.stop(function() { /* not like we can do anything better */ });
-  },
-
-  /**
-* Initiates processing of this connection, using the data in the given
-* request.
-*
-* @param request : Request
-* the request which should be processed
-*/
-  process: function(request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-
-    this.request = request;
-    this.server._handler.handleResponse(this);
-  },
-
-  /**
-* Initiates processing of this connection, generating a response with the
-* given HTTP error code.
-*
-* @param code : uint
-* an HTTP code, so in the range [0, 1000)
-* @param request : Request
-* incomplete data about the incoming request (since there were errors
-* during its processing
-*/
-  processError: function(code, request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-    this.request = request;
-    this.server._handler.handleError(code, this);
-  },
-
-  /** Converts this to a string for debugging purposes. */
-  toString: function()
-  {
-    return "<Connection(" + this.number +
-           (this.request ? ", " + this.request.path : "") +"): " +
-           (this._closed ? "closed" : "open") + ">";
-  }
-};
-
-
-
-/** Returns an array of count bytes from the given input stream. */
-function readBytes(inputStream, count)
-{
-  return new BinaryInputStream(inputStream).readByteArray(count);
-}
-
-
-
-/** Request reader processing states; see RequestReader for details. */
-const READER_IN_REQUEST_LINE = 0;
-const READER_IN_HEADERS = 1;
-const READER_IN_BODY = 2;
-const READER_FINISHED = 3;
-
-
-/**
-* Reads incoming request data asynchronously, does any necessary preprocessing,
-* and forwards it to the request handler. Processing occurs in three states:
-*
-* READER_IN_REQUEST_LINE Reading the request's status line
-* READER_IN_HEADERS Reading headers in the request
-* READER_IN_BODY Reading the body of the request
-* READER_FINISHED Entire request has been read and processed
-*
-* During the first two stages, initial metadata about the request is gathered
-* into a Request object. Once the status line and headers have been processed,
-* we start processing the body of the request into the Request. Finally, when
-* the entire body has been read, we create a Response and hand it off to the
-* ServerHandler to be given to the appropriate request handler.
-*
-* @param connection : Connection
-* the connection for the request being read
-*/
-function RequestReader(connection)
-{
-  /** Connection metadata for this request. */
-  this._connection = connection;
-
-  /**
-* A container providing line-by-line access to the raw bytes that make up the
-* data which has been read from the connection but has not yet been acted
-* upon (by passing it to the request handler or by extracting request
-* metadata from it).
-*/
-  this._data = new LineData();
-
-  /**
-* The amount of data remaining to be read from the body of this request.
-* After all headers in the request have been read this is the value in the
-* Content-Length header, but as the body is read its value decreases to zero.
-*/
-  this._contentLength = 0;
-
-  /** The current state of parsing the incoming request. */
-  this._state = READER_IN_REQUEST_LINE;
-
-  /** Metadata constructed from the incoming request for the request handler. */
-  this._metadata = new Request(connection.port);
-
-  /**
-* Used to preserve state if we run out of line data midway through a
-* multi-line header. _lastHeaderName stores the name of the header, while
-* _lastHeaderValue stores the value we've seen so far for the header.
-*
-* These fields are always either both undefined or both strings.
-*/
-  this._lastHeaderName = this._lastHeaderValue = undefined;
-}
-RequestReader.prototype =
-{
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Called when more data from the incoming request is available. This method
-* then reads the available data from input and deals with that data as
-* necessary, depending upon the syntax of already-downloaded data.
-*
-* @param input : nsIAsyncInputStream
-* the stream of incoming data from the connection
-*/
-  onInputStreamReady: function(input)
-  {
-    dumpn("*** onInputStreamReady(input=" + input + ") on thread " +
-          gThreadManager.currentThread + " (main is " +
-          gThreadManager.mainThread + ")");
-    dumpn("*** this._state == " + this._state);
-
-    // Handle cases where we get more data after a request error has been
-    // discovered but *before* we can close the connection.
-    var data = this._data;
-    if (!data)
-      return;
-
-    try
-    {
-      data.appendBytes(readBytes(input, input.available()));
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** WARNING: unexpected error when reading from socket; will " +
-              "be treated as if the input stream had been closed");
-        dumpn("*** WARNING: actual error was: " + e);
-      }
-
-      // We've lost a race -- input has been closed, but we're still expecting
-      // to read more data. available() will throw in this case, and since
-      // we're dead in the water now, destroy the connection.
-      dumpn("*** onInputStreamReady called on a closed input, destroying " +
-            "connection");
-      this._connection.close();
-      return;
-    }
-
-    switch (this._state)
-    {
-      default:
-        NS_ASSERT(false, "invalid state: " + this._state);
-        break;
-
-      case READER_IN_REQUEST_LINE:
-        if (!this._processRequestLine())
-          break;
-        /* fall through */
-
-      case READER_IN_HEADERS:
-        if (!this._processHeaders())
-          break;
-        /* fall through */
-
-      case READER_IN_BODY:
-        this._processBody();
-    }
-
-    if (this._state != READER_FINISHED)
-      input.asyncWait(this, 0, 0, gThreadManager.currentThread);
-  },
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(aIID)
-  {
-    if (aIID.equals(Ci.nsIInputStreamCallback) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE API
-
-  /**
-* Processes unprocessed, downloaded data as a request line.
-*
-* @returns boolean
-* true iff the request line has been fully processed
-*/
-  _processRequestLine: function()
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    // Servers SHOULD ignore any empty line(s) received where a Request-Line
-    // is expected (section 4.1).
-    var data = this._data;
-    var line = {};
-    var readSuccess;
-    while ((readSuccess = data.readLine(line)) && line.value == "")
-      dumpn("*** ignoring beginning blank line...");
-
-    // if we don't have a full line, wait until we do
-    if (!readSuccess)
-      return false;
-
-    // we have the first non-blank line
-    try
-    {
-      this._parseRequestLine(line.value);
-      this._state = READER_IN_HEADERS;
-      return true;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing request headers.
-*
-* @returns boolean
-* true iff header data in the request has been fully processed
-*/
-  _processHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    // XXX things to fix here:
-    //
-    // - need to support RFC 2047-encoded non-US-ASCII characters
-
-    try
-    {
-      var done = this._parseHeaders();
-      if (done)
-      {
-        var request = this._metadata;
-
-        // XXX this is wrong for requests with transfer-encodings applied to
-        // them, particularly chunked (which by its nature can have no
-        // meaningful Content-Length header)!
-        this._contentLength = request.hasHeader("Content-Length")
-                            ? parseInt(request.getHeader("Content-Length"), 10)
-                            : 0;
-        dumpn("_processHeaders, Content-length=" + this._contentLength);
-
-        this._state = READER_IN_BODY;
-      }
-      return done;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing the request body.
-*
-* @returns boolean
-* true iff the request body has been fully processed
-*/
-  _processBody: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    // XXX handle chunked transfer-coding request bodies!
-
-    try
-    {
-      if (this._contentLength > 0)
-      {
-        var data = this._data.purge();
-        var count = Math.min(data.length, this._contentLength);
-        dumpn("*** loading data=" + data + " len=" + data.length +
-              " excess=" + (data.length - count));
-
-        var bos = new BinaryOutputStream(this._metadata._bodyOutputStream);
-        bos.writeByteArray(data, count);
-        this._contentLength -= count;
-      }
-
-      dumpn("*** remaining body data len=" + this._contentLength);
-      if (this._contentLength == 0)
-      {
-        this._validateRequest();
-        this._state = READER_FINISHED;
-        this._handleResponse();
-        return true;
-      }
-
-      return false;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Does various post-header checks on the data in this request.
-*
-* @throws : HttpError
-* if the request was malformed in some way
-*/
-  _validateRequest: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    dumpn("*** _validateRequest");
-
-    var metadata = this._metadata;
-    var headers = metadata._headers;
-
-    // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header
-    var identity = this._connection.server.identity;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-    {
-      if (!headers.hasHeader("Host"))
-      {
-        dumpn("*** malformed HTTP/1.1 or greater request with no Host header!");
-        throw HTTP_400;
-      }
-
-      // If the Request-URI wasn't absolute, then we need to determine our host.
-      // We have to determine what scheme was used to access us based on the
-      // server identity data at this point, because the request just doesn't
-      // contain enough data on its own to do this, sadly.
-      if (!metadata._host)
-      {
-        var host, port;
-        var hostPort = headers.getHeader("Host");
-        var colon = hostPort.indexOf(":");
-        if (colon < 0)
-        {
-          host = hostPort;
-          port = "";
-        }
-        else
-        {
-          host = hostPort.substring(0, colon);
-          port = hostPort.substring(colon + 1);
-        }
-
-        // NB: We allow an empty port here because, oddly, a colon may be
-        // present even without a port number, e.g. "example.com:"; in this
-        // case the default port applies.
-        if (!HOST_REGEX.test(host) || !/^\d*$/.test(port))
-        {
-          dumpn("*** malformed hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        // If we're not given a port, we're stuck, because we don't know what
-        // scheme to use to look up the correct port here, in general. Since
-        // the HTTPS case requires a tunnel/proxy and thus requires that the
-        // requested URI be absolute (and thus contain the necessary
-        // information), let's assume HTTP will prevail and use that.
-        port = +port || 80;
-
-        var scheme = identity.getScheme(host, port);
-        if (!scheme)
-        {
-          dumpn("*** unrecognized hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        metadata._scheme = scheme;
-        metadata._host = host;
-        metadata._port = port;
-      }
-    }
-    else
-    {
-      NS_ASSERT(metadata._host === undefined,
-                "HTTP/1.0 doesn't allow absolute paths in the request line!");
-
-      metadata._scheme = identity.primaryScheme;
-      metadata._host = identity.primaryHost;
-      metadata._port = identity.primaryPort;
-    }
-
-    NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port),
-              "must have a location we recognize by now!");
-  },
-
-  /**
-* Handles responses in case of error, either in the server or in the request.
-*
-* @param e
-* the specific error encountered, which is an HttpError in the case where
-* the request is in some way invalid or cannot be fulfilled; if this isn't
-* an HttpError we're going to be paranoid and shut down, because that
-* shouldn't happen, ever
-*/
-  _handleError: function(e)
-  {
-    // Don't fall back into normal processing!
-    this._state = READER_FINISHED;
-
-    var server = this._connection.server;
-    if (e instanceof HttpError)
-    {
-      var code = e.code;
-    }
-    else
-    {
-      dumpn("!!! UNEXPECTED ERROR: " + e +
-            (e.lineNumber ? ", line " + e.lineNumber : ""));
-
-      // no idea what happened -- be paranoid and shut down
-      code = 500;
-      server._requestQuit();
-    }
-
-    // make attempted reuse of data an error
-    this._data = null;
-
-    this._connection.processError(code, this._metadata);
-  },
-
-  /**
-* Now that we've read the request line and headers, we can actually hand off
-* the request to be handled.
-*
-* This method is called once per request, after the request line and all
-* headers and the body, if any, have been received.
-*/
-  _handleResponse: function()
-  {
-    NS_ASSERT(this._state == READER_FINISHED);
-
-    // We don't need the line-based data any more, so make attempted reuse an
-    // error.
-    this._data = null;
-
-    this._connection.process(this._metadata);
-  },
-
-
-  // PARSING
-
-  /**
-* Parses the request line for the HTTP request associated with this.
-*
-* @param line : string
-* the request line
-*/
-  _parseRequestLine: function(line)
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    dumpn("*** _parseRequestLine('" + line + "')");
-
-    var metadata = this._metadata;
-
-    // clients and servers SHOULD accept any amount of SP or HT characters
-    // between fields, even though only a single SP is required (section 19.3)
-    var request = line.split(/[ \t]+/);
-    if (!request || request.length != 3)
-      throw HTTP_400;
-
-    metadata._method = request[0];
-
-    // get the HTTP version
-    var ver = request[2];
-    var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
-    if (!match)
-      throw HTTP_400;
-
-    // determine HTTP version
-    try
-    {
-      metadata._httpVersion = new nsHttpVersion(match[1]);
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
-        throw "unsupported HTTP version";
-    }
-    catch (e)
-    {
-      // we support HTTP/1.0 and HTTP/1.1 only
-      throw HTTP_501;
-    }
-
-
-    var fullPath = request[1];
-    var serverIdentity = this._connection.server.identity;
-
-    var scheme, host, port;
-
-    if (fullPath.charAt(0) != "/")
-    {
-      // No absolute paths in the request line in HTTP prior to 1.1
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-        throw HTTP_400;
-
-      try
-      {
-        var uri = Cc["@mozilla.org/network/io-service;1"]
-                    .getService(Ci.nsIIOService)
-                    .newURI(fullPath);
-        fullPath = uri.pathQueryRef;
-        scheme = uri.scheme;
-        host = metadata._host = uri.asciiHost;
-        port = uri.port;
-        if (port === -1)
-        {
-          if (scheme === "http")
-            port = 80;
-          else if (scheme === "https")
-            port = 443;
-          else
-            throw HTTP_400;
-        }
-      }
-      catch (e)
-      {
-        // If the host is not a valid host on the server, the response MUST be a
-        // 400 (Bad Request) error message (section 5.2). Alternately, the URI
-        // is malformed.
-        throw HTTP_400;
-      }
-
-      if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
-        throw HTTP_400;
-    }
-
-    var splitter = fullPath.indexOf("?");
-    if (splitter < 0)
-    {
-      // _queryString already set in ctor
-      metadata._path = fullPath;
-    }
-    else
-    {
-      metadata._path = fullPath.substring(0, splitter);
-      metadata._queryString = fullPath.substring(splitter + 1);
-    }
-
-    metadata._scheme = scheme;
-    metadata._host = host;
-    metadata._port = port;
-  },
-
-  /**
-* Parses all available HTTP headers in this until the header-ending CRLFCRLF,
-* adding them to the store of headers in the request.
-*
-* @throws
-* HTTP_400 if the headers are malformed
-* @returns boolean
-* true if all headers have now been processed, false otherwise
-*/
-  _parseHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    dumpn("*** _parseHeaders");
-
-    var data = this._data;
-
-    var headers = this._metadata._headers;
-    var lastName = this._lastHeaderName;
-    var lastVal = this._lastHeaderValue;
-
-    var line = {};
-    while (true)
-    {
-      NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
-                lastName === undefined ?
-                  "lastVal without lastName? lastVal: '" + lastVal + "'" :
-                  "lastName without lastVal? lastName: '" + lastName + "'");
-
-      if (!data.readLine(line))
-      {
-        // save any data we have from the header we might still be processing
-        this._lastHeaderName = lastName;
-        this._lastHeaderValue = lastVal;
-        return false;
-      }
-
-      var lineText = line.value;
-      var firstChar = lineText.charAt(0);
-
-      // blank line means end of headers
-      if (lineText == "")
-      {
-        // we're finished with the previous header
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-        else
-        {
-          // no headers in request -- valid for HTTP/1.0 requests
-        }
-
-        // either way, we're done processing headers
-        this._state = READER_IN_BODY;
-        return true;
-      }
-      else if (firstChar == " " || firstChar == "\t")
-      {
-        // multi-line header if we've already seen a header line
-        if (!lastName)
-        {
-          // we don't have a header to continue!
-          throw HTTP_400;
-        }
-
-        // append this line's text to the value; starts with SP/HT, so no need
-        // for separating whitespace
-        lastVal += lineText;
-      }
-      else
-      {
-        // we have a new header, so set the old one (if one existed)
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-
-        var colon = lineText.indexOf(":"); // first colon must be splitter
-        if (colon < 1)
-        {
-          // no colon or missing header field-name
-          throw HTTP_400;
-        }
-
-        // set header name, value (to be set in the next loop, usually)
-        lastName = lineText.substring(0, colon);
-        lastVal = lineText.substring(colon + 1);
-      } // empty, continuation, start of header
-    } // while (true)
-  }
-};
-
-
-/** The character codes for CR and LF. */
-const CR = 0x0D, LF = 0x0A;
-
-/**
-* Calculates the number of characters before the first CRLF pair in array, or
-* -1 if the array contains no CRLF pair.
-*
-* @param array : Array
-* an array of numbers in the range [0, 256), each representing a single
-* character; the first CRLF is the lowest index i where
-* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|,
-* if such an |i| exists, and -1 otherwise
-* @returns int
-* the index of the first CRLF if any were present, -1 otherwise
-*/
-function findCRLF(array)
-{
-  for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1))
-  {
-    if (array[i + 1] == LF)
-      return i;
-  }
-  return -1;
-}
-
-
-/**
-* A container which provides line-by-line access to the arrays of bytes with
-* which it is seeded.
-*/
-function LineData()
-{
-  /** An array of queued bytes from which to get line-based characters. */
-  this._data = [];
-}
-LineData.prototype =
-{
-  /**
-* Appends the bytes in the given array to the internal data cache maintained
-* by this.
-*/
-  appendBytes: function(bytes)
-  {
-    Array.prototype.push.apply(this._data, bytes);
-  },
-
-  /**
-* Removes and returns a line of data, delimited by CRLF, from this.
-*
-* @param out
-* an object whose "value" property will be set to the first line of text
-* present in this, sans CRLF, if this contains a full CRLF-delimited line
-* of text; if this doesn't contain enough data, the value of the property
-* is undefined
-* @returns boolean
-* true if a full line of data could be read from the data in this, false
-* otherwise
-*/
-  readLine: function(out)
-  {
-    var data = this._data;
-    var length = findCRLF(data);
-    if (length < 0)
-      return false;
-
-    //
-    // We have the index of the CR, so remove all the characters, including
-    // CRLF, from the array with splice, and convert the removed array into the
-    // corresponding string, from which we then strip the trailing CRLF.
-    //
-    // Getting the line in this matter acknowledges that substring is an O(1)
-    // operation in SpiderMonkey because strings are immutable, whereas two
-    // splices, both from the beginning of the data, are less likely to be as
-    // cheap as a single splice plus two extra character conversions.
-    //
-    var line = String.fromCharCode.apply(null, data.splice(0, length + 2));
-    out.value = line.substring(0, length);
-
-    return true;
-  },
-
-  /**
-* Removes the bytes currently within this and returns them in an array.
-*
-* @returns Array
-* the bytes within this when this method is called
-*/
-  purge: function()
-  {
-    var data = this._data;
-    this._data = [];
-    return data;
-  }
-};
-
-
-
-/**
-* Creates a request-handling function for an nsIHttpRequestHandler object.
-*/
-function createHandlerFunc(handler)
-{
-  return function(metadata, response) { handler.handle(metadata, response); };
-}
-
-
-/**
-* The default handler for directories; writes an HTML response containing a
-* slightly-formatted directory listing.
-*/
-function defaultIndexHandler(metadata, response)
-{
-  response.setHeader("Content-Type", "text/html", false);
-
-  var path = htmlEscape(decodeURI(metadata.path));
-
-  //
-  // Just do a very basic bit of directory listings -- no need for too much
-  // fanciness, especially since we don't have a style sheet in which we can
-  // stick rules (don't want to pollute the default path-space).
-  //
-
-  var body = '<html>\
-<head>\
-<title>' + path + '</title>\
-</head>\
-<body>\
-<h1>' + path + '</h1>\
-<ol style="list-style-type: none">';
-
-  var directory = metadata.getProperty("directory").QueryInterface(Ci.nsIFile);
-  NS_ASSERT(directory && directory.isDirectory());
-
-  var fileList = [];
-  var files = directory.directoryEntries;
-  while (files.hasMoreElements())
-  {
-    var f = files.getNext().QueryInterface(Ci.nsIFile);
-    var name = f.leafName;
-    if (!f.isHidden() &&
-        (name.charAt(name.length - 1) != HIDDEN_CHAR ||
-         name.charAt(name.length - 2) == HIDDEN_CHAR))
-      fileList.push(f);
-  }
-
-  fileList.sort(fileSort);
-
-  for (var i = 0; i < fileList.length; i++)
-  {
-    var file = fileList[i];
-    try
-    {
-      var name = file.leafName;
-      if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-        name = name.substring(0, name.length - 1);
-      var sep = file.isDirectory() ? "/" : "";
-
-      // Note: using " to delimit the attribute here because encodeURIComponent
-      // passes through '.
-      var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' +
-                   htmlEscape(name) + sep +
-                 '</a></li>';
-
-      body += item;
-    }
-    catch (e) { /* some file system error, ignore the file */ }
-  }
-
-  body += ' </ol>\
-</body>\
-</html>';
-
-  response.bodyOutputStream.write(body, body.length);
-}
-
-/**
-* Sorts a and b (nsIFile objects) into an aesthetically pleasing order.
-*/
-function fileSort(a, b)
-{
-  var dira = a.isDirectory(), dirb = b.isDirectory();
-
-  if (dira && !dirb)
-    return -1;
-  if (dirb && !dira)
-    return 1;
-
-  var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase();
-  return nameb > namea ? -1 : 1;
-}
-
-
-/**
-* Converts an externally-provided path into an internal path for use in
-* determining file mappings.
-*
-* @param path
-* the path to convert
-* @param encoded
-* true if the given path should be passed through decodeURI prior to
-* conversion
-* @throws URIError
-* if path is incorrectly encoded
-*/
-function toInternalPath(path, encoded)
-{
-  if (encoded)
-    path = decodeURI(path);
-
-  var comps = path.split("/");
-  for (var i = 0, sz = comps.length; i < sz; i++)
-  {
-    var comp = comps[i];
-    if (comp.charAt(comp.length - 1) == HIDDEN_CHAR)
-      comps[i] = comp + HIDDEN_CHAR;
-  }
-  return comps.join("/");
-}
-
-
-/**
-* Adds custom-specified headers for the given file to the given response, if
-* any such headers are specified.
-*
-* @param file
-* the file on the disk which is to be written
-* @param metadata
-* metadata about the incoming request
-* @param response
-* the Response to which any specified headers/data should be written
-* @throws HTTP_500
-* if an error occurred while processing custom-specified headers
-*/
-function maybeAddHeaders(file, metadata, response)
-{
-  var name = file.leafName;
-  if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-    name = name.substring(0, name.length - 1);
-
-  var headerFile = file.parent;
-  headerFile.append(name + HEADERS_SUFFIX);
-
-  if (!headerFile.exists())
-    return;
-
-  const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(headerFile, PR_RDONLY, 0o444,
-                                Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-  try
-  {
-    var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0);
-    lis.QueryInterface(Ci.nsIUnicharLineInputStream);
-
-    var line = {value: ""};
-    var more = lis.readLine(line);
-
-    if (!more && line.value == "")
-      return;
-
-
-    // request line
-
-    var status = line.value;
-    if (status.indexOf("HTTP ") == 0)
-    {
-      status = status.substring(5);
-      var space = status.indexOf(" ");
-      var code, description;
-      if (space < 0)
-      {
-        code = status;
-        description = "";
-      }
-      else
-      {
-        code = status.substring(0, space);
-        description = status.substring(space + 1, status.length);
-      }
-
-      response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description);
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-
-    // headers
-    while (more || line.value != "")
-    {
-      var header = line.value;
-      var colon = header.indexOf(":");
-
-      response.setHeader(header.substring(0, colon),
-                         header.substring(colon + 1, header.length),
-                         false); // allow overriding server-set headers
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-  }
-  catch (e)
-  {
-    dumpn("WARNING: error in headers for " + metadata.path + ": " + e);
-    throw HTTP_500;
-  }
-  finally
-  {
-    fis.close();
-  }
-}
-
-
-/**
-* An object which handles requests for a server, executing default and
-* overridden behaviors as instructed by the code which uses and manipulates it.
-* Default behavior includes the paths / and /trace (diagnostics), with some
-* support for HTTP error pages for various codes and fallback to HTTP 500 if
-* those codes fail for any reason.
-*
-* @param server : nsHttpServer
-* the server in which this handler is being used
-*/
-function ServerHandler(server)
-{
-  // FIELDS
-
-  /**
-* The nsHttpServer instance associated with this handler.
-*/
-  this._server = server;
-
-  /**
-* A FileMap object containing the set of path->nsIFile mappings for
-* all directory mappings set in the server (e.g., "/" for /var/www/html/,
-* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2).
-*
-* Note carefully: the leading and trailing "/" in each path (not file) are
-* removed before insertion to simplify the code which uses this. You have
-* been warned!
-*/
-  this._pathDirectoryMap = new FileMap();
-
-  /**
-* Custom request handlers for the server in which this resides. Path-handler
-* pairs are stored as property-value pairs in this property.
-*
-* @see ServerHandler.prototype._defaultPaths
-*/
-  this._overridePaths = {};
-
-  /**
-* Custom request handlers for the server in which this resides. Prefix-handler
-* pairs are stored as property-value pairs in this property.
-*/
-  this._overridePrefixes = {};
-
-  /**
-* Custom request handlers for the error handlers in the server in which this
-* resides. Path-handler pairs are stored as property-value pairs in this
-* property.
-*
-* @see ServerHandler.prototype._defaultErrors
-*/
-  this._overrideErrors = {};
-
-  /**
-* Maps file extensions to their MIME types in the server, overriding any
-* mapping that might or might not exist in the MIME service.
-*/
-  this._mimeMappings = {};
-
-  /**
-* The default handler for requests for directories, used to serve directories
-* when no index file is present.
-*/
-  this._indexHandler = defaultIndexHandler;
-
-  /** Per-path state storage for the server. */
-  this._state = {};
-
-  /** Entire-server state storage. */
-  this._sharedState = {};
-
-  /** Entire-server state storage for nsISupports values. */
-  this._objectState = {};
-}
-ServerHandler.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Handles a request to this server, responding to the request appropriately
-* and initiating server shutdown if necessary.
-*
-* This method never throws an exception.
-*
-* @param connection : Connection
-* the connection for this request
-*/
-  handleResponse: function(connection)
-  {
-    var request = connection.request;
-    var response = new Response(connection);
-
-    var path = request.path;
-    dumpn("*** path == " + path);
-
-    try
-    {
-      try
-      {
-        if (path in this._overridePaths)
-        {
-          // explicit paths first, then files based on existing directory mappings,
-          // then (if the file doesn't exist) built-in server default paths
-          dumpn("calling override for " + path);
-          this._overridePaths[path](request, response);
-        }
-        else
-        {
-          let longestPrefix = "";
-          for (let prefix in this._overridePrefixes)
-          {
-            if (prefix.length > longestPrefix.length && path.startsWith(prefix))
-            {
-              longestPrefix = prefix;
-            }
-          }
-          if (longestPrefix.length > 0)
-          {
-            dumpn("calling prefix override for " + longestPrefix);
-            this._overridePrefixes[longestPrefix](request, response);
-          }
-          else
-          {
-            this._handleDefault(request, response);
-          }
-        }
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        if (!(e instanceof HttpError))
-        {
-          dumpn("*** unexpected error: e == " + e);
-          throw HTTP_500;
-        }
-        if (e.code !== 404)
-          throw e;
-
-        dumpn("*** default: " + (path in this._defaultPaths));
-
-        response = new Response(connection);
-        if (path in this._defaultPaths)
-          this._defaultPaths[path](request, response);
-        else
-          throw HTTP_404;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort(e);
-        return;
-      }
-
-      var errorCode = "internal";
-
-      try
-      {
-        if (!(e instanceof HttpError))
-          throw e;
-
-        errorCode = e.code;
-        dumpn("*** errorCode == " + errorCode);
-
-        response = new Response(connection);
-        if (e.customErrorHandling)
-          e.customErrorHandling(response);
-        this._handleError(errorCode, request, response);
-        return;
-      }
-      catch (e2)
-      {
-        dumpn("*** error handling " + errorCode + " error: " +
-              "e2 == " + e2 + ", shutting down server");
-
-        connection.server._requestQuit();
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (!file)
-    {
-      dumpn("*** unregistering '" + path + "' mapping");
-      delete this._overridePaths[path];
-      return;
-    }
-
-    dumpn("*** registering '" + path + "' as mapping to " + file.path);
-    file = file.clone();
-
-    var self = this;
-    this._overridePaths[path] =
-      function(request, response)
-      {
-        if (!file.exists())
-          throw HTTP_404;
-
-        response.setStatusLine(request.httpVersion, 200, "OK");
-        self._writeFileResponse(request, file, response, 0, file.fileSize);
-      };
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePaths, path);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    // XXX true prefix validation!
-    if (!(prefix.startsWith("/") && prefix.endsWith("/")))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePrefixes, prefix);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // strip off leading and trailing '/' so that we can use lastIndexOf when
-    // determining exactly how a path maps onto a mapped directory --
-    // conditional is required here to deal with "/".substring(1, 0) being
-    // converted to "/".substring(0, 1) per the JS specification
-    var key = path.length == 1 ? "" : path.substring(1, path.length - 1);
-
-    // the path-to-directory mapping code requires that the first character not
-    // be "/", or it will go into an infinite loop
-    if (key.charAt(0) == "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    key = toInternalPath(key, false);
-
-    if (directory)
-    {
-      dumpn("*** mapping '" + path + "' to the location " + directory.path);
-      this._pathDirectoryMap.put(key, directory);
-    }
-    else
-    {
-      dumpn("*** removing mapping for '" + path + "'");
-      this._pathDirectoryMap.put(key, null);
-    }
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(err, handler)
-  {
-    if (!(err in HTTP_ERROR_CODES))
-      dumpn("*** WARNING: registering non-HTTP/1.1 error code " +
-            "(" + err + ") handler -- was this intentional?");
-
-    this._handlerToField(handler, this._overrideErrors, err);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    if (!handler)
-      handler = defaultIndexHandler;
-    else if (typeof(handler) != "function")
-      handler = createHandlerFunc(handler);
-
-    this._indexHandler = handler;
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    if (!type)
-      delete this._mimeMappings[ext];
-    else
-      this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type);
-  },
-
-  // PRIVATE API
-
-  /**
-* Sets or remove (if handler is null) a handler in an object with a key.
-*
-* @param handler
-* a handler, either function or an nsIHttpRequestHandler
-* @param dict
-* The object to attach the handler to.
-* @param key
-* The field name of the handler.
-*/
-  _handlerToField: function(handler, dict, key)
-  {
-    // for convenience, handler can be a function if this is run from xpcshell
-    if (typeof(handler) == "function")
-      dict[key] = handler;
-    else if (handler)
-      dict[key] = createHandlerFunc(handler);
-    else
-      delete dict[key];
-  },
-
-  /**
-* Handles a request which maps to a file in the local filesystem (if a base
-* path has already been set; otherwise the 404 error is thrown).
-*
-* @param metadata : Request
-* metadata for the incoming request
-* @param response : Response
-* an uninitialized Response to the given request, to be initialized by a
-* request handler
-* @throws HTTP_###
-* if an HTTP error occurred (usually HTTP_404); note that in this case the
-* calling code must handle post-processing of the response
-*/
-  _handleDefault: function(metadata, response)
-  {
-    dumpn("*** _handleDefault()");
-
-    response.setStatusLine(metadata.httpVersion, 200, "OK");
-
-    var path = metadata.path;
-    NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">");
-
-    // determine the actual on-disk file; this requires finding the deepest
-    // path-to-directory mapping in the requested URL
-    var file = this._getFileForPath(path);
-
-    // the "file" might be a directory, in which case we either serve the
-    // contained index.html or make the index handler write the response
-    if (file.exists() && file.isDirectory())
-    {
-      file.append("index.html"); // make configurable?
-      if (!file.exists() || file.isDirectory())
-      {
-        metadata._ensurePropertyBag();
-        metadata._bag.setPropertyAsInterface("directory", file.parent);
-        this._indexHandler(metadata, response);
-        return;
-      }
-    }
-
-    // alternately, the file might not exist
-    if (!file.exists())
-      throw HTTP_404;
-
-    var start, end;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
-        metadata.hasHeader("Range") &&
-        this._getTypeFromFile(file) !== SJS_TYPE)
-    {
-      var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
-      if (!rangeMatch)
-        throw HTTP_400;
-
-      if (rangeMatch[1] !== undefined)
-        start = parseInt(rangeMatch[1], 10);
-
-      if (rangeMatch[2] !== undefined)
-        end = parseInt(rangeMatch[2], 10);
-
-      if (start === undefined && end === undefined)
-        throw HTTP_400;
-
-      // No start given, so the end is really the count of bytes from the
-      // end of the file.
-      if (start === undefined)
-      {
-        start = Math.max(0, file.fileSize - end);
-        end = file.fileSize - 1;
-      }
-
-      // start and end are inclusive
-      if (end === undefined || end >= file.fileSize)
-        end = file.fileSize - 1;
-
-      if (start !== undefined && start >= file.fileSize) {
-        var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
-        HTTP_416.customErrorHandling = function(errorResponse)
-        {
-          maybeAddHeaders(file, metadata, errorResponse);
-        };
-        throw HTTP_416;
-      }
-
-      if (end < start)
-      {
-        response.setStatusLine(metadata.httpVersion, 200, "OK");
-        start = 0;
-        end = file.fileSize - 1;
-      }
-      else
-      {
-        response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
-        var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize;
-        response.setHeader("Content-Range", contentRange);
-      }
-    }
-    else
-    {
-      start = 0;
-      end = file.fileSize - 1;
-    }
-
-    // finally...
-    dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " +
-          start + " to " + end + " inclusive");
-    this._writeFileResponse(metadata, file, response, start, end - start + 1);
-  },
-
-  /**
-* Writes an HTTP response for the given file, including setting headers for
-* file metadata.
-*
-* @param metadata : Request
-* the Request for which a response is being generated
-* @param file : nsIFile
-* the file which is to be sent in the response
-* @param response : Response
-* the response to which the file should be written
-* @param offset: uint
-* the byte offset to skip to when writing
-* @param count: uint
-* the number of bytes to write
-*/
-  _writeFileResponse: function(metadata, file, response, offset, count)
-  {
-    const PR_RDONLY = 0x01;
-
-    var type = this._getTypeFromFile(file);
-    if (type === SJS_TYPE)
-    {
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      try
-      {
-        var sis = new ScriptableInputStream(fis);
-        var s = Cu.Sandbox(gGlobalObject);
-        s.importFunction(dump, "dump");
-
-        // Define a basic key-value state-preservation API across requests, with
-        // keys initially corresponding to the empty string.
-        var self = this;
-        var path = metadata.path;
-        s.importFunction(function getState(k)
-        {
-          return self._getState(path, k);
-        });
-        s.importFunction(function setState(k, v)
-        {
-          self._setState(path, k, v);
-        });
-        s.importFunction(function getSharedState(k)
-        {
-          return self._getSharedState(k);
-        });
-        s.importFunction(function setSharedState(k, v)
-        {
-          self._setSharedState(k, v);
-        });
-        s.importFunction(function getObjectState(k, callback)
-        {
-          callback(self._getObjectState(k));
-        });
-        s.importFunction(function setObjectState(k, v)
-        {
-          self._setObjectState(k, v);
-        });
-        s.importFunction(function registerPathHandler(p, h)
-        {
-          self.registerPathHandler(p, h);
-        });
-
-        // Make it possible for sjs files to access their location
-        this._setState(path, "__LOCATION__", file.path);
-
-        try
-        {
-          // Alas, the line number in errors dumped to console when calling the
-          // request handler is simply an offset from where we load the SJS file.
-          // Work around this in a reasonably non-fragile way by dynamically
-          // getting the line number where we evaluate the SJS file. Don't
-          // separate these two lines!
-          var line = new Error().lineNumber;
-          Cu.evalInSandbox(sis.read(file.fileSize), s);
-        }
-        catch (e)
-        {
-          dumpn("*** syntax error in SJS at " + file.path + ": " + e);
-          throw HTTP_500;
-        }
-
-        try
-        {
-          s.handleRequest(metadata, response);
-        }
-        catch (e)
-        {
-          dump("*** error running SJS at " + file.path + ": " +
-               e + " on line " +
-               (e instanceof Error
-               ? e.lineNumber + " in httpd.js"
-               : (e.lineNumber - line)) + "\n");
-          throw HTTP_500;
-        }
-      }
-      finally
-      {
-        fis.close();
-      }
-    }
-    else
-    {
-      try
-      {
-        response.setHeader("Last-Modified",
-                           toDateString(file.lastModifiedTime),
-                           false);
-      }
-      catch (e) { /* lastModifiedTime threw, ignore */ }
-
-      response.setHeader("Content-Type", type, false);
-      maybeAddHeaders(file, metadata, response);
-      response.setHeader("Content-Length", "" + count, false);
-
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      offset = offset || 0;
-      count = count || file.fileSize;
-      NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset");
-      NS_ASSERT(count >= 0, "bad count");
-      NS_ASSERT(offset + count <= file.fileSize, "bad total data size");
-
-      try
-      {
-        if (offset !== 0)
-        {
-          // Seek (or read, if seeking isn't supported) to the correct offset so
-          // the data sent to the client matches the requested range.
-          if (fis instanceof Ci.nsISeekableStream)
-            fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset);
-          else
-            new ScriptableInputStream(fis).read(offset);
-        }
-      }
-      catch (e)
-      {
-        fis.close();
-        throw e;
-      }
-
-      let writeMore = function writeMore()
-      {
-        gThreadManager.dispatchToMainThread(writeData);
-      }
-
-      var input = new BinaryInputStream(fis);
-      var output = new BinaryOutputStream(response.bodyOutputStream);
-      var writeData =
-        {
-          run: function()
-          {
-            var chunkSize = Math.min(65536, count);
-            count -= chunkSize;
-            NS_ASSERT(count >= 0, "underflow");
-
-            try
-            {
-              var data = input.readByteArray(chunkSize);
-              NS_ASSERT(data.length === chunkSize,
-                        "incorrect data returned? got " + data.length +
-                        ", expected " + chunkSize);
-              output.writeByteArray(data, data.length);
-              if (count === 0)
-              {
-                fis.close();
-                response.finish();
-              }
-              else
-              {
-                writeMore();
-              }
-            }
-            catch (e)
-            {
-              try
-              {
-                fis.close();
-              }
-              finally
-              {
-                response.finish();
-              }
-              throw e;
-            }
-          }
-        };
-
-      writeMore();
-
-      // Now that we know copying will start, flag the response as async.
-      response.processAsync();
-    }
-  },
-
-  /**
-* Get the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getState: function(path, k)
-  {
-    var state = this._state;
-    if (path in state && k in state[path])
-      return state[path][k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setState: function(path, k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    var state = this._state;
-    if (!(path in state))
-      state[path] = {};
-    state[path][k] = v;
-  },
-
-  /**
-* Get the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getSharedState: function(k)
-  {
-    var state = this._sharedState;
-    if (k in state)
-      return state[k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setSharedState: function(k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    this._sharedState[k] = v;
-  },
-
-  /**
-* Returns the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be returned
-* @returns nsISupports
-* the corresponding object, or null if none was present
-*/
-  _getObjectState: function(k)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    return this._objectState[k] || null;
-  },
-
-  /**
-* Sets the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be set
-* @param v : nsISupports
-* the object to be associated with the given key; may be null
-*/
-  _setObjectState: function(k, v)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    if (typeof v !== "object")
-      throw new Error("non-object value passed");
-    if (v && !("QueryInterface" in v))
-    {
-      throw new Error("must pass an nsISupports; use wrappedJSObject to ease " +
-                      "pain when using the server from JS");
-    }
-
-    this._objectState[k] = v;
-  },
-
-  /**
-* Gets a content-type for the given file, first by checking for any custom
-* MIME-types registered with this handler for the file's extension, second by
-* asking the global MIME service for a content-type, and finally by failing
-* over to application/octet-stream.
-*
-* @param file : nsIFile
-* the nsIFile for which to get a file type
-* @returns string
-* the best content-type which can be determined for the file
-*/
-  _getTypeFromFile: function(file)
-  {
-    try
-    {
-      var name = file.leafName;
-      var dot = name.lastIndexOf(".");
-      if (dot > 0)
-      {
-        var ext = name.slice(dot + 1);
-        if (ext in this._mimeMappings)
-          return this._mimeMappings[ext];
-      }
-      return Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
-               .getService(Ci.nsIMIMEService)
-               .getTypeFromFile(file);
-    }
-    catch (e)
-    {
-      return "application/octet-stream";
-    }
-  },
-
-  /**
-* Returns the nsIFile which corresponds to the path, as determined using
-* all registered path->directory mappings and any paths which are explicitly
-* overridden.
-*
-* @param path : string
-* the server path for which a file should be retrieved, e.g. "/foo/bar"
-* @throws HttpError
-* when the correct action is the corresponding HTTP error (i.e., because no
-* mapping was found for a directory in path, the referenced file doesn't
-* exist, etc.)
-* @returns nsIFile
-* the file to be sent as the response to a request for the path
-*/
-  _getFileForPath: function(path)
-  {
-    // decode and add underscores as necessary
-    try
-    {
-      path = toInternalPath(path, true);
-    }
-    catch (e)
-    {
-      throw HTTP_400; // malformed path
-    }
-
-    // next, get the directory which contains this path
-    var pathMap = this._pathDirectoryMap;
-
-    // An example progression of tmp for a path "/foo/bar/baz/" might be:
-    // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
-    var tmp = path.substring(1);
-    while (true)
-    {
-      // do we have a match for current head of the path?
-      var file = pathMap.get(tmp);
-      if (file)
-      {
-        // XXX hack; basically disable showing mapping for /foo/bar/ when the
-        // requested path was /foo/bar, because relative links on the page
-        // will all be incorrect -- we really need the ability to easily
-        // redirect here instead
-        if (tmp == path.substring(1) &&
-            tmp.length != 0 &&
-            tmp.charAt(tmp.length - 1) != "/")
-          file = null;
-        else
-          break;
-      }
-
-      // if we've finished trying all prefixes, exit
-      if (tmp == "")
-        break;
-
-      tmp = tmp.substring(0, tmp.lastIndexOf("/"));
-    }
-
-    // no mapping applies, so 404
-    if (!file)
-      throw HTTP_404;
-
-
-    // last, get the file for the path within the determined directory
-    var parentFolder = file.parent;
-    var dirIsRoot = (parentFolder == null);
-
-    // Strategy here is to append components individually, making sure we
-    // never move above the given directory; this allows paths such as
-    // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling";
-    // this component-wise approach also means the code works even on platforms
-    // which don't use "/" as the directory separator, such as Windows
-    var leafPath = path.substring(tmp.length + 1);
-    var comps = leafPath.split("/");
-    for (var i = 0, sz = comps.length; i < sz; i++)
-    {
-      var comp = comps[i];
-
-      if (comp == "..")
-        file = file.parent;
-      else if (comp == "." || comp == "")
-        continue;
-      else
-        file.append(comp);
-
-      if (!dirIsRoot && file.equals(parentFolder))
-        throw HTTP_403;
-    }
-
-    return file;
-  },
-
-  /**
-* Writes the error page for the given HTTP error code over the given
-* connection.
-*
-* @param errorCode : uint
-* the HTTP error code to be used
-* @param connection : Connection
-* the connection on which the error occurred
-*/
-  handleError: function(errorCode, connection)
-  {
-    var response = new Response(connection);
-
-    dumpn("*** error in request: " + errorCode);
-
-    this._handleError(errorCode, new Request(connection.port), response);
-  },
-
-  /**
-* Handles a request which generates the given error code, using the
-* user-defined error handler if one has been set, gracefully falling back to
-* the x00 status code if the code has no handler, and failing to status code
-* 500 if all else fails.
-*
-* @param errorCode : uint
-* the HTTP error which is to be returned
-* @param metadata : Request
-* metadata for the request, which will often be incomplete since this is an
-* error
-* @param response : Response
-* an uninitialized Response should be initialized when this method
-* completes with information which represents the desired error code in the
-* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a
-* fallback for 505, per HTTP specs)
-*/
-  _handleError: function(errorCode, metadata, response)
-  {
-    if (!metadata)
-      throw Cr.NS_ERROR_NULL_POINTER;
-
-    var errorX00 = errorCode - (errorCode % 100);
-
-    try
-    {
-      if (!(errorCode in HTTP_ERROR_CODES))
-        dumpn("*** WARNING: requested invalid error: " + errorCode);
-
-      // RFC 2616 says that we should try to handle an error by its class if we
-      // can't otherwise handle it -- if that fails, we revert to handling it as
-      // a 500 internal server error, and if that fails we throw and shut down
-      // the server
-
-      // actually handle the error
-      try
-      {
-        if (errorCode in this._overrideErrors)
-          this._overrideErrors[errorCode](metadata, response);
-        else
-          this._defaultErrors[errorCode](metadata, response);
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        // don't retry the handler that threw
-        if (errorX00 == errorCode)
-          throw HTTP_500;
-
-        dumpn("*** error in handling for error code " + errorCode + ", " +
-              "falling back to " + errorX00 + "...");
-        response = new Response(response._connection);
-        if (errorX00 in this._overrideErrors)
-          this._overrideErrors[errorX00](metadata, response);
-        else if (errorX00 in this._defaultErrors)
-          this._defaultErrors[errorX00](metadata, response);
-        else
-          throw HTTP_500;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort();
-        return;
-      }
-
-      // we've tried everything possible for a meaningful error -- now try 500
-      dumpn("*** error in handling for error code " + errorX00 + ", falling " +
-            "back to 500...");
-
-      try
-      {
-        response = new Response(response._connection);
-        if (500 in this._overrideErrors)
-          this._overrideErrors[500](metadata, response);
-        else
-          this._defaultErrors[500](metadata, response);
-      }
-      catch (e2)
-      {
-        dumpn("*** multiple errors in default error handlers!");
-        dumpn("*** e == " + e + ", e2 == " + e2);
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  // FIELDS
-
-  /**
-* This object contains the default handlers for the various HTTP error codes.
-*/
-  _defaultErrors:
-  {
-    400: function(metadata, response)
-    {
-      // none of the data in metadata is reliable, so hard-code everything here
-      response.setStatusLine("1.1", 400, "Bad Request");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Bad request\n";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    403: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 403, "Forbidden");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>403 Forbidden</title></head>\
-<body>\
-<h1>403 Forbidden</h1>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    404: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 404, "Not Found");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>404 Not Found</title></head>\
-<body>\
-<h1>404 Not Found</h1>\
-<p>\
-<span style='font-family: monospace;'>" +
-                          htmlEscape(metadata.path) +
-                       "</span> was not found.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    416: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                            416,
-                            "Requested Range Not Satisfiable");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head>\
-<title>416 Requested Range Not Satisfiable</title></head>\
-<body>\
-<h1>416 Requested Range Not Satisfiable</h1>\
-<p>The byte range was not valid for the\
-requested resource.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    500: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                             500,
-                             "Internal Server Error");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>500 Internal Server Error</title></head>\
-<body>\
-<h1>500 Internal Server Error</h1>\
-<p>Something's broken in this server and\
-needs to be fixed.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    501: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 501, "Not Implemented");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>501 Not Implemented</title></head>\
-<body>\
-<h1>501 Not Implemented</h1>\
-<p>This server is not (yet) Apache.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    505: function(metadata, response)
-    {
-      response.setStatusLine("1.1", 505, "HTTP Version Not Supported");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>505 HTTP Version Not Supported</title></head>\
-<body>\
-<h1>505 HTTP Version Not Supported</h1>\
-<p>This server only supports HTTP/1.0 and HTTP/1.1\
-connections.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    }
-  },
-
-  /**
-* Contains handlers for the default set of URIs contained in this server.
-*/
-  _defaultPaths:
-  {
-    "/": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>httpd.js</title></head>\
-<body>\
-<h1>httpd.js</h1>\
-<p>If you're seeing this page, httpd.js is up and\
-serving requests! Now set a base path and serve some\
-files!</p>\
-</body>\
-</html>";
-
-      response.bodyOutputStream.write(body, body.length);
-    },
-
-    "/trace": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Request-URI: " +
-                 metadata.scheme + "://" + metadata.host + ":" + metadata.port +
-                 metadata.path + "\n\n";
-      body += "Request (semantically equivalent, slightly reformatted):\n\n";
-      body += metadata.method + " " + metadata.path;
-
-      if (metadata.queryString)
-        body += "?" + metadata.queryString;
-
-      body += " HTTP/" + metadata.httpVersion + "\r\n";
-
-      var headEnum = metadata.headers;
-      while (headEnum.hasMoreElements())
-      {
-        var fieldName = headEnum.getNext()
-                                .QueryInterface(Ci.nsISupportsString)
-                                .data;
-        body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n";
-      }
-
-      response.bodyOutputStream.write(body, body.length);
-    }
-  }
-};
-
-
-/**
-* Maps absolute paths to files on the local file system (as nsILocalFiles).
-*/
-function FileMap()
-{
-  /** Hash which will map paths to nsILocalFiles. */
-  this._map = {};
-}
-FileMap.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Maps key to a clone of the nsIFile value if value is non-null;
-* otherwise, removes any extant mapping for key.
-*
-* @param key : string
-* string to which a clone of value is mapped
-* @param value : nsIFile
-* the file to map to key, or null to remove a mapping
-*/
-  put: function(key, value)
-  {
-    if (value)
-      this._map[key] = value.clone();
-    else
-      delete this._map[key];
-  },
-
-  /**
-* Returns a clone of the nsIFile mapped to key, or null if no such
-* mapping exists.
-*
-* @param key : string
-* key to which the returned file maps
-* @returns nsIFile
-* a clone of the mapped file, or null if no mapping exists
-*/
-  get: function(key)
-  {
-    var val = this._map[key];
-    return val ? val.clone() : null;
-  }
-};
-
-
-// Response CONSTANTS
-
-// token = *<any CHAR except CTLs or separators>
-// CHAR = <any US-ASCII character (0-127)>
-// CTL = <any US-ASCII control character (0-31) and DEL (127)>
-// separators = "(" | ")" | "<" | ">" | "@"
-// | "," | ";" | ":" | "\" | <">
-// | "/" | "[" | "]" | "?" | "="
-// | "{" | "}" | SP | HT
-const IS_TOKEN_ARRAY =
-  [0, 0, 0, 0, 0, 0, 0, 0, // 0
-   0, 0, 0, 0, 0, 0, 0, 0, // 8
-   0, 0, 0, 0, 0, 0, 0, 0, // 16
-   0, 0, 0, 0, 0, 0, 0, 0, // 24
-
-   0, 1, 0, 1, 1, 1, 1, 1, // 32
-   0, 0, 1, 1, 0, 1, 1, 0, // 40
-   1, 1, 1, 1, 1, 1, 1, 1, // 48
-   1, 1, 0, 0, 0, 0, 0, 0, // 56
-
-   0, 1, 1, 1, 1, 1, 1, 1, // 64
-   1, 1, 1, 1, 1, 1, 1, 1, // 72
-   1, 1, 1, 1, 1, 1, 1, 1, // 80
-   1, 1, 1, 0, 0, 0, 1, 1, // 88
-
-   1, 1, 1, 1, 1, 1, 1, 1, // 96
-   1, 1, 1, 1, 1, 1, 1, 1, // 104
-   1, 1, 1, 1, 1, 1, 1, 1, // 112
-   1, 1, 1, 0, 1, 0, 1]; // 120
-
-
-/**
-* Determines whether the given character code is a CTL.
-*
-* @param code : uint
-* the character code
-* @returns boolean
-* true if code is a CTL, false otherwise
-*/
-function isCTL(code)
-{
-  return (code >= 0 && code <= 31) || (code == 127);
-}
-
-/**
-* Represents a response to an HTTP request, encapsulating all details of that
-* response. This includes all headers, the HTTP version, status code and
-* explanation, and the entity itself.
-*
-* @param connection : Connection
-* the connection over which this response is to be written
-*/
-function Response(connection)
-{
-  /** The connection over which this response will be written. */
-  this._connection = connection;
-
-  /**
-* The HTTP version of this response; defaults to 1.1 if not set by the
-* handler.
-*/
-  this._httpVersion = nsHttpVersion.HTTP_1_1;
-
-  /**
-* The HTTP code of this response; defaults to 200.
-*/
-  this._httpCode = 200;
-
-  /**
-* The description of the HTTP code in this response; defaults to "OK".
-*/
-  this._httpDescription = "OK";
-
-  /**
-* An nsIHttpHeaders object in which the headers in this response should be
-* stored. This property is null after the status line and headers have been
-* written to the network, and it may be modified up until it is cleared,
-* except if this._finished is set first (in which case headers are written
-* asynchronously in response to a finish() call not preceded by
-* flushHeaders()).
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* Set to true when this response is ended (completely constructed if possible
-* and the connection closed); further actions on this will then fail.
-*/
-  this._ended = false;
-
-  /**
-* A stream used to hold data written to the body of this response.
-*/
-  this._bodyOutputStream = null;
-
-  /**
-* A stream containing all data that has been written to the body of this
-* response so far. (Async handlers make the data contained in this
-* unreliable as a way of determining content length in general, but auxiliary
-* saved information can sometimes be used to guarantee reliability.)
-*/
-  this._bodyInputStream = null;
-
-  /**
-* A stream copier which copies data to the network. It is initially null
-* until replaced with a copier for response headers; when headers have been
-* fully sent it is replaced with a copier for the response body, remaining
-* so for the duration of response processing.
-*/
-  this._asyncCopier = null;
-
-  /**
-* True if this response has been designated as being processed
-* asynchronously rather than for the duration of a single call to
-* nsIHttpRequestHandler.handle.
-*/
-  this._processAsync = false;
-
-  /**
-* True iff finish() has been called on this, signaling that no more changes
-* to this may be made.
-*/
-  this._finished = false;
-
-  /**
-* True iff powerSeized() has been called on this, signaling that this
-* response is to be handled manually by the response handler (which may then
-* send arbitrary data in response, even non-HTTP responses).
-*/
-  this._powerSeized = false;
-}
-Response.prototype =
-{
-  // PUBLIC CONSTRUCTION API
-
-  //
-  // see nsIHttpResponse.bodyOutputStream
-  //
-  get bodyOutputStream()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    if (!this._bodyOutputStream)
-    {
-      var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX,
-                          null);
-      this._bodyOutputStream = pipe.outputStream;
-      this._bodyInputStream = pipe.inputStream;
-      if (this._processAsync || this._powerSeized)
-        this._startAsyncProcessor();
-    }
-
-    return this._bodyOutputStream;
-  },
-
-  //
-  // see nsIHttpResponse.write
-  //
-  write: function(data)
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    var dataAsString = String(data);
-    this.bodyOutputStream.write(dataAsString, dataAsString.length);
-  },
-
-  //
-  // see nsIHttpResponse.setStatusLine
-  //
-  setStatusLine: function(httpVersion, code, description)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    if (!(code >= 0 && code < 1000))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    try
-    {
-      var httpVer;
-      // avoid version construction for the most common cases
-      if (!httpVersion || httpVersion == "1.1")
-        httpVer = nsHttpVersion.HTTP_1_1;
-      else if (httpVersion == "1.0")
-        httpVer = nsHttpVersion.HTTP_1_0;
-      else
-        httpVer = new nsHttpVersion(httpVersion);
-    }
-    catch (e)
-    {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    // Reason-Phrase = *<TEXT, excluding CR, LF>
-    // TEXT = <any OCTET except CTLs, but including LWS>
-    //
-    // XXX this ends up disallowing octets which aren't Unicode, I think -- not
-    // much to do if description is IDL'd as string
-    if (!description)
-      description = "";
-    for (var i = 0; i < description.length; i++)
-      if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t")
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // set the values only after validation to preserve atomicity
-    this._httpDescription = description;
-    this._httpCode = code;
-    this._httpVersion = httpVer;
-  },
-
-  //
-  // see nsIHttpResponse.setHeader
-  //
-  setHeader: function(name, value, merge)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    this._headers.setHeader(name, value, merge);
-  },
-
-  //
-  // see nsIHttpResponse.processAsync
-  //
-  processAsync: function()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._processAsync)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** processing connection " + this._connection.number + " async");
-    this._processAsync = true;
-
-    /*
-* Either the bodyOutputStream getter or this method is responsible for
-* starting the asynchronous processor and catching writes of data to the
-* response body of async responses as they happen, for the purpose of
-* forwarding those writes to the actual connection's output stream.
-* If bodyOutputStream is accessed first, calling this method will create
-* the processor (when it first is clear that body data is to be written
-* immediately, not buffered). If this method is called first, accessing
-* bodyOutputStream will create the processor. If only this method is
-* called, we'll write nothing, neither headers nor the nonexistent body,
-* until finish() is called. Since that delay is easily avoided by simply
-* getting bodyOutputStream or calling write(""), we don't worry about it.
-*/
-    if (this._bodyOutputStream && !this._asyncCopier)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.seizePower
-  //
-  seizePower: function()
-  {
-    if (this._processAsync)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** forcefully seizing power over connection " +
-          this._connection.number + "...");
-
-    // Purge any already-written data without sending it. We could as easily
-    // swap out the streams entirely, but that makes it possible to acquire and
-    // unknowingly use a stale reference, so we require there only be one of
-    // each stream ever for any response to avoid this complication.
-    if (this._asyncCopier)
-      this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED);
-    this._asyncCopier = null;
-    if (this._bodyOutputStream)
-    {
-      var input = new BinaryInputStream(this._bodyInputStream);
-      var avail;
-      while ((avail = input.available()) > 0)
-        input.readByteArray(avail);
-    }
-
-    this._powerSeized = true;
-    if (this._bodyOutputStream)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.finish
-  //
-  finish: function()
-  {
-    if (!this._processAsync && !this._powerSeized)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._finished)
-      return;
-
-    dumpn("*** finishing connection " + this._connection.number);
-    this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-    this._finished = true;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // POST-CONSTRUCTION API (not exposed externally)
-
-  /**
-* The HTTP version number of this, as a string (e.g. "1.1").
-*/
-  get httpVersion()
-  {
-    this._ensureAlive();
-    return this._httpVersion.toString();
-  },
-
-  /**
-* The HTTP status code of this response, as a string of three characters per
-* RFC 2616.
-*/
-  get httpCode()
-  {
-    this._ensureAlive();
-
-    var codeString = (this._httpCode < 10 ? "0" : "") +
-                     (this._httpCode < 100 ? "0" : "") +
-                     this._httpCode;
-    return codeString;
-  },
-
-  /**
-* The description of the HTTP status code of this response, or "" if none is
-* set.
-*/
-  get httpDescription()
-  {
-    this._ensureAlive();
-
-    return this._httpDescription;
-  },
-
-  /**
-* The headers in this response, as an nsHttpHeaders object.
-*/
-  get headers()
-  {
-    this._ensureAlive();
-
-    return this._headers;
-  },
-
-  //
-  // see nsHttpHeaders.getHeader
-  //
-  getHeader: function(name)
-  {
-    this._ensureAlive();
-
-    return this._headers.getHeader(name);
-  },
-
-  /**
-* Determines whether this response may be abandoned in favor of a newly
-* constructed response. A response may be abandoned only if it is not being
-* sent asynchronously and if raw control over it has not been taken from the
-* server.
-*
-* @returns boolean
-* true iff no data has been written to the network
-*/
-  partiallySent: function()
-  {
-    dumpn("*** partiallySent()");
-    return this._processAsync || this._powerSeized;
-  },
-
-  /**
-* If necessary, kicks off the remaining request processing needed to be done
-* after a request handler performs its initial work upon this response.
-*/
-  complete: function()
-  {
-    dumpn("*** complete()");
-    if (this._processAsync || this._powerSeized)
-    {
-      NS_ASSERT(this._processAsync ^ this._powerSeized,
-                "can't both send async and relinquish power");
-      return;
-    }
-
-    NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?");
-
-    this._startAsyncProcessor();
-
-    // Now make sure we finish processing this request!
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-  },
-
-  /**
-* Abruptly ends processing of this response, usually due to an error in an
-* incoming request but potentially due to a bad error handler. Since we
-* cannot handle the error in the usual way (giving an HTTP error page in
-* response) because data may already have been sent (or because the response
-* might be expected to have been generated asynchronously or completely from
-* scratch by the handler), we stop processing this response and abruptly
-* close the connection.
-*
-* @param e : Error
-* the exception which precipitated this abort, or null if no such exception
-* was generated
-*/
-  abort: function(e)
-  {
-    dumpn("*** abort(<" + e + ">)");
-
-    // This response will be ended by the processor if one was created.
-    var copier = this._asyncCopier;
-    if (copier)
-    {
-      // We dispatch asynchronously here so that any pending writes of data to
-      // the connection will be deterministically written. This makes it easier
-      // to specify exact behavior, and it makes observable behavior more
-      // predictable for clients. Note that the correctness of this depends on
-      // callbacks in response to _waitToReadData in WriteThroughCopier
-      // happening asynchronously with respect to the actual writing of data to
-      // bodyOutputStream, as they currently do; if they happened synchronously,
-      // an event which ran before this one could write more data to the
-      // response body before we get around to canceling the copier. We have
-      // tests for this in test_seizepower.js, however, and I can't think of a
-      // way to handle both cases without removing bodyOutputStream access and
-      // moving its effective write(data, length) method onto Response, which
-      // would be slower and require more code than this anyway.
-      gThreadManager.dispatchToMainThread({
-        run: function()
-        {
-          dumpn("*** canceling copy asynchronously...");
-          copier.cancel(Cr.NS_ERROR_UNEXPECTED);
-        }
-      });
-    }
-    else
-    {
-      this.end();
-    }
-  },
-
-  /**
-* Closes this response's network connection, marks the response as finished,
-* and notifies the server handler that the request is done being processed.
-*/
-  end: function()
-  {
-    NS_ASSERT(!this._ended, "ending this response twice?!?!");
-
-    this._connection.close();
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-
-    this._finished = true;
-    this._ended = true;
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Sends the status line and headers of this response if they haven't been
-* sent and initiates the process of copying data written to this response's
-* body to the network.
-*/
-  _startAsyncProcessor: function()
-  {
-    dumpn("*** _startAsyncProcessor()");
-
-    // Handle cases where we're being called a second time. The former case
-    // happens when this is triggered both by complete() and by processAsync(),
-    // while the latter happens when processAsync() in conjunction with sent
-    // data causes abort() to be called.
-    if (this._asyncCopier || this._ended)
-    {
-      dumpn("*** ignoring second call to _startAsyncProcessor");
-      return;
-    }
-
-    // Send headers if they haven't been sent already and should be sent, then
-    // asynchronously continue to send the body.
-    if (this._headers && !this._powerSeized)
-    {
-      this._sendHeaders();
-      return;
-    }
-
-    this._headers = null;
-    this._sendBody();
-  },
-
-  /**
-* Signals that all modifications to the response status line and headers are
-* complete and then sends that data over the network to the client. Once
-* this method completes, a different response to the request that resulted
-* in this response cannot be sent -- the only possible action in case of
-* error is to abort the response and close the connection.
-*/
-  _sendHeaders: function()
-  {
-    dumpn("*** _sendHeaders()");
-
-    NS_ASSERT(this._headers);
-    NS_ASSERT(!this._powerSeized);
-
-    // request-line
-    var statusLine = "HTTP/" + this.httpVersion + " " +
-                     this.httpCode + " " +
-                     this.httpDescription + "\r\n";
-
-    // header post-processing
-
-    var headers = this._headers;
-    headers.setHeader("Connection", "close", false);
-    headers.setHeader("Server", "httpd.js", false);
-    if (!headers.hasHeader("Date"))
-      headers.setHeader("Date", toDateString(Date.now()), false);
-
-    // Any response not being processed asynchronously must have an associated
-    // Content-Length header for reasons of backwards compatibility with the
-    // initial server, which fully buffered every response before sending it.
-    // Beyond that, however, it's good to do this anyway because otherwise it's
-    // impossible to test behaviors that depend on the presence or absence of a
-    // Content-Length header.
-    if (!this._processAsync)
-    {
-      dumpn("*** non-async response, set Content-Length");
-
-      var bodyStream = this._bodyInputStream;
-      var avail = bodyStream ? bodyStream.available() : 0;
-
-      // XXX assumes stream will always report the full amount of data available
-      headers.setHeader("Content-Length", "" + avail, false);
-    }
-
-
-    // construct and send response
-    dumpn("*** header post-processing completed, sending response head...");
-
-    // request-line
-    var preambleData = [statusLine];
-
-    // headers
-    var headEnum = headers.enumerator;
-    while (headEnum.hasMoreElements())
-    {
-      var fieldName = headEnum.getNext()
-                              .QueryInterface(Ci.nsISupportsString)
-                              .data;
-      var values = headers.getHeaderValues(fieldName);
-      for (var i = 0, sz = values.length; i < sz; i++)
-        preambleData.push(fieldName + ": " + values[i] + "\r\n");
-    }
-
-    // end request-line/headers
-    preambleData.push("\r\n");
-
-    var preamble = preambleData.join("");
-
-    var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null);
-    responseHeadPipe.outputStream.write(preamble, preamble.length);
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, cx)
-        {
-          dumpn("*** preamble copying started");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** preamble copying complete " +
-                "[status=0x" + statusCode.toString(16) + "]");
-
-          if (!components.isSuccessCode(statusCode))
-          {
-            dumpn("!!! header copying problems: non-success statusCode, " +
-                  "ending response");
-
-            response.end();
-          }
-          else
-          {
-            response._sendBody();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    var headerCopier = this._asyncCopier =
-      new WriteThroughCopier(responseHeadPipe.inputStream,
-                             this._connection.output,
-                             copyObserver, null);
-
-    responseHeadPipe.outputStream.close();
-
-    // Forbid setting any more headers or modifying the request line.
-    this._headers = null;
-  },
-
-  /**
-* Asynchronously writes the body of the response (or the entire response, if
-* seizePower() has been called) to the network.
-*/
-  _sendBody: function()
-  {
-    dumpn("*** _sendBody");
-
-    NS_ASSERT(!this._headers, "still have headers around but sending body?");
-
-    // If no body data was written, we're done
-    if (!this._bodyInputStream)
-    {
-      dumpn("*** empty body, response finished");
-      this.end();
-      return;
-    }
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, context)
-        {
-          dumpn("*** onStartRequest");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]");
-
-          if (statusCode === Cr.NS_BINDING_ABORTED)
-          {
-            dumpn("*** terminating copy observer without ending the response");
-          }
-          else
-          {
-            if (!components.isSuccessCode(statusCode))
-              dumpn("*** WARNING: non-success statusCode in onStopRequest");
-
-            response.end();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    dumpn("*** starting async copier of body data...");
-    this._asyncCopier =
-      new WriteThroughCopier(this._bodyInputStream, this._connection.output,
-                            copyObserver, null);
-  },
-
-  /** Ensures that this hasn't been ended. */
-  _ensureAlive: function()
-  {
-    NS_ASSERT(!this._ended, "not handling response lifetime correctly");
-  }
-};
-
-/**
-* Size of the segments in the buffer used in storing response data and writing
-* it to the socket.
-*/
-Response.SEGMENT_SIZE = 8192;
-
-/** Serves double duty in WriteThroughCopier implementation. */
-function notImplemented()
-{
-  throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/** Returns true iff the given exception represents stream closure. */
-function streamClosed(e)
-{
-  return e === Cr.NS_BASE_STREAM_CLOSED ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED);
-}
-
-/** Returns true iff the given exception represents a blocked stream. */
-function wouldBlock(e)
-{
-  return e === Cr.NS_BASE_STREAM_WOULD_BLOCK ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK);
-}
-
-/**
-* Copies data from source to sink as it becomes available, when that data can
-* be written to sink without blocking.
-*
-* @param source : nsIAsyncInputStream
-* the stream from which data is to be read
-* @param sink : nsIAsyncOutputStream
-* the stream to which data is to be copied
-* @param observer : nsIRequestObserver
-* an observer which will be notified when the copy starts and finishes
-* @param context : nsISupports
-* context passed to observer when notified of start/stop
-* @throws NS_ERROR_NULL_POINTER
-* if source, sink, or observer are null
-*/
-function WriteThroughCopier(source, sink, observer, context)
-{
-  if (!source || !sink || !observer)
-    throw Cr.NS_ERROR_NULL_POINTER;
-
-  /** Stream from which data is being read. */
-  this._source = source;
-
-  /** Stream to which data is being written. */
-  this._sink = sink;
-
-  /** Observer watching this copy. */
-  this._observer = observer;
-
-  /** Context for the observer watching this. */
-  this._context = context;
-
-  /**
-* True iff this is currently being canceled (cancel has been called, the
-* callback may not yet have been made).
-*/
-  this._canceled = false;
-
-  /**
-* False until all data has been read from input and written to output, at
-* which point this copy is completed and cancel() is asynchronously called.
-*/
-  this._completed = false;
-
-  /** Required by nsIRequest, meaningless. */
-  this.loadFlags = 0;
-  /** Required by nsIRequest, meaningless. */
-  this.loadGroup = null;
-  /** Required by nsIRequest, meaningless. */
-  this.name = "response-body-copy";
-
-  /** Status of this request. */
-  this.status = Cr.NS_OK;
-
-  /** Arrays of byte strings waiting to be written to output. */
-  this._pendingData = [];
-
-  // start copying
-  try
-  {
-    observer.onStartRequest(this, context);
-    this._waitToReadData();
-    this._waitForSinkClosure();
-  }
-  catch (e)
-  {
-    dumpn("!!! error starting copy: " + e +
-          ("lineNumber" in e ? ", line " + e.lineNumber : ""));
-    dumpn(e.stack);
-    this.cancel(Cr.NS_ERROR_UNEXPECTED);
-  }
-}
-WriteThroughCopier.prototype =
-{
-  /* nsISupports implementation */
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIInputStreamCallback) ||
-        iid.equals(Ci.nsIOutputStreamCallback) ||
-        iid.equals(Ci.nsIRequest) ||
-        iid.equals(Ci.nsISupports))
-    {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Receives a more-data-in-input notification and writes the corresponding
-* data to the output.
-*
-* @param input : nsIAsyncInputStream
-* the input stream on whose data we have been waiting
-*/
-  onInputStreamReady: function(input)
-  {
-    if (this._source === null)
-      return;
-
-    dumpn("*** onInputStreamReady");
-
-    //
-    // Ordinarily we'll read a non-zero amount of data from input, queue it up
-    // to be written and then wait for further callbacks. The complications in
-    // this method are the cases where we deviate from that behavior when errors
-    // occur or when copying is drawing to a finish.
-    //
-    // The edge cases when reading data are:
-    //
-    // Zero data is read
-    // If zero data was read, we're at the end of available data, so we can
-    // should stop reading and move on to writing out what we have (or, if
-    // we've already done that, onto notifying of completion).
-    // A stream-closed exception is thrown
-    // This is effectively a less kind version of zero data being read; the
-    // only difference is that we notify of completion with that result
-    // rather than with NS_OK.
-    // Some other exception is thrown
-    // This is the least kind result. We don't know what happened, so we
-    // act as though the stream closed except that we notify of completion
-    // with the result NS_ERROR_UNEXPECTED.
-    //
-
-    var bytesWanted = 0, bytesConsumed = -1;
-    try
-    {
-      input = new BinaryInputStream(input);
-
-      bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE);
-      dumpn("*** input wanted: " + bytesWanted);
-
-      if (bytesWanted > 0)
-      {
-        var data = input.readByteArray(bytesWanted);
-        bytesConsumed = data.length;
-        this._pendingData.push(String.fromCharCode.apply(String, data));
-      }
-
-      dumpn("*** " + bytesConsumed + " bytes read");
-
-      // Handle the zero-data edge case in the same place as all other edge
-      // cases are handled.
-      if (bytesWanted === 0)
-        throw Cr.NS_BASE_STREAM_CLOSED;
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** input stream closed");
-        e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED;
-      }
-      else
-      {
-        dumpn("!!! unexpected error reading from input, canceling: " + e);
-        e = Cr.NS_ERROR_UNEXPECTED;
-      }
-
-      this._doneReadingSource(e);
-      return;
-    }
-
-    var pendingData = this._pendingData;
-
-    NS_ASSERT(bytesConsumed > 0);
-    NS_ASSERT(pendingData.length > 0, "no pending data somehow?");
-    NS_ASSERT(pendingData[pendingData.length - 1].length > 0,
-              "buffered zero bytes of data?");
-
-    NS_ASSERT(this._source !== null);
-
-    // Reading has gone great, and we've gotten data to write now. What if we
-    // don't have a place to write that data, because output went away just
-    // before this read? Drop everything on the floor, including new data, and
-    // cancel at this point.
-    if (this._sink === null)
-    {
-      pendingData.length = 0;
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we've read the data, and we know we have a place to write it. We
-    // need to queue up the data to be written, but *only* if none is queued
-    // already -- if data's already queued, the code that actually writes the
-    // data will make sure to wait on unconsumed pending data.
-    try
-    {
-      if (pendingData.length === 1)
-        this._waitToWriteData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to write data just read, swallowing and " +
-            "writing only what we already have: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Whee! We successfully read some data, and it's successfully queued up to
-    // be written. All that remains now is to wait for more data to read.
-    try
-    {
-      this._waitToReadData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to read more data: " + e);
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-    }
-  },
-
-
-  // NSIOUTPUTSTREAMCALLBACK
-
-  /**
-* Callback when data may be written to the output stream without blocking, or
-* when the output stream has been closed.
-*
-* @param output : nsIAsyncOutputStream
-* the output stream on whose writability we've been waiting, also known as
-* this._sink
-*/
-  onOutputStreamReady: function(output)
-  {
-    if (this._sink === null)
-      return;
-
-    dumpn("*** onOutputStreamReady");
-
-    var pendingData = this._pendingData;
-    if (pendingData.length === 0)
-    {
-      // There's no pending data to write. The only way this can happen is if
-      // we're waiting on the output stream's closure, so we can respond to a
-      // copying failure as quickly as possible (rather than waiting for data to
-      // be available to read and then fail to be copied). Therefore, we must
-      // be done now -- don't bother to attempt to write anything and wrap
-      // things up.
-      dumpn("!!! output stream closed prematurely, ending copy");
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-
-    NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?");
-
-    //
-    // Write out the first pending quantum of data. The possible errors here
-    // are:
-    //
-    // The write might fail because we can't write that much data
-    // Okay, we've written what we can now, so re-queue what's left and
-    // finish writing it out later.
-    // The write failed because the stream was closed
-    // Discard pending data that we can no longer write, stop reading, and
-    // signal that copying finished.
-    // Some other error occurred.
-    // Same as if the stream were closed, but notify with the status
-    // NS_ERROR_UNEXPECTED so the observer knows something was wonky.
-    //
-
-    try
-    {
-      var quantum = pendingData[0];
-
-      // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on
-      // undefined behavior! We're only using this because writeByteArray
-      // is unusably broken for asynchronous output streams; see bug 532834
-      // for details.
-      var bytesWritten = output.write(quantum, quantum.length);
-      if (bytesWritten === quantum.length)
-        pendingData.shift();
-      else
-        pendingData[0] = quantum.substring(bytesWritten);
-
-      dumpn("*** wrote " + bytesWritten + " bytes of data");
-    }
-    catch (e)
-    {
-      if (wouldBlock(e))
-      {
-        NS_ASSERT(pendingData.length > 0,
-                  "stream-blocking exception with no data to write?");
-        NS_ASSERT(pendingData[0].length > 0,
-                  "stream-blocking exception with empty quantum?");
-        this._waitToWriteData();
-        return;
-      }
-
-      if (streamClosed(e))
-        dumpn("!!! output stream prematurely closed, signaling error...");
-      else
-        dumpn("!!! unknown error: " + e + ", quantum=" + quantum);
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // The day is ours! Quantum written, now let's see if we have more data
-    // still to write.
-    try
-    {
-      if (pendingData.length > 0)
-      {
-        this._waitToWriteData();
-        return;
-      }
-    }
-    catch (e)
-    {
-      dumpn("!!! unexpected error waiting to write pending data: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we have no more pending data to write -- but might we get more in
-    // the future?
-    if (this._source !== null)
-    {
-      /*
-* If we might, then wait for the output stream to be closed. (We wait
-* only for closure because we have no data to write -- and if we waited
-* for a specific amount of data, we would get repeatedly notified for no
-* reason if over time the output stream permitted more and more data to
-* be written to it without blocking.)
-*/
-       this._waitForSinkClosure();
-    }
-    else
-    {
-      /*
-* On the other hand, if we can't have more data because the input
-* stream's gone away, then it's time to notify of copy completion.
-* Victory!
-*/
-      this._sink = null;
-      this._cancelOrDispatchCancelCallback(Cr.NS_OK);
-    }
-  },
-
-
-  // NSIREQUEST
-
-  /** Returns true if the cancel observer hasn't been notified yet. */
-  isPending: function()
-  {
-    return !this._completed;
-  },
-
-  /** Not implemented, don't use! */
-  suspend: notImplemented,
-  /** Not implemented, don't use! */
-  resume: notImplemented,
-
-  /**
-* Cancels data reading from input, asynchronously writes out any pending
-* data, and causes the observer to be notified with the given error code when
-* all writing has finished.
-*
-* @param status : nsresult
-* the status to pass to the observer when data copying has been canceled
-*/
-  cancel: function(status)
-  {
-    dumpn("*** cancel(" + status.toString(16) + ")");
-
-    if (this._canceled)
-    {
-      dumpn("*** suppressing a late cancel");
-      return;
-    }
-
-    this._canceled = true;
-    this.status = status;
-
-    // We could be in the middle of absolutely anything at this point. Both
-    // input and output might still be around, we might have pending data to
-    // write, and in general we know nothing about the state of the world. We
-    // therefore must assume everything's in progress and take everything to its
-    // final steady state (or so far as it can go before we need to finish
-    // writing out remaining data).
-
-    this._doneReadingSource(status);
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Stop reading input if we haven't already done so, passing e as the status
-* when closing the stream, and kick off a copy-completion notice if no more
-* data remains to be written.
-*
-* @param e : nsresult
-* the status to be used when closing the input stream
-*/
-  _doneReadingSource: function(e)
-  {
-    dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
-
-    this._finishSource(e);
-    if (this._pendingData.length === 0)
-      this._sink = null;
-    else
-      NS_ASSERT(this._sink !== null, "null output?");
-
-    // If we've written out all data read up to this point, then it's time to
-    // signal completion.
-    if (this._sink === null)
-    {
-      NS_ASSERT(this._pendingData.length === 0, "pending data still?");
-      this._cancelOrDispatchCancelCallback(e);
-    }
-  },
-
-  /**
-* Stop writing output if we haven't already done so, discard any data that
-* remained to be sent, close off input if it wasn't already closed, and kick
-* off a copy-completion notice.
-*
-* @param e : nsresult
-* the status to be used when closing input if it wasn't already closed
-*/
-  _doneWritingToSink: function(e)
-  {
-    dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")");
-
-    this._pendingData.length = 0;
-    this._sink = null;
-    this._doneReadingSource(e);
-  },
-
-  /**
-* Completes processing of this copy: either by canceling the copy if it
-* hasn't already been canceled using the provided status, or by dispatching
-* the cancel callback event (with the originally provided status, of course)
-* if it already has been canceled.
-*
-* @param status : nsresult
-* the status code to use to cancel this, if this hasn't already been
-* canceled
-*/
-  _cancelOrDispatchCancelCallback: function(status)
-  {
-    dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")");
-
-    NS_ASSERT(this._source === null, "should have finished input");
-    NS_ASSERT(this._sink === null, "should have finished output");
-    NS_ASSERT(this._pendingData.length === 0, "should have no pending data");
-
-    if (!this._canceled)
-    {
-      this.cancel(status);
-      return;
-    }
-
-    var self = this;
-    var event =
-      {
-        run: function()
-        {
-          dumpn("*** onStopRequest async callback");
-
-          self._completed = true;
-          try
-          {
-            self._observer.onStopRequest(self, self._context, self.status);
-          }
-          catch (e)
-          {
-            NS_ASSERT(false,
-                      "how are we throwing an exception here? we control " +
-                      "all the callers! " + e);
-          }
-        }
-      };
-
-    gThreadManager.dispatchToMainThread(event);
-  },
-
-  /**
-* Kicks off another wait for more data to be available from the input stream.
-*/
-  _waitToReadData: function()
-  {
-    dumpn("*** _waitToReadData");
-    this._source.asyncWait(this, 0, Response.SEGMENT_SIZE,
-                           gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off another wait until data can be written to the output stream.
-*/
-  _waitToWriteData: function()
-  {
-    dumpn("*** _waitToWriteData");
-
-    var pendingData = this._pendingData;
-    NS_ASSERT(pendingData.length > 0, "no pending data to write?");
-    NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?");
-
-    this._sink.asyncWait(this, 0, pendingData[0].length,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off a wait for the sink to which data is being copied to be closed.
-* We wait for stream closure when we don't have any data to be copied, rather
-* than waiting to write a specific amount of data. We can't wait to write
-* data because the sink might be infinitely writable, and if no data appears
-* in the source for a long time we might have to spin quite a bit waiting to
-* write, waiting to write again, &c. Waiting on stream closure instead means
-* we'll get just one notification if the sink dies. Note that when data
-* starts arriving from the sink we'll resume waiting for data to be written,
-* dropping this closure-only callback entirely.
-*/
-  _waitForSinkClosure: function()
-  {
-    dumpn("*** _waitForSinkClosure");
-
-    this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Closes input with the given status, if it hasn't already been closed;
-* otherwise a no-op.
-*
-* @param status : nsresult
-* status code use to close the source stream if necessary
-*/
-  _finishSource: function(status)
-  {
-    dumpn("*** _finishSource(" + status.toString(16) + ")");
-
-    if (this._source !== null)
-    {
-      this._source.closeWithStatus(status);
-      this._source = null;
-    }
-  }
-};
-
-
-/**
-* A container for utility functions used with HTTP headers.
-*/
-const headerUtils =
-{
-  /**
-* Normalizes fieldName (by converting it to lowercase) and ensures it is a
-* valid header field name (although not necessarily one specified in RFC
-* 2616).
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not match the field-name production in RFC 2616
-* @returns string
-* fieldName converted to lowercase if it is a valid header, for characters
-* where case conversion is possible
-*/
-  normalizeFieldName: function(fieldName)
-  {
-    if (fieldName == "")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    for (var i = 0, sz = fieldName.length; i < sz; i++)
-    {
-      if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
-      {
-        dumpn(fieldName + " is not a valid header field name!");
-        throw Cr.NS_ERROR_INVALID_ARG;
-      }
-    }
-
-    return fieldName.toLowerCase();
-  },
-
-  /**
-* Ensures that fieldValue is a valid header field value (although not
-* necessarily as specified in RFC 2616 if the corresponding field name is
-* part of the HTTP protocol), normalizes the value if it is, and
-* returns the normalized value.
-*
-* @param fieldValue : string
-* a value to be normalized as an HTTP header field value
-* @throws NS_ERROR_INVALID_ARG
-* if fieldValue does not match the field-value production in RFC 2616
-* @returns string
-* fieldValue as a normalized HTTP header field value
-*/
-  normalizeFieldValue: function(fieldValue)
-  {
-    // field-value = *( field-content | LWS )
-    // field-content = <the OCTETs making up the field-value
-    // and consisting of either *TEXT or combinations
-    // of token, separators, and quoted-string>
-    // TEXT = <any OCTET except CTLs,
-    // but including LWS>
-    // LWS = [CRLF] 1*( SP | HT )
-    //
-    // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-    // qdtext = <any TEXT except <">>
-    // quoted-pair = "\" CHAR
-    // CHAR = <any US-ASCII character (octets 0 - 127)>
-
-    // Any LWS that occurs between field-content MAY be replaced with a single
-    // SP before interpreting the field value or forwarding the message
-    // downstream (section 4.2); we replace 1*LWS with a single SP
-    var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
-
-    // remove leading/trailing LWS (which has been converted to SP)
-    val = val.replace(/^ +/, "").replace(/ +$/, "");
-
-    // that should have taken care of all CTLs, so val should contain no CTLs
-    for (var i = 0, len = val.length; i < len; i++)
-      if (isCTL(val.charCodeAt(i)))
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
-    // normalize, however, so this can be construed as a tightening of the
-    // spec and not entirely as a bug
-    return val;
-  }
-};
-
-
-
-/**
-* Converts the given string into a string which is safe for use in an HTML
-* context.
-*
-* @param str : string
-* the string to make HTML-safe
-* @returns string
-* an HTML-safe version of str
-*/
-function htmlEscape(str)
-{
-  // this is naive, but it'll work
-  var s = "";
-  for (var i = 0; i < str.length; i++)
-    s += "&#" + str.charCodeAt(i) + ";";
-  return s;
-}
-
-
-/**
-* Constructs an object representing an HTTP version (see section 3.1).
-*
-* @param versionString
-* a string of the form "#.#", where # is an non-negative decimal integer with
-* or without leading zeros
-* @throws
-* if versionString does not specify a valid HTTP version number
-*/
-function nsHttpVersion(versionString)
-{
-  var matches = /^(\d+)\.(\d+)$/.exec(versionString);
-  if (!matches)
-    throw "Not a valid HTTP version!";
-
-  /** The major version number of this, as a number. */
-  this.major = parseInt(matches[1], 10);
-
-  /** The minor version number of this, as a number. */
-  this.minor = parseInt(matches[2], 10);
-
-  if (isNaN(this.major) || isNaN(this.minor) ||
-      this.major < 0 || this.minor < 0)
-    throw "Not a valid HTTP version!";
-}
-nsHttpVersion.prototype =
-{
-  /**
-* Returns the standard string representation of the HTTP version represented
-* by this (e.g., "1.1").
-*/
-  toString: function ()
-  {
-    return this.major + "." + this.minor;
-  },
-
-  /**
-* Returns true if this represents the same HTTP version as otherVersion,
-* false otherwise.
-*
-* @param otherVersion : nsHttpVersion
-* the version to compare against this
-*/
-  equals: function (otherVersion)
-  {
-    return this.major == otherVersion.major &&
-           this.minor == otherVersion.minor;
-  },
-
-  /** True if this >= otherVersion, false otherwise. */
-  atLeast: function(otherVersion)
-  {
-    return this.major > otherVersion.major ||
-           (this.major == otherVersion.major &&
-            this.minor >= otherVersion.minor);
-  }
-};
-
-nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0");
-nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1");
-
-
-/**
-* An object which stores HTTP headers for a request or response.
-*
-* Note that since headers are case-insensitive, this object converts headers to
-* lowercase before storing them. This allows the getHeader and hasHeader
-* methods to work correctly for any case of a header, but it means that the
-* values returned by .enumerator may not be equal case-sensitively to the
-* values passed to setHeader when adding headers to this.
-*/
-function nsHttpHeaders()
-{
-  /**
-* A hash of headers, with header field names as the keys and header field
-* values as the values. Header field names are case-insensitive, but upon
-* insertion here they are converted to lowercase. Header field values are
-* normalized upon insertion to contain no leading or trailing whitespace.
-*
-* Note also that per RFC 2616, section 4.2, two headers with the same name in
-* a message may be treated as one header with the same field name and a field
-* value consisting of the separate field values joined together with a "," in
-* their original order. This hash stores multiple headers with the same name
-* in this manner.
-*/
-  this._headers = {};
-}
-nsHttpHeaders.prototype =
-{
-  /**
-* Sets the header represented by name and value in this.
-*
-* @param name : string
-* the header name
-* @param value : string
-* the header value
-* @throws NS_ERROR_INVALID_ARG
-* if name or value is not a valid header component
-*/
-  setHeader: function(fieldName, fieldValue, merge)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    var value = headerUtils.normalizeFieldValue(fieldValue);
-
-    // The following three headers are stored as arrays because their real-world
-    // syntax prevents joining individual headers into a single header using
-    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
-    if (merge && name in this._headers)
-    {
-      if (name === "www-authenticate" ||
-          name === "proxy-authenticate" ||
-          name === "set-cookie")
-      {
-        this._headers[name].push(value);
-      }
-      else
-      {
-        this._headers[name][0] += "," + value;
-        NS_ASSERT(this._headers[name].length === 1,
-            "how'd a non-special header have multiple values?")
-      }
-    }
-    else
-    {
-      this._headers[name] = [value];
-    }
-  },
-
-  /**
-* Returns the value for the header specified by this.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns string
-* the field value for the given header, possibly with non-semantic changes
-* (i.e., leading/trailing whitespace stripped, whitespace runs replaced
-* with spaces, etc.) at the option of the implementation; multiple
-* instances of the header will be combined with a comma, except for
-* the three headers noted in the description of getHeaderValues
-*/
-  getHeader: function(fieldName)
-  {
-    return this.getHeaderValues(fieldName).join("\n");
-  },
-
-  /**
-* Returns the value for the header specified by fieldName as an array.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns [string]
-* an array of all the header values in this for the given
-* header name. Header values will generally be collapsed
-* into a single header by joining all header values together
-* with commas, but certain headers (Proxy-Authenticate,
-* WWW-Authenticate, and Set-Cookie) violate the HTTP spec
-* and cannot be collapsed in this manner. For these headers
-* only, the returned array may contain multiple elements if
-* that header has been added more than once.
-*/
-  getHeaderValues: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-
-    if (name in this._headers)
-      return this._headers[name];
-    else
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-  },
-
-  /**
-* Returns true if a header with the given field name exists in this, false
-* otherwise.
-*
-* @param fieldName : string
-* the field name whose existence is to be determined in this
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @returns boolean
-* true if the header's present, false otherwise
-*/
-  hasHeader: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    return (name in this._headers);
-  },
-
-  /**
-* Returns a new enumerator over the field names of the headers in this, as
-* nsISupportsStrings. The names returned will be in lowercase, regardless of
-* how they were input using setHeader (header names are case-insensitive per
-* RFC 2616).
-*/
-  get enumerator()
-  {
-    var headers = [];
-    for (var i in this._headers)
-    {
-      var supports = new SupportsString();
-      supports.data = i;
-      headers.push(supports);
-    }
-
-    return new nsSimpleEnumerator(headers);
-  }
-};
-
-
-/**
-* Constructs an nsISimpleEnumerator for the given array of items.
-*
-* @param items : Array
-* the items, which must all implement nsISupports
-*/
-function nsSimpleEnumerator(items)
-{
-  this._items = items;
-  this._nextIndex = 0;
-}
-nsSimpleEnumerator.prototype =
-{
-  hasMoreElements: function()
-  {
-    return this._nextIndex < this._items.length;
-  },
-  getNext: function()
-  {
-    if (!this.hasMoreElements())
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    return this._items[this._nextIndex++];
-  },
-  QueryInterface: function(aIID)
-  {
-    if (Ci.nsISimpleEnumerator.equals(aIID) ||
-        Ci.nsISupports.equals(aIID))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-
-/**
-* A representation of the data in an HTTP request.
-*
-* @param port : uint
-* the port on which the server receiving this request runs
-*/
-function Request(port)
-{
-  /** Method of this request, e.g. GET or POST. */
-  this._method = "";
-
-  /** Path of the requested resource; empty paths are converted to '/'. */
-  this._path = "";
-
-  /** Query string, if any, associated with this request (not including '?'). */
-  this._queryString = "";
-
-  /** Scheme of requested resource, usually http, always lowercase. */
-  this._scheme = "http";
-
-  /** Hostname on which the requested resource resides. */
-  this._host = undefined;
-
-  /** Port number over which the request was received. */
-  this._port = port;
-
-  var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null);
-
-  /** Stream from which data in this request's body may be read. */
-  this._bodyInputStream = bodyPipe.inputStream;
-
-  /** Stream to which data in this request's body is written. */
-  this._bodyOutputStream = bodyPipe.outputStream;
-
-  /**
-* The headers in this request.
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* For the addition of ad-hoc properties and new functionality without having
-* to change nsIHttpRequest every time; currently lazily created, as its only
-* use is in directory listings.
-*/
-  this._bag = null;
-}
-Request.prototype =
-{
-  // SERVER METADATA
-
-  //
-  // see nsIHttpRequest.scheme
-  //
-  get scheme()
-  {
-    return this._scheme;
-  },
-
-  //
-  // see nsIHttpRequest.host
-  //
-  get host()
-  {
-    return this._host;
-  },
-
-  //
-  // see nsIHttpRequest.port
-  //
-  get port()
-  {
-    return this._port;
-  },
-
-  // REQUEST LINE
-
-  //
-  // see nsIHttpRequest.method
-  //
-  get method()
-  {
-    return this._method;
-  },
-
-  //
-  // see nsIHttpRequest.httpVersion
-  //
-  get httpVersion()
-  {
-    return this._httpVersion.toString();
-  },
-
-  //
-  // see nsIHttpRequest.path
-  //
-  get path()
-  {
-    return this._path;
-  },
-
-  //
-  // see nsIHttpRequest.queryString
-  //
-  get queryString()
-  {
-    return this._queryString;
-  },
-
-  // HEADERS
-
-  //
-  // see nsIHttpRequest.getHeader
-  //
-  getHeader: function(name)
-  {
-    return this._headers.getHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.hasHeader
-  //
-  hasHeader: function(name)
-  {
-    return this._headers.hasHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get headers()
-  {
-    return this._headers.enumerator;
-  },
-
-  //
-  // see nsIPropertyBag.enumerator
-  //
-  get enumerator()
-  {
-    this._ensurePropertyBag();
-    return this._bag.enumerator;
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get bodyInputStream()
-  {
-    return this._bodyInputStream;
-  },
-
-  //
-  // see nsIPropertyBag.getProperty
-  //
-  getProperty: function(name)
-  {
-    this._ensurePropertyBag();
-    return this._bag.getProperty(name);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /** Ensures a property bag has been created for ad-hoc behaviors. */
-  _ensurePropertyBag: function()
-  {
-    if (!this._bag)
-      this._bag = new WritablePropertyBag();
-  }
-};
-
-
-// XPCOM trappings
-if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason...
-    "generateNSGetFactory" in XPCOMUtils) {
-  var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]);
-}
-
-
-
-/**
-* Creates a new HTTP server listening for loopback traffic on the given port,
-* starts it, and runs the server until the server processes a shutdown request,
-* spinning an event loop so that events posted by the server's socket are
-* processed.
-*
-* This method is primarily intended for use in running this script from within
-* xpcshell and running a functional HTTP server without having to deal with
-* non-essential details.
-*
-* Note that running multiple servers using variants of this method probably
-* doesn't work, simply due to how the internal event loop is spun and stopped.
-*
-* @note
-* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code);
-* you should use this server as a component in Mozilla 1.8.
-* @param port
-* the port on which the server will run, or -1 if there exists no preference
-* for a specific port; note that attempting to use some values for this
-* parameter (particularly those below 1024) may cause this method to throw or
-* may result in the server being prematurely shut down
-* @param basePath
-* a local directory from which requests will be served (i.e., if this is
-* "/home/jwalden/" then a request to /index.html will load
-* /home/jwalden/index.html); if this is omitted, only the default URLs in
-* this server implementation will be functional
-*/
-function server(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  // if you're running this, you probably want to see debugging info
-  DEBUG = true;
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", SJS_TYPE);
-  srv.start(port);
-
-  gThreadManager.spinEventLoopUntil(() => srv.isStopped());
-
-  gThreadManager.spinEventLoopUntilEmpty();
-
-  DEBUG = false;
-}
-
-function startServerAsync(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", "sjs");
-  srv.start(port);
-  return srv;
-}
-
-exports.nsHttpServer = nsHttpServer;
-exports.ScriptableInputStream = ScriptableInputStream;
-exports.server = server;
-exports.startServerAsync = startServerAsync;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/main.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-const { safeMerge: merge } = require('sdk/util/object');
-const app = require("sdk/system/xul-app");
-
-// Once Bug 903018 is resolved, just move the application testing to
-// module.metadata.engines
-if (app.is('Firefox')) {
-  merge(module.exports,
-    require('./test-places-events'),
-    require('./test-places-bookmarks'),
-    require('./test-places-favicon'),
-    require('./test-places-history'),
-    require('./test-places-host'),
-    require('./test-places-utils')
-  );
-} else {
-  exports['test unsupported'] = (assert) => {
-    assert.pass('This application is unsupported.');
-  };
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/places-helper.js
+++ /dev/null
@@ -1,232 +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 { send } = require('sdk/addon/events');
-const { setTimeout } = require('sdk/timers');
-const { newURI } = require('sdk/url/utils');
-const { defer, all } = require('sdk/core/promise');
-const { once } = require('sdk/system/events');
-const { set } = require('sdk/preferences/service');
-const {
-  Bookmark, Group, Separator,
-  save, search,
-  MENU, TOOLBAR, UNSORTED
-} = require('sdk/places/bookmarks');
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
-  "resource://gre/modules/PlacesUtils.jsm");
-
-function invalidResolve (assert) {
-  return function (e) {
-    assert.fail('Resolve state should not be called: ' + e);
-  };
-}
-exports.invalidResolve = invalidResolve;
-
-// Removes all children of group
-function clearBookmarks (group) {
-  group
-   ? PlacesUtils.bookmarks.removeFolderChildren(group.id)
-   : clearAllBookmarks();
-}
-
-function clearAllBookmarks () {
-  [MENU, TOOLBAR, UNSORTED].forEach(clearBookmarks);
-}
-
-function clearHistory (done) {
-  PlacesUtils.history.clear().catch(Cu.reportError).then(done);
-}
-
-// Cleans bookmarks and history and disables maintanance
-function resetPlaces (done) {
-  // Set last maintenance to current time to prevent
-  // Places DB maintenance occuring and locking DB
-  set('places.database.lastMaintenance', Math.floor(Date.now() / 1000));
-  clearAllBookmarks();
-  clearHistory(done);
-}
-exports.resetPlaces = resetPlaces;
-
-function compareWithHost (assert, item) {
-  let id = item.id;
-  let type = item.type === 'group' ?
-    PlacesUtils.bookmarks.TYPE_FOLDER :
-    PlacesUtils.bookmarks['TYPE_' + item.type.toUpperCase()];
-  let url = item.url && !item.url.endsWith('/') ? item.url + '/' : item.url;
-
-  if (type === PlacesUtils.bookmarks.TYPE_BOOKMARK) {
-    assert.equal(url, PlacesUtils.bookmarks.getBookmarkURI(id).spec.toString(),
-                 'Matches host url');
-    let tags = PlacesUtils.tagging.getTagsForURI(newURI(item.url));
-    for (let tag of tags) {
-      // Handle both array for raw data and set for instances
-      if (Array.isArray(item.tags))
-        assert.ok(~item.tags.indexOf(tag), 'has correct tag');
-      else
-        assert.ok(item.tags.has(tag), 'has correct tag');
-    }
-    assert.equal(tags.length,
-      Array.isArray(item.tags) ? item.tags.length : item.tags.size,
-      'matches tag count');
-  }
-  if (type !== PlacesUtils.bookmarks.TYPE_SEPARATOR) {
-    assert.equal(item.title, PlacesUtils.bookmarks.getItemTitle(id),
-                 'Matches host title');
-  }
-  assert.equal(item.index, PlacesUtils.bookmarks.getItemIndex(id),
-               'Matches host index');
-  assert.equal(item.group.id || item.group,
-               PlacesUtils.bookmarks.getFolderIdForItem(id),
-               'Matches host group id');
-  assert.equal(type, PlacesUtils.bookmarks.getItemType(id),
-               'Matches host type');
-}
-exports.compareWithHost = compareWithHost;
-
-/**
- * Adds visits to places.
- *
- * @param {Array|String} urls Either an array of urls to add, or a single url
- *                            as a string.
- */
-function addVisits (urls) {
-  return PlacesUtils.history.insertMany([].concat(urls).map(createVisit));
-}
-exports.addVisits = addVisits;
-
-function removeVisits (urls) {
-  PlacesUtils.history.remove(urls);
-}
-exports.removeVisits = removeVisits;
-
-// Creates a mozIVisitInfo object
-function createVisit (url) {
-  return {
-    url,
-    title: "Test visit for " + url,
-    visits: [{
-      transition: PlacesUtils.history.TRANSITION_LINK
-    }]
-  };
-}
-
-function createBookmark (data) {
-  data = data || {};
-  let item = {
-    title: data.title || 'Moz',
-    url: data.url || (!data.type || data.type === 'bookmark' ?
-      'http://moz.com/' :
-      undefined),
-    tags: data.tags || (!data.type || data.type === 'bookmark' ?
-      ['firefox'] :
-      undefined),
-    type: data.type || 'bookmark',
-    group: data.group
-  };
-  return send('sdk-places-bookmarks-create', item);
-}
-exports.createBookmark = createBookmark;
-
-function historyBatch () {
-  PlacesUtils.history.runInBatchMode(() => {}, null);
-}
-exports.historyBatch = historyBatch;
-
-function createBookmarkItem (data) {
-  let deferred = defer();
-  data = data || {};
-  save({
-    title: data.title || 'Moz',
-    url: data.url || 'http://moz.com/',
-    tags: data.tags || (!data.type || data.type === 'bookmark' ?
-      ['firefox'] :
-      undefined),
-    type: data.type || 'bookmark',
-    group: data.group
-  }).on('end', function (bookmark) {
-    deferred.resolve(bookmark[0]);
-  });
-  return deferred.promise;
-}
-exports.createBookmarkItem = createBookmarkItem;
-
-function createBookmarkTree () {
-  let agg = [];
-  return createBookmarkItem({ type: 'group', title: 'mozgroup' })
-    .then(group => {
-    agg.push(group);
-    return all([createBookmarkItem({
-      title: 'mozilla.com',
-      url: 'http://mozilla.com/',
-      group: group,
-      tags: ['mozilla', 'firefox', 'thunderbird', 'rust']
-    }), createBookmarkItem({
-      title: 'mozilla.org',
-      url: 'http://mozilla.org/',
-      group: group,
-      tags: ['mozilla', 'firefox', 'thunderbird', 'rust']
-    }), createBookmarkItem({
-      title: 'firefox',
-      url: 'http://firefox.com/',
-      group: group,
-      tags: ['mozilla', 'firefox', 'browser']
-    }), createBookmarkItem({
-      title: 'thunderbird',
-      url: 'http://mozilla.org/thunderbird/',
-      group: group,
-      tags: ['mozilla', 'thunderbird', 'email']
-    }), createBookmarkItem({
-      title: 'moz subfolder',
-      group: group,
-      type: 'group'
-    })
-    ]);
-  })
-  .then(results => {
-    agg = agg.concat(results);
-    let subfolder = results.filter(item => item.type === 'group')[0];
-    return createBookmarkItem({
-      title: 'dark javascript secrets',
-      url: 'http://w3schools.com',
-      group: subfolder,
-      tags: []
-    });
-  }).then(item => {
-    agg.push(item);
-    return createBookmarkItem(
-      { type: 'group', group: MENU, title: 'other stuff' }
-    );
-  }).then(newGroup => {
-    agg.push(newGroup);
-    return all([
-      createBookmarkItem({
-        title: 'mdn',
-        url: 'http://developer.mozilla.org/en-US/',
-        group: newGroup,
-        tags: ['javascript']
-      }),
-      createBookmarkItem({
-        title: 'web audio',
-        url: 'http://webaud.io',
-        group: newGroup,
-        tags: ['javascript', 'web audio']
-      }),
-      createBookmarkItem({
-        title: 'web audio components',
-        url: 'http://component.fm',
-        group: newGroup,
-        tags: ['javascript', 'web audio', 'components']
-      })
-    ]);
-  }).then(results => {
-    agg = agg.concat(results);
-    return agg;
-  });
-}
-exports.createBookmarkTree = createBookmarkTree;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-bookmarks.js
+++ /dev/null
@@ -1,948 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require('chrome');
-const { request } = require('sdk/addon/host');
-const { filter } = require('sdk/event/utils');
-const { on, off } = require('sdk/event/core');
-const { setTimeout } = require('sdk/timers');
-const { newURI } = require('sdk/url/utils');
-const { defer, all, resolve } = require('sdk/core/promise');
-const { before, after } = require('sdk/test/utils');
-
-const {
-  Bookmark, Group, Separator,
-  save, search, remove,
-  MENU, TOOLBAR, UNSORTED
-} = require('sdk/places/bookmarks');
-const {
-  invalidResolve, createTree,
-  compareWithHost, createBookmark, createBookmarkItem,
-  createBookmarkTree, addVisits, resetPlaces
-} = require('./places-helper');
-const { promisedEmitter } = require('sdk/places/utils');
-const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
-                    getService(Ci.nsINavBookmarksService);
-const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
-                    getService(Ci.nsITaggingService);
-
-exports.testDefaultFolders = function (assert) {
-  var ids = [
-    bmsrv.bookmarksMenuFolder,
-    bmsrv.toolbarFolder,
-    bmsrv.unfiledBookmarksFolder
-  ];
-
-  [MENU, TOOLBAR, UNSORTED].forEach(function (g, i) {
-    assert.ok(g.id === ids[i], ' default group matches id');
-  });
-};
-
-exports.testValidation = function (assert) {
-  assert.throws(() => {
-    Bookmark({ title: 'a title' });
-  }, /The `url` property must be a valid URL/, 'throws empty URL error');
-
-  assert.throws(() => {
-    Bookmark({ title: 'a title', url: 'not.a.url' });
-  }, /The `url` property must be a valid URL/, 'throws invalid URL error');
-
-  assert.throws(() => {
-    Bookmark({ url: 'http://foo.com' });
-  }, /The `title` property must be defined/, 'throws title error');
-
-  assert.throws(() => {
-    Bookmark();
-  }, /./, 'throws any error');
-
-  assert.throws(() => {
-    Group();
-  }, /The `title` property must be defined/, 'throws title error for group');
-
-  assert.throws(() => {
-    Bookmark({ url: 'http://foo.com', title: 'my title', tags: 'a tag' });
-  }, /The `tags` property must be a Set, or an array/, 'throws error for non set/array tag');
-};
-
-exports.testCreateBookmarks = function (assert, done) {
-  var bm = Bookmark({
-    title: 'moz',
-    url: 'http://mozilla.org',
-    tags: ['moz1', 'moz2', 'moz3']
-  });
-
-  save(bm).on('data', (bookmark, input) => {
-    assert.equal(input, bm, 'input is original input item');
-    assert.ok(bookmark.id, 'Bookmark has ID');
-    assert.equal(bookmark.title, 'moz');
-    assert.equal(bookmark.url, 'http://mozilla.org');
-    assert.equal(bookmark.group, UNSORTED, 'Unsorted folder is default parent');
-    assert.ok(bookmark !== bm, 'bookmark should be a new instance');
-    compareWithHost(assert, bookmark);
-  }).on('end', bookmarks => {
-    assert.equal(bookmarks.length, 1, 'returned bookmarks in end');
-    assert.equal(bookmarks[0].url, 'http://mozilla.org');
-    assert.equal(bookmarks[0].tags.has('moz1'), true, 'has first tag');
-    assert.equal(bookmarks[0].tags.has('moz2'), true, 'has second tag');
-    assert.equal(bookmarks[0].tags.has('moz3'), true, 'has third tag');
-    assert.pass('end event is called');
-    done();
-  });
-};
-
-exports.testCreateGroup = function (assert, done) {
-  save(Group({ title: 'mygroup', group: MENU })).on('data', g => {
-    assert.ok(g.id, 'Bookmark has ID');
-    assert.equal(g.title, 'mygroup', 'matches title');
-    assert.equal(g.group, MENU, 'Menu folder matches');
-    compareWithHost(assert, g);
-  }).on('end', results => {
-    assert.equal(results.length, 1);
-    assert.pass('end event is called');
-    done();
-  });
-};
-
-exports.testCreateSeparator = function (assert, done) {
-  save(Separator({ group: MENU })).on('data', function (s) {
-    assert.ok(s.id, 'Separator has id');
-    assert.equal(s.group, MENU, 'Parent group matches');
-    compareWithHost(assert, s);
-  }).on('end', function (results) {
-    assert.equal(results.length, 1);
-    assert.pass('end event is called');
-    done();
-  });
-};
-
-exports.testCreateError = function (assert, done) {
-  let bookmarks = [
-    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark'},
-    { title: 'moz2', url: 'invalidurl', type: 'bookmark'},
-    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark'}
-  ];
-
-  let dataCount = 0, errorCount = 0;
-  save(bookmarks).on('data', bookmark => {
-    assert.ok(/moz[1|3]/.test(bookmark.title), 'valid bookmarks complete');
-    dataCount++;
-  }).on('error', (reason, item) => {
-    assert.ok(
-      /The `url` property must be a valid URL/.test(reason),
-      'Error event called with correct reason');
-    assert.equal(item, bookmarks[1], 'returns input that failed in event');
-    errorCount++;
-  }).on('end', items => {
-    assert.equal(dataCount, 2, 'data event called twice');
-    assert.equal(errorCount, 1, 'error event called once');
-    assert.equal(items.length, bookmarks.length, 'all items should be in result');
-    assert.equal(items[0].toString(), '[object Bookmark]',
-      'should be a saved instance');
-    assert.equal(items[2].toString(), '[object Bookmark]',
-      'should be a saved instance');
-    assert.equal(items[1], bookmarks[1], 'should be original, unsaved object');
-
-    search({ query: 'moz' }).on('end', items => {
-      assert.equal(items.length, 2, 'only two items were successfully saved');
-      bookmarks[1].url = 'http://moz2.com/';
-      dataCount = errorCount = 0;
-      save(bookmarks).on('data', bookmark => {
-        dataCount++;
-      }).on('error', reason => errorCount++)
-      .on('end', items => {
-        assert.equal(items.length, 3, 'all 3 items saved');
-        assert.equal(dataCount, 3, '3 data events called');
-        assert.equal(errorCount, 0, 'no error events called');
-        search({ query: 'moz' }).on('end', items => {
-          assert.equal(items.length, 3, 'only 3 items saved');
-          items.map(item =>
-            assert.ok(/moz\d\.com/.test(item.url), 'correct item'))
-          done();
-        });
-      });
-    });
-  });
-};
-
-exports.testSaveDucktypes = function (assert, done) {
-  save({
-    title: 'moz',
-    url: 'http://mozilla.org',
-    type: 'bookmark'
-  }).on('data', (bookmark) => {
-    compareWithHost(assert, bookmark);
-    done();
-  });
-};
-
-exports.testSaveDucktypesParent = function (assert, done) {
-  let folder = { title: 'myfolder', type: 'group' };
-  let bookmark = { title: 'mozzie', url: 'http://moz.com', group: folder, type: 'bookmark' };
-  let sep = { type: 'separator', group: folder };
-  save([sep, bookmark]).on('end', (res) => {
-    compareWithHost(assert, res[0]);
-    compareWithHost(assert, res[1]);
-    assert.equal(res[0].group.title, 'myfolder', 'parent is ducktyped group');
-    assert.equal(res[1].group.title, 'myfolder', 'parent is ducktyped group');
-    done();
-  });
-};
-
-/*
- * Tests the scenario where the original bookmark item is resaved
- * and does not have an ID or an updated date, but should still be
- * mapped to the item it created previously
- */
-exports.testResaveOriginalItemMapping = function (assert, done) {
-  let bookmark = Bookmark({ title: 'moz', url: 'http://moz.org' });
-  save(bookmark).on('data', newBookmark => {
-    bookmark.title = 'new moz';
-    save(bookmark).on('data', newNewBookmark => {
-      assert.equal(newBookmark.id, newNewBookmark.id, 'should be the same bookmark item');
-      assert.equal(bmsrv.getItemTitle(newBookmark.id), 'new moz', 'should have updated title');
-      done();
-    });
-  });
-};
-
-exports.testCreateMultipleBookmarks = function (assert, done) {
-  let data = [
-    Bookmark({title: 'bm1', url: 'http://bm1.com'}),
-    Bookmark({title: 'bm2', url: 'http://bm2.com'}),
-    Bookmark({title: 'bm3', url: 'http://bm3.com'}),
-  ];
-  save(data).on('data', function (bookmark, input) {
-    let stored = data.filter(({title}) => title === bookmark.title)[0];
-    assert.equal(input, stored, 'input is original input item');
-    assert.equal(bookmark.title, stored.title, 'titles match');
-    assert.equal(bookmark.url, stored.url, 'urls match');
-    compareWithHost(assert, bookmark);
-  }).on('end', function (bookmarks) {
-    assert.equal(bookmarks.length, 3, 'all bookmarks returned');
-    done();
-  });
-};
-
-exports.testCreateImplicitParent = function (assert, done) {
-  let folder = Group({ title: 'my parent' });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: folder }),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: folder }),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: folder })
-  ];
-  save(bookmarks).on('data', function (bookmark) {
-    if (bookmark.type === 'bookmark') {
-      assert.equal(bookmark.group.title, folder.title, 'parent is linked');
-      compareWithHost(assert, bookmark);
-    } else if (bookmark.type === 'group') {
-      assert.equal(bookmark.group.id, UNSORTED.id, 'parent ID of group is correct');
-      compareWithHost(assert, bookmark);
-    }
-  }).on('end', function (results) {
-    assert.equal(results.length, 3, 'results should only hold explicit saves');
-    done();
-  });
-};
-
-exports.testCreateExplicitParent = function (assert, done) {
-  let folder = Group({ title: 'my parent' });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: folder }),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: folder }),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: folder })
-  ];
-  save(bookmarks.concat(folder)).on('data', function (bookmark) {
-    if (bookmark.type === 'bookmark') {
-      assert.equal(bookmark.group.title, folder.title, 'parent is linked');
-      compareWithHost(assert, bookmark);
-    } else if (bookmark.type === 'group') {
-      assert.equal(bookmark.group.id, UNSORTED.id, 'parent ID of group is correct');
-      compareWithHost(assert, bookmark);
-    }
-  }).on('end', function () {
-    done();
-  });
-};
-
-exports.testCreateNested = function (assert, done) {
-  let topFolder = Group({ title: 'top', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder }),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder }),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder })
-  ];
-  let dataEventCount = 0;
-  save(bookmarks).on('data', function (bookmark) {
-    if (bookmark.type === 'bookmark') {
-      assert.equal(bookmark.group.title, midFolder.title, 'parent is linked');
-    } else if (bookmark.title === 'top') {
-      assert.equal(bookmark.group.id, MENU.id, 'parent ID of top group is correct');
-    } else {
-      assert.equal(bookmark.group.title, topFolder.title, 'parent title of middle group is correct');
-    }
-    dataEventCount++;
-    compareWithHost(assert, bookmark);
-  }).on('end', () => {
-    assert.equal(dataEventCount, 5, 'data events for all saves have occurred');
-    assert.ok('end event called');
-    done();
-  });
-};
-
-/*
- * Was a scenario when implicitly saving a bookmark that was already created,
- * it was not being properly fetched and attempted to recreate
- */
-exports.testAddingToExistingParent = function (assert, done) {
-  let group = { type: 'group', title: 'mozgroup' };
-  let bookmarks = [
-    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark', group: group },
-    { title: 'moz2', url: 'http://moz2.com', type: 'bookmark', group: group },
-    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark', group: group }
-  ],
-  firstBatch, secondBatch;
-
-  saveP(bookmarks).then(data => {
-    firstBatch = data;
-    return saveP([
-      { title: 'moz4', url: 'http://moz4.com', type: 'bookmark', group: group },
-      { title: 'moz5', url: 'http://moz5.com', type: 'bookmark', group: group }
-    ]);
-  }, assert.fail).then(data => {
-    secondBatch = data;
-    assert.equal(firstBatch[0].group.id, secondBatch[0].group.id,
-      'successfully saved to the same parent');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testUpdateParent = function (assert, done) {
-  let group = { type: 'group', title: 'mozgroup' };
-  saveP(group).then(item => {
-    item[0].title = 'mozgroup-resave';
-    return saveP(item[0]);
-  }).then(item => {
-    assert.equal(item[0].title, 'mozgroup-resave', 'group saved successfully');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testUpdateSeparator = function (assert, done) {
-  let sep = [Separator(), Separator(), Separator()];
-  saveP(sep).then(item => {
-    item[0].index = 2;
-    return saveP(item[0]);
-  }).then(item => {
-    assert.equal(item[0].index, 2, 'updated index of separator');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testPromisedSave = function (assert, done) {
-  let topFolder = Group({ title: 'top', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
-  ];
-  let first, second, third;
-  saveP(bookmarks).then(bms => {
-    first = bms.filter(b => b.title === 'moz1')[0];
-    second = bms.filter(b => b.title === 'moz2')[0];
-    third = bms.filter(b => b.title === 'moz3')[0];
-    assert.equal(first.index, 0);
-    assert.equal(second.index, 1);
-    assert.equal(third.index, 2);
-    first.index = 3;
-    return saveP(first);
-  }).then(() => {
-    assert.equal(bmsrv.getItemIndex(first.id), 2, 'properly moved bookmark');
-    assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
-    assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testPromisedErrorSave = function*(assert) {
-  let bookmarks = [
-    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark'},
-    { title: 'moz2', url: 'invalidurl', type: 'bookmark'},
-    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark'}
-  ];
-
-  yield saveP(bookmarks).then(() => {
-    assert.fail("should not resolve");
-  }, reason => {
-    assert.ok(
-      /The `url` property must be a valid URL/.test(reason),
-      'Error event called with correct reason');
-  });
-
-  bookmarks[1].url = 'http://moz2.com';
-  yield saveP(bookmarks);
-
-  let res = yield searchP({ query: 'moz' });
-  assert.equal(res.length, 3, 'all 3 should be saved upon retry');
-  res.map(item => assert.ok(/moz\d\.com/.test(item.url), 'correct item'));
-};
-
-exports.testMovingChildren = function (assert, done) {
-  let topFolder = Group({ title: 'top', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
-  ];
-
-  save(bookmarks).on('end', bms => {
-    let first = bms.filter(b => b.title === 'moz1')[0];
-    let second = bms.filter(b => b.title === 'moz2')[0];
-    let third = bms.filter(b => b.title === 'moz3')[0];
-    assert.equal(first.index, 0);
-    assert.equal(second.index, 1);
-    assert.equal(third.index, 2);
-    /* When moving down in the same container we take
-     * into account the removal of the original item. If you want
-     * to move from index X to index Y > X you must use
-     * moveItem(id, folder, Y + 1)
-     */
-    first.index = 3;
-    save(first).on('end', () => {
-      assert.equal(bmsrv.getItemIndex(first.id), 2, 'properly moved bookmark');
-      assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
-      assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
-      done();
-    });
-  });
-};
-
-exports.testMovingChildrenNewFolder = function (assert, done) {
-  let topFolder = Group({ title: 'top', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let newFolder = Group({ title: 'new', group: MENU });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
-  ];
-  save(bookmarks).on('end', bms => {
-    let first = bms.filter(b => b.title === 'moz1')[0];
-    let second = bms.filter(b => b.title === 'moz2')[0];
-    let third = bms.filter(b => b.title === 'moz3')[0];
-    let definedMidFolder = first.group;
-    let definedNewFolder;
-    first.group = newFolder;
-    assert.equal(first.index, 0);
-    assert.equal(second.index, 1);
-    assert.equal(third.index, 2);
-    save(first).on('data', (data) => {
-      if (data.type === 'group') definedNewFolder = data;
-    }).on('end', (moved) => {
-      assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
-      assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
-      assert.equal(bmsrv.getItemIndex(first.id), 0, 'properly moved bookmark');
-      assert.equal(bmsrv.getFolderIdForItem(first.id), definedNewFolder.id,
-        'bookmark has new parent');
-      assert.equal(bmsrv.getFolderIdForItem(second.id), definedMidFolder.id,
-        'sibling bookmarks did not move');
-      assert.equal(bmsrv.getFolderIdForItem(third.id), definedMidFolder.id,
-        'sibling bookmarks did not move');
-      done();
-    });
-  });
-};
-
-exports.testRemoveFunction = function (assert) {
-  let topFolder = Group({ title: 'new', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
-  ];
-  remove([midFolder, topFolder].concat(bookmarks)).map(item => {
-    assert.equal(item.remove, true, 'remove toggled `remove` property to true');
-  });
-};
-
-exports.testRemove = function (assert, done) {
-  let id;
-  createBookmarkItem().then(data => {
-    id = data.id;
-    compareWithHost(assert, data); // ensure bookmark exists
-    save(remove(data)).on('data', (res) => {
-      assert.pass('data event should be called');
-      assert.ok(!res, 'response should be empty');
-    }).on('end', () => {
-      assert.throws(function () {
-        bmsrv.getItemTitle(id);
-      }, 'item should no longer exist');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-/*
- * Tests recursively removing children when removing a group
- */
-exports.testRemoveAllChildren = function (assert, done) {
-  let topFolder = Group({ title: 'new', group: MENU });
-  let midFolder = Group({ title: 'middle', group: topFolder });
-  let bookmarks = [
-    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
-    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
-    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
-  ];
-
-  let saved = [];
-  save(bookmarks).on('data', (data) => saved.push(data)).on('end', () => {
-    save(remove(topFolder)).on('end', () => {
-      assert.equal(saved.length, 5, 'all items should have been saved');
-      saved.map((item) => {
-        assert.throws(function () {
-          bmsrv.getItemTitle(item.id);
-        }, 'item should no longer exist');
-      });
-      done();
-    });
-  });
-};
-
-exports.testResolution = function (assert, done) {
-  let firstSave, secondSave;
-  createBookmarkItem().then((item) => {
-    firstSave = item;
-    assert.ok(item.updated, 'bookmark has updated time');
-    item.title = 'my title';
-    // Ensure delay so a different save time is set
-    return resolve(item);
-  }).then(saveP)
-  .then(items => {
-    let item = items[0];
-    secondSave = item;
-    assert.ok(firstSave.updated < secondSave.updated, 'snapshots have different update times');
-    firstSave.title = 'updated title';
-    return saveP(firstSave, { resolve: (mine, theirs) => {
-      assert.equal(mine.title, 'updated title', 'correct data for my object');
-      assert.equal(theirs.title, 'my title', 'correct data for their object');
-      assert.equal(mine.url, theirs.url, 'other data is equal');
-      assert.equal(mine.group, theirs.group, 'other data is equal');
-      assert.ok(mine !== firstSave, 'instance is not passed in');
-      assert.ok(theirs !== secondSave, 'instance is not passed in');
-      assert.equal(mine.toString(), '[object Object]', 'serialized objects');
-      assert.equal(theirs.toString(), '[object Object]', 'serialized objects');
-      mine.title = 'a new title';
-      return mine;
-    }});
-  }).then((results) => {
-    let result = results[0];
-    assert.equal(result.title, 'a new title', 'resolve handles results');
-  }).then(done).catch(assert.fail);
-};
-
-/*
- * Same as the resolution test, but with the 'unsaved' snapshot
- */
-exports.testResolutionMapping = function (assert, done) {
-  let bookmark = Bookmark({ title: 'moz', url: 'http://bookmarks4life.com/' });
-  let saved;
-
-  saveP(bookmark).then(data => {
-    saved = data[0];
-    saved.title = 'updated title';
-    // Ensure a delay for different updated times
-    return resolve(saved);
-  }).
-  then(saveP).
-  then(() => {
-    bookmark.title = 'conflicting title';
-    return saveP(bookmark, { resolve: (mine, theirs) => {
-      assert.equal(mine.title, 'conflicting title', 'correct data for my object');
-      assert.equal(theirs.title, 'updated title', 'correct data for their object');
-      assert.equal(mine.url, theirs.url, 'other data is equal');
-      assert.equal(mine.group, theirs.group, 'other data is equal');
-      assert.ok(mine !== bookmark, 'instance is not passed in');
-      assert.ok(theirs !== saved, 'instance is not passed in');
-      assert.equal(mine.toString(), '[object Object]', 'serialized objects');
-      assert.equal(theirs.toString(), '[object Object]', 'serialized objects');
-      mine.title = 'a new title';
-      return mine;
-    }});
-  }).then((results) => {
-    let result = results[0];
-    assert.equal(result.title, 'a new title', 'resolve handles results');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testUpdateTags = function (assert, done) {
-  createBookmarkItem({ tags: ['spidermonkey'] }).then(bookmark => {
-    bookmark.tags.add('jagermonkey');
-    bookmark.tags.add('ionmonkey');
-    bookmark.tags.delete('spidermonkey');
-    save(bookmark).on('data', saved => {
-      assert.equal(saved.tags.size, 2, 'should have 2 tags');
-      assert.ok(saved.tags.has('jagermonkey'), 'should have added tag');
-      assert.ok(saved.tags.has('ionmonkey'), 'should have added tag');
-      assert.ok(!saved.tags.has('spidermonkey'), 'should not have removed tag');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-/*
- * View `createBookmarkTree` in `./places-helper.js` to see
- * expected tree construction
- */
-
-exports.testSearchByGroupSimple = function (assert, done) {
-  createBookmarkTree().then(() => {
-     // In initial release of Places API, groups can only be queried
-     // via a 'simple query', which is one folder set, and no other
-     // parameters
-    return searchP({ group: UNSORTED });
-  }).then(results => {
-    let groups = results.filter(({type}) => type === 'group');
-    assert.equal(groups.length, 2, 'returns folders');
-    assert.equal(results.length, 7,
-      'should return all bookmarks and folders under UNSORTED');
-    assert.equal(groups[0].toString(), '[object Group]', 'returns instance');
-    return searchP({
-      group: groups.filter(({title}) => title === 'mozgroup')[0]
-    });
-  }).then(results => {
-    let groups = results.filter(({type}) => type === 'group');
-    assert.equal(groups.length, 1, 'returns one subfolder');
-    assert.equal(results.length, 6,
-      'returns all children bookmarks/folders');
-    assert.ok(results.filter(({url}) => url === 'http://w3schools.com/'),
-      'returns nested children');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testSearchByGroupComplex = function (assert, done) {
-  let mozgroup;
-  createBookmarkTree().then(results => {
-    mozgroup = results.filter(({title}) => title === 'mozgroup')[0];
-    return searchP({ group: mozgroup, query: 'javascript' });
-  }).then(results => {
-    assert.equal(results.length, 1, 'only one javascript result under mozgroup');
-    assert.equal(results[0].url, 'http://w3schools.com/', 'correct result');
-    return searchP({ group: mozgroup, url: '*.mozilla.org' });
-  }).then(results => {
-    assert.equal(results.length, 2, 'expected results');
-    assert.ok(
-      !results.filter(({url}) => /developer.mozilla/.test(url)).length,
-      'does not find results from other folders');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testSearchEmitters = function (assert, done) {
-  createBookmarkTree().then(() => {
-    let count = 0;
-    search({ tags: ['mozilla', 'firefox'] }).on('data', data => {
-      assert.ok(/mozilla|firefox/.test(data.title), 'one of the correct items');
-      assert.ok(data.tags.has('firefox'), 'has firefox tag');
-      assert.ok(data.tags.has('mozilla'), 'has mozilla tag');
-      assert.equal(data + '', '[object Bookmark]', 'returns bookmark');
-      count++;
-    }).on('end', data => {
-      assert.equal(count, 3, 'data event was called for each item');
-      assert.equal(data.length, 3,
-        'should return two bookmarks that have both mozilla AND firefox');
-      assert.equal(data[0].title, 'mozilla.com', 'returns correct bookmark');
-      assert.equal(data[1].title, 'mozilla.org', 'returns correct bookmark');
-      assert.equal(data[2].title, 'firefox', 'returns correct bookmark');
-      assert.equal(data[0] + '', '[object Bookmark]', 'returns bookmarks');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-exports.testSearchTags = function (assert, done) {
-  createBookmarkTree().then(() => {
-    // AND tags
-    return searchP({ tags: ['mozilla', 'firefox'] });
-  }).then(data => {
-    assert.equal(data.length, 3,
-      'should return two bookmarks that have both mozilla AND firefox');
-    assert.equal(data[0].title, 'mozilla.com', 'returns correct bookmark');
-    assert.equal(data[1].title, 'mozilla.org', 'returns correct bookmark');
-    assert.equal(data[2].title, 'firefox', 'returns correct bookmark');
-    assert.equal(data[0] + '', '[object Bookmark]', 'returns bookmarks');
-    return searchP([{tags: ['firefox']}, {tags: ['javascript']}]);
-  }).then(data => {
-    // OR tags
-    assert.equal(data.length, 6,
-      'should return all bookmarks with firefox OR javascript tag');
-  }).then(done).catch(assert.fail);
-};
-
-/*
- * Tests 4 scenarios
- * '*.mozilla.com'
- * 'mozilla.com'
- * 'http://mozilla.com/'
- * 'http://mozilla.com/*'
- */
-exports.testSearchURLForBookmarks = function*(assert) {
-  yield createBookmarkTree()
-  let data = yield searchP({ url: 'mozilla.org' });
-
-  assert.equal(data.length, 2, 'only URLs with host domain');
-  assert.equal(data[0].url, 'http://mozilla.org/');
-  assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
-
-  data = yield searchP({ url: '*.mozilla.org' });
-
-  assert.equal(data.length, 3, 'returns domain and when host is other than domain');
-  assert.equal(data[0].url, 'http://mozilla.org/');
-  assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
-  assert.equal(data[2].url, 'http://developer.mozilla.org/en-US/');
-
-  data = yield searchP({ url: 'http://mozilla.org' });
-
-  assert.equal(data.length, 1, 'only exact URL match');
-  assert.equal(data[0].url, 'http://mozilla.org/');
-
-  data = yield searchP({ url: 'http://mozilla.org/*' });
-
-  assert.equal(data.length, 2, 'only URLs that begin with query');
-  assert.equal(data[0].url, 'http://mozilla.org/');
-  assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
-
-  data = yield searchP([{ url: 'mozilla.org' }, { url: 'component.fm' }]);
-
-  assert.equal(data.length, 3, 'returns URLs that match EITHER query');
-  assert.equal(data[0].url, 'http://mozilla.org/');
-  assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
-  assert.equal(data[2].url, 'http://component.fm/');
-};
-
-/*
- * Searches url, title, tags
- */
-exports.testSearchQueryForBookmarks = function*(assert) {
-  yield createBookmarkTree();
-
-  let data = yield searchP({ query: 'thunder' });
-  assert.equal(data.length, 3);
-  assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
-  assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
-  assert.equal(data[2].title, 'thunderbird', 'query matches tag, url, or title');
-
-  data = yield searchP([{ query: 'rust' }, { query: 'component' }]);
-  // rust OR component
-  assert.equal(data.length, 3);
-  assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
-  assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
-  assert.equal(data[2].title, 'web audio components', 'query matches tag, url, or title');
-
-  data = yield searchP([{ query: 'moz', tags: ['javascript']}]);
-  assert.equal(data.length, 1);
-  assert.equal(data[0].title, 'mdn',
-    'only one item matches moz query AND has a javascript tag');
-};
-
-/*
- * Test caching on bulk calls.
- * Each construction of a bookmark item snapshot results in
- * the recursive lookup of parent groups up to the root groups --
- * ensure that the appropriate instances equal each other, and no duplicate
- * fetches are called
- *
- * Implementation-dependent, this checks the host event `sdk-places-bookmarks-get`,
- * and if implementation changes, this could increase or decrease
- */
-
-exports.testCaching = function (assert, done) {
-  let count = 0;
-  let stream = filter(request, ({event}) =>
-    /sdk-places-bookmarks-get/.test(event));
-  on(stream, 'data', handle);
-
-  let group = { type: 'group', title: 'mozgroup' };
-  let bookmarks = [
-    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark', group: group },
-    { title: 'moz2', url: 'http://moz2.com', type: 'bookmark', group: group },
-    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark', group: group }
-  ];
-
-  /*
-   * Use timeout in tests since the platform calls are synchronous
-   * and the counting event shim may not have occurred yet
-   */
-
-  saveP(bookmarks).then(() => {
-    assert.equal(count, 0, 'all new items and root group, no fetches should occur');
-    count = 0;
-    return saveP([
-      { title: 'moz4', url: 'http://moz4.com', type: 'bookmark', group: group },
-      { title: 'moz5', url: 'http://moz5.com', type: 'bookmark', group: group }
-    ]);
-  // Test `save` look-up
-  }).then(() => {
-    assert.equal(count, 1, 'should only look up parent once');
-    count = 0;
-    return searchP({ query: 'moz' });
-  }).then(results => {
-    // Should query for each bookmark (5) from the query (id -> data),
-    // their parent during `construct` (1) and the root shouldn't
-    // require a lookup
-    assert.equal(count, 6, 'lookup occurs once for each item and parent');
-    off(stream, 'data', handle);
-  }).then(done).catch(assert.fail);
-
-  function handle ({data}) {
-    return count++;
-  }
-};
-
-/*
- * Search Query Options
- */
-
-exports.testSearchCount = function (assert, done) {
-  let max = 8;
-  createBookmarkTree()
-  .then(testCount(1))
-  .then(testCount(2))
-  .then(testCount(3))
-  .then(testCount(5))
-  .then(testCount(10))
-  .then(done)
-  .catch(assert.fail);
-
-  function testCount (n) {
-    return function () {
-      return searchP({}, { count: n }).then(results => {
-        if (n > max) n = max;
-        assert.equal(results.length, n,
-          'count ' + n + ' returns ' + n + ' results');
-      });
-    };
-  }
-};
-
-exports.testSearchSortForBookmarks = function (assert, done) {
-  let urls = [
-    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
-    'http://developer.mozilla.com/', 'http://bandcamp.com/'
-  ];
-
-  saveP(
-    urls.map(url =>
-      Bookmark({ url: url, title: url.replace(/http:\/\/|\//g,'')}))
-  ).then(() => {
-    return searchP({}, { sort: 'title' });
-  }).then(results => {
-    checkOrder(results, [4,3,0,2,1]);
-    return searchP({}, { sort: 'title', descending: true });
-  }).then(results => {
-    checkOrder(results, [1,2,0,3,4]);
-    return searchP({}, { sort: 'url' });
-  }).then(results => {
-    checkOrder(results, [4,3,0,2,1]);
-    return searchP({}, { sort: 'url', descending: true });
-  }).then(results => {
-    checkOrder(results, [1,2,0,3,4]);
-    return addVisits(['http://mozilla.com/', 'http://mozilla.com']);
-  }).then(() =>
-    saveP(Bookmark({ url: 'http://github.com', title: 'github.com' }))
-  ).then(() => addVisits('http://bandcamp.com/'))
-  .then(() => searchP({ query: 'webfwd' }))
-  .then(results => {
-    results[0].title = 'new title for webfwd';
-    return saveP(results[0]);
-  })
-  .then(() =>
-    searchP({}, { sort: 'visitCount' })
-  ).then(results => {
-    assert.equal(results[5].url, 'http://mozilla.com/',
-      'last entry is the highest visit count');
-    return searchP({}, { sort: 'visitCount', descending: true });
-  }).then(results => {
-    assert.equal(results[0].url, 'http://mozilla.com/',
-      'first entry is the highest visit count');
-    return searchP({}, { sort: 'date' });
-  }).then(results => {
-    assert.equal(results[5].url, 'http://bandcamp.com/',
-      'latest visited should be first');
-    return searchP({}, { sort: 'date', descending: true });
-  }).then(results => {
-    assert.equal(results[0].url, 'http://bandcamp.com/',
-      'latest visited should be at the end');
-    return searchP({}, { sort: 'dateAdded' });
-  }).then(results => {
-    assert.equal(results[5].url, 'http://github.com/',
-     'last added should be at the end');
-    return searchP({}, { sort: 'dateAdded', descending: true });
-  }).then(results => {
-    assert.equal(results[0].url, 'http://github.com/',
-      'last added should be first');
-    return searchP({}, { sort: 'lastModified' });
-  }).then(results => {
-    assert.equal(results[5].url, 'http://mozilla.com/webfwd/',
-      'last modified should be last');
-    return searchP({}, { sort: 'lastModified', descending: true });
-  }).then(results => {
-    assert.equal(results[0].url, 'http://mozilla.com/webfwd/',
-      'last modified should be first');
-  }).then(done).catch(assert.fail);
-
-  function checkOrder (results, nums) {
-    assert.equal(results.length, nums.length, 'expected return count');
-    for (let i = 0; i < nums.length; i++) {
-      assert.equal(results[i].url, urls[nums[i]], 'successful order');
-    }
-  }
-};
-
-exports.testSearchComplexQueryWithOptions = function (assert, done) {
-  createBookmarkTree().then(() => {
-    return searchP([
-      { tags: ['rust'], url: '*.mozilla.org' },
-      { tags: ['javascript'], query: 'mozilla' }
-    ], { sort: 'title' });
-  }).then(results => {
-    let expected = [
-      'http://developer.mozilla.org/en-US/',
-      'http://mozilla.org/'
-    ];
-    for (let i = 0; i < expected.length; i++)
-      assert.equal(results[i].url, expected[i], 'correct ordering and item');
-  }).then(done).catch(assert.fail);
-};
-
-exports.testCheckSaveOrder = function (assert, done) {
-  let group = Group({ title: 'mygroup' });
-  let bookmarks = [
-    Bookmark({ url: 'http://url1.com', title: 'url1', group: group }),
-    Bookmark({ url: 'http://url2.com', title: 'url2', group: group }),
-    Bookmark({ url: 'http://url3.com', title: 'url3', group: group }),
-    Bookmark({ url: 'http://url4.com', title: 'url4', group: group }),
-    Bookmark({ url: 'http://url5.com', title: 'url5', group: group })
-  ];
-  saveP(bookmarks).then(results => {
-    for (let i = 0; i < bookmarks.length; i++)
-      assert.equal(results[i].url, bookmarks[i].url,
-        'correct ordering of bookmark results');
-  }).then(done).catch(assert.fail);
-};
-
-before(exports, (name, assert, done) => resetPlaces(done));
-after(exports, (name, assert, done) => resetPlaces(done));
-
-function saveP () {
-  return promisedEmitter(save.apply(null, Array.prototype.slice.call(arguments)));
-}
-
-function searchP () {
-  return promisedEmitter(search.apply(null, Array.prototype.slice.call(arguments)));
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-events.js
+++ /dev/null
@@ -1,328 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require('chrome');
-const { defer, all } = require('sdk/core/promise');
-const { filter } = require('sdk/event/utils');
-const { on, off } = require('sdk/event/core');
-const { events } = require('sdk/places/events');
-const { setTimeout } = require('sdk/timers');
-const { before, after } = require('sdk/test/utils');
-const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
-                getService(Ci.nsINavBookmarksService);
-const { release, platform } = require('node/os');
-
-const isOSX10_6 = (() => {
-  let vString = release();
-  return vString && /darwin/.test(platform()) && /10\.6/.test(vString);
-})();
-
-const { search } = require('sdk/places/history');
-const {
-  invalidResolve, createTree, createBookmark,
-  compareWithHost, addVisits, resetPlaces, createBookmarkItem,
-  removeVisits, historyBatch
-} = require('./places-helper');
-const { save, MENU, UNSORTED } = require('sdk/places/bookmarks');
-const { promisedEmitter } = require('sdk/places/utils');
-
-exports['test bookmark-item-added'] = function (assert, done) {
-  events.on('data', function handler ({type, data}) {
-    if (type !== 'bookmark-item-added') return;
-    if (data.title !== 'bookmark-added-title') return;
-    events.off('data', handler);
-
-    assert.equal(type, 'bookmark-item-added', 'correct type in bookmark-added event');
-    assert.equal(data.type, 'bookmark', 'correct data.type in bookmark-added event');
-    assert.ok(data.id != null, 'correct data.id in bookmark-added event');
-    assert.notEqual(data.parentId, null, 'correct data.parentId in bookmark-added event');
-    assert.ok(data.index >= 0, 'correct data.index in bookmark-added event');
-    assert.equal(data.url, 'http://moz.com/', 'correct data.url in bookmark-added event');
-    assert.notEqual(data.dateAdded, null, 'correct data.dateAdded in bookmark-added event');
-    done();
-  });
-  createBookmark({ title: 'bookmark-added-title' });
-};
-
-exports['test bookmark-item-changed'] = function (assert, done) {
-  let id;
-  let complete = makeCompleted(done);
-
-  // Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
-  // in debug builds) to prevent intermittent failures
-  if (isOSX10_6) {
-    assert.pass('skipping test in OSX 10.6');
-    return done();
-  }
-
-  function handler ({type, data}) {
-    if (type !== 'bookmark-item-changed') return;
-    if (data.id !== id) return;
-    // Abort if the 'bookmark-item-changed' event isn't for the `title` property,
-    // as sometimes the event can be for the `url` property.
-    // Intermittent failure, bug 969616
-    if (data.property !== 'title') return;
-
-    assert.equal(type, 'bookmark-item-changed',
-      'correct type in bookmark-item-changed event');
-    assert.equal(data.type, 'bookmark',
-      'correct data in bookmark-item-changed event');
-    assert.equal(data.property, 'title',
-      'correct property in bookmark-item-changed event');
-    assert.equal(data.value, 'bookmark-changed-title-2',
-      'correct value in bookmark-item-changed event');
-    assert.ok(data.id === id, 'correct id in bookmark-item-changed event');
-    assert.ok(data.parentId != null, 'correct data in bookmark-added event');
-
-    events.off('data', handler);
-    complete();
-  }
-  events.on('data', handler);
-
-  createBookmarkItem({ title: 'bookmark-changed-title' }).then(item => {
-    id = item.id;
-    item.title = 'bookmark-changed-title-2';
-    return saveP(item);
-  }).then(complete).catch(assert.fail);
-};
-
-exports['test bookmark-item-moved'] = function (assert, done) {
-  let id;
-  let complete = makeCompleted(done);
-  let previousIndex, previousParentId;
-
-  // Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
-  // in debug builds) to prevent intermittent failures
-  if (isOSX10_6) {
-    assert.ok(true, 'skipping test in OSX 10.6');
-    return done();
-  }
-
-  function handler ({type, data}) {
-    if (type !== 'bookmark-item-moved') return;
-    if (data.id !== id) return;
-    assert.equal(type, 'bookmark-item-moved',
-      'correct type in bookmark-item-moved event');
-    assert.equal(data.type, 'bookmark',
-      'correct data in bookmark-item-moved event');
-    assert.ok(data.id === id, 'correct id in bookmark-item-moved event');
-    assert.equal(data.previousParentId, previousParentId,
-      'correct previousParentId');
-    assert.equal(data.currentParentId, bmsrv.getFolderIdForItem(id),
-      'correct currentParentId');
-    assert.equal(data.previousIndex, previousIndex, 'correct previousIndex');
-    assert.equal(data.currentIndex, bmsrv.getItemIndex(id), 'correct currentIndex');
-
-    events.off('data', handler);
-    complete();
-  }
-  events.on('data', handler);
-
-  createBookmarkItem({
-    title: 'bookmark-moved-title',
-    group: UNSORTED
-  }).then(item => {
-    id = item.id;
-    previousIndex = bmsrv.getItemIndex(id);
-    previousParentId = bmsrv.getFolderIdForItem(id);
-    item.group = MENU;
-    return saveP(item);
-  }).then(complete).catch(assert.fail);
-};
-
-exports['test bookmark-item-removed'] = function (assert, done) {
-  let id;
-  let complete = makeCompleted(done);
-  function handler ({type, data}) {
-    if (type !== 'bookmark-item-removed') return;
-    if (data.id !== id) return;
-    assert.equal(type, 'bookmark-item-removed',
-      'correct type in bookmark-item-removed event');
-    assert.equal(data.type, 'bookmark',
-      'correct data in bookmark-item-removed event');
-    assert.ok(data.id === id, 'correct id in bookmark-item-removed event');
-    assert.equal(data.parentId, UNSORTED.id,
-      'correct parentId in bookmark-item-removed');
-    assert.equal(data.url, 'http://moz.com/',
-      'correct url in bookmark-item-removed event');
-    assert.equal(data.index, 0,
-      'correct index in bookmark-item-removed event');
-
-    events.off('data', handler);
-    complete();
-  }
-  events.on('data', handler);
-
-  createBookmarkItem({
-    title: 'bookmark-item-remove-title',
-    group: UNSORTED
-  }).then(item => {
-    id = item.id;
-    item.remove = true;
-    return saveP(item);
-  }).then(complete).catch(assert.fail);
-};
-
-exports['test bookmark-item-visited'] = function (assert, done) {
-  let id;
-  let complete = makeCompleted(done);
-  function handler ({type, data}) {
-    if (type !== 'bookmark-item-visited') return;
-    if (data.id !== id) return;
-    assert.equal(type, 'bookmark-item-visited',
-      'correct type in bookmark-item-visited event');
-    assert.ok(data.id === id, 'correct id in bookmark-item-visited event');
-    assert.equal(data.parentId, UNSORTED.id,
-      'correct parentId in bookmark-item-visited');
-    assert.ok(data.transitionType != null,
-      'has a transition type in bookmark-item-visited event');
-    assert.ok(data.time != null,
-      'has a time in bookmark-item-visited event');
-    assert.ok(data.visitId != null,
-      'has a visitId in bookmark-item-visited event');
-    assert.equal(data.url, 'http://bookmark-item-visited.com/',
-      'correct url in bookmark-item-visited event');
-
-    events.off('data', handler);
-    complete();
-  }
-  events.on('data', handler);
-
-  createBookmarkItem({
-    title: 'bookmark-item-visited',
-    url: 'http://bookmark-item-visited.com/'
-  }).then(item => {
-    id = item.id;
-    return addVisits('http://bookmark-item-visited.com/');
-  }).then(complete).catch(assert.fail);
-};
-
-exports['test history-start-batch, history-end-batch, history-start-clear'] = function (assert, done) {
-  let complete = makeCompleted(done, 4);
-  let startEvent = filter(events, ({type}) => type === 'history-start-batch');
-  let endEvent = filter(events, ({type}) => type === 'history-end-batch');
-  let clearEvent = filter(events, ({type}) => type === 'history-start-clear');
-  function startHandler ({type, data}) {
-    assert.pass('history-start-batch called');
-    assert.equal(type, 'history-start-batch',
-      'history-start-batch has correct type');
-    off(startEvent, 'data', startHandler);
-    on(endEvent, 'data', endHandler);
-    complete();
-  }
-  function endHandler ({type, data}) {
-    assert.pass('history-end-batch called');
-    assert.equal(type, 'history-end-batch',
-      'history-end-batch has correct type');
-    off(endEvent, 'data', endHandler);
-    complete();
-  }
-  function clearHandler ({type, data}) {
-    assert.pass('history-start-clear called');
-    assert.equal(type, 'history-start-clear',
-      'history-start-clear has correct type');
-    off(clearEvent, 'data', clearHandler);
-    complete();
-  }
-
-  on(startEvent, 'data', startHandler);
-  on(clearEvent, 'data', clearHandler);
-
-  historyBatch();
-  resetPlaces(complete);
-};
-
-exports['test history-visit, history-title-changed'] = function (assert, done) {
-  let complete = makeCompleted(() => {
-    off(titleEvents, 'data', titleHandler);
-    off(visitEvents, 'data', visitHandler);
-    done();
-  }, 6);
-  let visitEvents = filter(events, ({type}) => type === 'history-visit');
-  let titleEvents = filter(events, ({type}) => type === 'history-title-changed');
-
-  let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/'];
-
-  function visitHandler ({type, data}) {
-    assert.equal(type, 'history-visit', 'correct type in history-visit');
-    assert.ok(~urls.indexOf(data.url), 'history-visit has correct url');
-    assert.ok(data.visitId != null, 'history-visit has a visitId');
-    assert.ok(data.time != null, 'history-visit has a time');
-    assert.ok(data.sessionId != null, 'history-visit has a sessionId');
-    assert.ok(data.referringId != null, 'history-visit has a referringId');
-    assert.ok(data.transitionType != null, 'history-visit has a transitionType');
-    complete();
-  }
-
-  function titleHandler ({type, data}) {
-    assert.equal(type, 'history-title-changed',
-      'correct type in history-title-changed');
-    assert.ok(~urls.indexOf(data.url),
-      'history-title-changed has correct url');
-    assert.ok(data.title, 'history-title-changed has title');
-    complete();
-  }
-
-  on(titleEvents, 'data', titleHandler);
-  on(visitEvents, 'data', visitHandler);
-  addVisits(urls);
-}
-
-exports['test history-delete-url'] = function (assert, done) {
-  let complete = makeCompleted(() => {
-    events.off('data', handler);
-    done();
-  }, 3);
-  let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/'];
-  function handler({type, data}) {
-    if (type !== 'history-delete-url') return;
-    assert.equal(type, 'history-delete-url',
-      'history-delete-url has correct type');
-    assert.ok(~urls.indexOf(data.url), 'history-delete-url has correct url');
-    complete();
-  }
-
-  events.on('data', handler);
-  addVisits(urls).then(() => {
-    removeVisits(urls);
-  });
-};
-
-exports['test history-page-changed'] = function (assert) {
-  assert.pass('history-page-changed tested in test-places-favicons');
-};
-
-exports['test history-delete-visits'] = function (assert) {
-  assert.pass('TODO test history-delete-visits');
-};
-
-// Bug 1060843
-// Wait a tick before finishing tests, as some bookmark activities require
-// completion of a result for events. For example, when creating a bookmark,
-// a `bookmark-item-added` event is fired, listened to by the first test here,
-// while constructing the bookmark item requires subsequent calls to that bookmark item.
-// If we destroy the underlying bookmark immediately, these calls will fail.
-//
-// The places SDK abstraction around this alleviates it, but these are low level events.
-after(exports, (name, assert, done) => setTimeout(() => resetPlaces(done), 1));
-before(exports, (name, assert, done) => resetPlaces(done));
-
-function saveP () {
-  return promisedEmitter(save.apply(null, Array.prototype.slice.call(arguments)));
-}
-
-function makeCompleted (done, countTo) {
-  let count = 0;
-  countTo = countTo || 2;
-  return function () {
-    if (++count === countTo) done();
-  };
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-favicon.js
+++ /dev/null
@@ -1,242 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci, Cu } = require('chrome');
-const { getFavicon } = require('sdk/places/favicon');
-const tabs = require('sdk/tabs');
-const open = tabs.open;
-const port = 8099;
-const host = 'http://localhost:' + port;
-const { onFaviconChange, serve, binFavicon } = require('./favicon-helpers');
-const { once } = require('sdk/system/events');
-const { resetPlaces } = require('./places-helper');
-const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
-                         getService(Ci.nsIFaviconService);
-
-exports.testStringGetFaviconCallbackSuccess = function*(assert) {
-  let name = 'callbacksuccess'
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let favicon = host + '/' + name + '.ico';
-  let tab;
-
-  let wait = new Promise(resolve => {
-    onFaviconChange(url).then((faviconUrl) => {
-      getFavicon(url, (url) => {
-        assert.equal(favicon, url, 'Callback returns correct favicon url');
-        resolve();
-      });
-    });
-  });
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield wait;
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-exports.testStringGetFaviconCallbackFailure = function*(assert) {
-  let name = 'callbackfailure';
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let tab;
-
-  let wait = waitAndExpire(url);
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield wait;
-
-  assert.pass("Getting favicon");
-
-  yield new Promise(resolve => {
-    getFavicon(url, (url) => {
-      assert.equal(url, null, 'Callback returns null');
-      resolve();
-    });
-  });
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-exports.testStringGetFaviconPromiseSuccess = function*(assert) {
-  let name = 'promisesuccess'
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let favicon = host + '/' + name + '.ico';
-  let tab;
-
-  let wait = onFaviconChange(url);
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield wait;
-
-  assert.pass("Getting favicon");
-
-  yield getFavicon(url).then((url) => {
-    assert.equal(url, favicon, 'Callback returns null');
-  }, () => {
-    assert.fail('Reject should not be called');
-  });
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-exports.testStringGetFaviconPromiseFailure = function*(assert) {
-  let name = 'promisefailure'
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let tab;
-
-  let wait = waitAndExpire(url);
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield wait;
-
-  assert.pass("Getting favicon");
-
-  yield getFavicon(url).then(invalidResolve(assert), validReject(assert, 'expired url'));
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-exports.testTabsGetFaviconPromiseSuccess = function*(assert) {
-  let name = 'tabs-success'
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let favicon = host + '/' + name + '.ico';
-  let tab;
-
-  let iconPromise = onFaviconChange(url);
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield iconPromise;
-
-  assert.pass("Getting favicon");
-
-  yield getFavicon(tab).then((url) => {
-    assert.equal(url, favicon, "getFavicon should return url for tab");
-  });
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-
-exports.testTabsGetFaviconPromiseFailure = function*(assert) {
-  let name = 'tabs-failure'
-  let srv = yield makeServer(name);
-  let url = host + '/' + name + '.html';
-  let tab;
-
-  let wait = waitAndExpire(url);
-
-  assert.pass("Opening tab");
-
-  open({
-    url: url,
-    onOpen: (newTab) => tab = newTab,
-    inBackground: true
-  });
-
-  yield wait;
-
-  assert.pass("Getting favicon");
-
-  yield getFavicon(tab).then(invalidResolve(assert), validReject(assert, 'expired tab'));
-
-  assert.pass("Complete");
-
-  yield complete(tab, srv);
-};
-
-exports.testRejects = function*(assert) {
-  yield getFavicon({})
-    .then(invalidResolve(assert), validReject(assert, 'Object'));
-
-  yield getFavicon(null)
-    .then(invalidResolve(assert), validReject(assert, 'null'));
-
-  yield getFavicon(undefined)
-    .then(invalidResolve(assert), validReject(assert, 'undefined'));
-
-  yield getFavicon([])
-    .then(invalidResolve(assert), validReject(assert, 'Array'));
-};
-
-var invalidResolve = (assert) => () => assert.fail('Promise should not be resolved successfully');
-var validReject = (assert, name) => () => assert.pass(name + ' correctly rejected');
-
-var makeServer = (name) => serve({
-  name: name,
-  favicon: binFavicon,
-  port: port,
-  host: host
-});
-
-var waitAndExpire = (url) => new Promise(resolve => {
-  onFaviconChange(url).then(() => {
-    once('places-favicons-expired', resolve);
-    faviconService.expireAllFavicons();
-  });
-});
-
-var complete = (tab, srv) => new Promise(resolve => {
-  tab.close(() => {
-    resetPlaces(() => {
-      srv.stop(resolve);
-    });
-  });
-});
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-history.js
+++ /dev/null
@@ -1,244 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require('chrome');
-const { defer, all } = require('sdk/core/promise');
-const { has } = require('sdk/util/array');
-const { setTimeout } = require('sdk/timers');
-const { before, after } = require('sdk/test/utils');
-const { set } = require('sdk/preferences/service');
-const {
-  search
-} = require('sdk/places/history');
-const {
-  invalidResolve, createTree,
-  compareWithHost, addVisits, resetPlaces
-} = require('./places-helper');
-const { promisedEmitter } = require('sdk/places/utils');
-
-exports.testEmptyQuery = function*(assert) {
-  let within = toBeWithin();
-  yield addVisits([
-    'http://simplequery-1.com', 'http://simplequery-2.com'
-  ]);
-
-  let results = yield searchP();
-  assert.equal(results.length, 2, 'Correct number of entries returned');
-  assert.equal(results[0].url, 'http://simplequery-1.com/',
-    'matches url');
-  assert.equal(results[1].url, 'http://simplequery-2.com/',
-    'matches url');
-  assert.equal(results[0].title, 'Test visit for ' + 'http://simplequery-1.com',
-    'title matches');
-  assert.equal(results[1].title, 'Test visit for ' + 'http://simplequery-2.com',
-    'title matches');
-  assert.equal(results[0].visitCount, 1, 'matches access');
-  assert.equal(results[1].visitCount, 1, 'matches access');
-  assert.ok(within(results[0].time), 'accurate access time');
-  assert.ok(within(results[1].time), 'accurate access time');
-  assert.equal(Object.keys(results[0]).length, 4,
-    'no addition exposed properties on history result');
-};
-
-exports.testVisitCount = function*(assert) {
-  yield addVisits([
-    'http://simplequery-1.com', 'http://simplequery-1.com',
-    'http://simplequery-1.com', 'http://simplequery-1.com'
-  ]);
-  let results = yield searchP();
-  assert.equal(results.length, 1, 'Correct number of entries returned');
-  assert.equal(results[0].url, 'http://simplequery-1.com/', 'correct url');
-  assert.equal(results[0].visitCount, 4, 'matches access count');
-};
-
-/*
- * Tests 4 scenarios
- * '*.mozilla.org'
- * 'mozilla.org'
- * 'http://mozilla.org/'
- * 'http://mozilla.org/*'
- */
-exports.testSearchURLForHistory = function*(assert) {
-  yield addVisits([
-    'http://developer.mozilla.org', 'http://mozilla.org',
-    'http://mozilla.org/index', 'https://mozilla.org'
-  ]);
-
-  let results = yield searchP({ url: 'http://mozilla.org/' });
-  assert.equal(results.length, 1, 'should just be an exact match');
-
-  results = yield searchP({ url: '*.mozilla.org' });
-  assert.equal(results.length, 4, 'returns all entries');
-
-  results = yield searchP({ url: 'mozilla.org' });
-  assert.equal(results.length, 3, 'returns entries where mozilla.org is host');
-
-  results = yield searchP({ url: 'http://mozilla.org/*' });
-  assert.equal(results.length, 2, 'should match anything starting with substring');
-};
-
-// Disabling due to intermittent Bug 892619
-// TODO solve this
-/*
-exports.testSearchTimeRange = function (assert, done) {
-  let firstTime, secondTime;
-  addVisits([
-    'http://earlyvisit.org', 'http://earlyvisit.org/earlytown.html'
-  ]).then(searchP).then(results => {
-    firstTime = results[0].time;
-    var deferred = defer();
-    setTimeout(() => deferred.resolve(), 1000);
-    return deferred.promise;
-  }).then(() => {
-    return addVisits(['http://newvisit.org', 'http://newvisit.org/whoawhoa.html']);
-  }).then(searchP).then(results => {
-    results.filter(({url, time}) => {
-      if (/newvisit/.test(url)) secondTime = time;
-    });
-    return searchP({ from: firstTime - 1000 });
-  }).then(results => {
-    assert.equal(results.length, 4, 'should return all entries');
-    return searchP({ to: firstTime + 500 });
-  }).then(results => {
-    assert.equal(results.length, 2, 'should return only first entries');
-    results.map(item => {
-      assert.ok(/earlyvisit/.test(item.url), 'correct entry');
-    });
-    return searchP({ from: firstTime + 500 });
-  }).then(results => {
-    assert.equal(results.length, 2, 'should return only last entries');
-    results.map(item => {
-      assert.ok(/newvisit/.test(item.url), 'correct entry');
-    });
-    done();
-  });
-};
-*/
-exports.testSearchQueryForHistory = function*(assert) {
-  yield addVisits([
-    'http://mozilla.com', 'http://webaud.io', 'http://mozilla.com/webfwd'
-  ]);
-
-  let results = yield searchP({ query: 'moz' });
-  assert.equal(results.length, 2, 'should return urls that match substring');
-  results.map(({url}) => {
-    assert.ok(/moz/.test(url), 'correct item');
-  });
-
-  results = yield searchP([{ query: 'webfwd' }, { query: 'aud.io' }]);
-  assert.equal(results.length, 2, 'should OR separate queries');
-  results.map(({url}) => {
-    assert.ok(/webfwd|aud\.io/.test(url), 'correct item');
-  });
-};
-
-/*
- * Query Options
- */
-
-exports.testSearchCount = function (assert, done) {
-  addVisits([
-    'http://mozilla.com', 'http://webaud.io', 'http://mozilla.com/webfwd',
-    'http://developer.mozilla.com', 'http://bandcamp.com'
-  ]).then(testCount(1))
-  .then(testCount(2))
-  .then(testCount(3))
-  .then(testCount(5))
-  .then(done);
-
-  function testCount (n) {
-    return function () {
-      return searchP({}, { count: n }).then(results => {
-        assert.equal(results.length, n,
-          'count ' + n + ' returns ' + n + ' results');
-      });
-    };
-  }
-};
-
-exports.testSearchSortForHistory = function*(assert) {
-  function checkOrder (results, nums) {
-    assert.equal(results.length, nums.length, 'expected return count');
-    for (let i = 0; i < nums.length; i++) {
-      assert.equal(results[i].url, places[nums[i]], 'successful order');
-    }
-  }
-
-  let places = [
-    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
-    'http://developer.mozilla.com/', 'http://bandcamp.com/'
-  ];
-  yield addVisits(places);
-
-  let results = yield searchP({}, { sort: 'title' });
-  checkOrder(results, [4,3,0,2,1]);
-
-  results = yield searchP({}, { sort: 'title', descending: true });
-  checkOrder(results, [1,2,0,3,4]);
-
-  results = yield searchP({}, { sort: 'url' });
-  checkOrder(results, [4,3,0,2,1]);
-
-  results = yield searchP({}, { sort: 'url', descending: true });
-  checkOrder(results, [1,2,0,3,4]);
-
-  yield addVisits('http://mozilla.com'); // for visit conut
-  yield addVisits('http://github.com'); // for checking date
-
-  results = yield searchP({}, { sort: 'visitCount' });
-  assert.equal(results[5].url, 'http://mozilla.com/',
-    'last entry is the highest visit count');
-
-  results = yield  searchP({}, { sort: 'visitCount', descending: true });
-  assert.equal(results[0].url, 'http://mozilla.com/',
-    'first entry is the highest visit count');
-
-  results = yield  searchP({}, { sort: 'date' });
-  assert.equal(results[5].url, 'http://github.com/',
-    'latest visited should be first');
-
-  results = yield  searchP({}, { sort: 'date', descending: true });
-  assert.equal(results[0].url, 'http://github.com/',
-    'latest visited should be at the end');
-};
-
-exports.testEmitters = function (assert, done) {
-  let urls = [
-    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
-    'http://developer.mozilla.com/', 'http://bandcamp.com/'
-  ];
-  addVisits(urls).then(() => {
-    let count = 0;
-    search().on('data', item => {
-      assert.ok(~urls.indexOf(item.url), 'data value found in url list');
-      count++;
-    }).on('end', results => {
-      assert.equal(results.length, 5, 'correct count of items');
-      assert.equal(count, 5, 'data event called 5 times');
-      done();
-    });
-  });
-};
-
-function toBeWithin (range) {
-  range = range || 2000;
-  var current = new Date() * 1000; // convert to microseconds
-  return compared => {
-    return compared - current < range;
-  };
-}
-
-function searchP () {
-  return promisedEmitter(search.apply(null, Array.prototype.slice.call(arguments)));
-}
-
-before(exports, (name, assert, done) => resetPlaces(done));
-after(exports, (name, assert, done) => resetPlaces(done));
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-host.js
+++ /dev/null
@@ -1,301 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require('chrome');
-const { defer, all } = require('sdk/core/promise');
-const { setTimeout } = require('sdk/timers');
-const { newURI } = require('sdk/url/utils');
-const { send } = require('sdk/addon/events');
-const { set } = require('sdk/preferences/service');
-const { before, after } = require('sdk/test/utils');
-
-require('sdk/places/host/host-bookmarks');
-require('sdk/places/host/host-tags');
-require('sdk/places/host/host-query');
-const {
-  invalidResolve, createTree,
-  compareWithHost, createBookmark, createBookmarkTree, resetPlaces
-} = require('./places-helper');
-
-const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
-                    getService(Ci.nsINavBookmarksService);
-const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
-              getService(Ci.nsINavHistoryService);
-const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
-              getService(Ci.nsITaggingService);
-
-exports.testBookmarksCreate = function*(assert) {
-  let items = [{
-    title: 'my title',
-    url: 'http://test-places-host.com/testBookmarksCreate/',
-    tags: ['some', 'tags', 'yeah'],
-    type: 'bookmark'
-  }, {
-    title: 'my folder',
-    type: 'group',
-    group: bmsrv.bookmarksMenuFolder
-  }, {
-    type: 'separator',
-    group: bmsrv.unfiledBookmarksFolder
-  }];
-
-  yield all(items.map((item) => {
-    return send('sdk-places-bookmarks-create', item).then((data) => {
-      compareWithHost(assert, data);
-    });
-  }));
-};
-
-exports.testBookmarksCreateFail = function (assert, done) {
-  let items = [{
-    title: 'my title',
-    url: 'not-a-url',
-    type: 'bookmark'
-  }, {
-    type: 'group',
-    group: bmsrv.bookmarksMenuFolder
-  }, {
-    group: bmsrv.unfiledBookmarksFolder
-  }];
-  all(items.map(function (item) {
-    return send('sdk-places-bookmarks-create', item).catch(function (reason) {
-      assert.ok(reason, 'bookmark create should fail');
-    });
-  })).then(done);
-};
-
-exports.testBookmarkLastUpdated = function (assert, done) {
-  let timestamp;
-  let item;
-  createBookmark({
-    url: 'http://test-places-host.com/testBookmarkLastUpdated'
-  }).then(function (data) {
-    item = data;
-    timestamp = item.updated;
-    return send('sdk-places-bookmarks-last-updated', { id: item.id });
-  }).then(function (updated) {
-    let { resolve, promise } = defer();
-    assert.equal(timestamp, updated, 'should return last updated time');
-    item.title = 'updated mozilla';
-    setTimeout(() => {
-      resolve(send('sdk-places-bookmarks-save', item));
-    }, 100);
-    return promise;
-  }).then(function (data) {
-    assert.ok(data.updated > timestamp, 'time has elapsed and updated the updated property');
-    done();
-  });
-};
-
-exports.testBookmarkRemove = function (assert, done) {
-  let id;
-  createBookmark({
-    url: 'http://test-places-host.com/testBookmarkRemove/'
-  }).then(function (data) {
-    id = data.id;
-    compareWithHost(assert, data); // ensure bookmark exists
-    bmsrv.getItemTitle(id); // does not throw an error
-    return send('sdk-places-bookmarks-remove', data);
-  }).then(function () {
-    assert.throws(function () {
-      bmsrv.getItemTitle(id);
-    }, 'item should no longer exist');
-    done();
-  }, assert.fail);
-};
-
-exports.testBookmarkGet = function (assert, done) {
-  let bookmark;
-  createBookmark({
-    url: 'http://test-places-host.com/testBookmarkGet/'
-  }).then(function (data) {
-    bookmark = data;
-    return send('sdk-places-bookmarks-get', { id: data.id });
-  }).then(function (data) {
-    'title url index group updated type tags'.split(' ').map(function (prop) {
-      if (prop === 'tags') {
-        for (let tag of bookmark.tags) {
-          assert.ok(~data.tags.indexOf(tag),
-            'correctly fetched tag ' + tag);
-        }
-        assert.equal(bookmark.tags.length, data.tags.length,
-          'same amount of tags');
-      }
-      else
-        assert.equal(bookmark[prop], data[prop], 'correctly fetched ' + prop);
-    });
-    done();
-  });
-};
-
-exports.testTagsTag = function (assert, done) {
-  let url;
-  createBookmark({
-    url: 'http://test-places-host.com/testTagsTag/',
-  }).then(function (data) {
-    url = data.url;
-    return send('sdk-places-tags-tag', {
-      url: data.url, tags: ['mozzerella', 'foxfire']
-    });
-  }).then(function () {
-    let tags = tagsrv.getTagsForURI(newURI(url));
-    assert.ok(~tags.indexOf('mozzerella'), 'first tag found');
-    assert.ok(~tags.indexOf('foxfire'), 'second tag found');
-    assert.ok(~tags.indexOf('firefox'), 'default tag found');
-    assert.equal(tags.length, 3, 'no extra tags');
-    done();
-  });
-};
-
-exports.testTagsUntag = function (assert, done) {
-  let item;
-  createBookmark({
-    url: 'http://test-places-host.com/testTagsUntag/',
-    tags: ['tag1', 'tag2', 'tag3']
-  }).then(data => {
-    item = data;
-    return send('sdk-places-tags-untag', {
-      url: item.url,
-      tags: ['tag2', 'firefox']
-    });
-  }).then(function () {
-    let tags = tagsrv.getTagsForURI(newURI(item.url));
-    assert.ok(~tags.indexOf('tag1'), 'first tag persisted');
-    assert.ok(~tags.indexOf('tag3'), 'second tag persisted');
-    assert.ok(!~tags.indexOf('firefox'), 'first tag removed');
-    assert.ok(!~tags.indexOf('tag2'), 'second tag removed');
-    assert.equal(tags.length, 2, 'no extra tags');
-    done();
-  });
-};
-
-exports.testTagsGetURLsByTag = function (assert, done) {
-  let item;
-  createBookmark({
-    url: 'http://test-places-host.com/testTagsGetURLsByTag/'
-  }).then(function (data) {
-    item = data;
-    return send('sdk-places-tags-get-urls-by-tag', {
-      tag: 'firefox'
-    });
-  }).then(function(urls) {
-    assert.equal(item.url, urls[0], 'returned correct url');
-    assert.equal(urls.length, 1, 'returned only one url');
-    done();
-  });
-};
-
-exports.testTagsGetTagsByURL = function (assert, done) {
-  let item;
-  createBookmark({
-    url: 'http://test-places-host.com/testTagsGetURLsByTag/',
-    tags: ['firefox', 'mozilla', 'metal']
-  }).then(function (data) {
-    item = data;
-    return send('sdk-places-tags-get-tags-by-url', {
-      url: data.url,
-    });
-  }).then(function(tags) {
-    assert.ok(~tags.indexOf('firefox'), 'returned first tag');
-    assert.ok(~tags.indexOf('mozilla'), 'returned second tag');
-    assert.ok(~tags.indexOf('metal'), 'returned third tag');
-    assert.equal(tags.length, 3, 'returned all tags');
-    done();
-  });
-};
-
-exports.testHostQuery = function (assert, done) {
-  all([
-    createBookmark({
-      url: 'http://firefox.com/testHostQuery/',
-      tags: ['firefox', 'mozilla']
-    }),
-    createBookmark({
-      url: 'http://mozilla.com/testHostQuery/',
-      tags: ['mozilla']
-    }),
-    createBookmark({ url: 'http://thunderbird.com/testHostQuery/' })
-  ]).then(data => {
-    return send('sdk-places-query', {
-      queries: { tags: ['mozilla'] },
-      options: { sortingMode: 6, queryType: 1 } // sort by URI ascending, bookmarks only
-    });
-  }).then(results => {
-    assert.equal(results.length, 2, 'should only return two');
-    assert.equal(results[0].url,
-      'http://mozilla.com/testHostQuery/', 'is sorted by URI asc');
-    return send('sdk-places-query', {
-      queries: { tags: ['mozilla'] },
-      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
-    });
-  }).then(results => {
-    assert.equal(results.length, 2, 'should only return two');
-    assert.equal(results[0].url,
-      'http://firefox.com/testHostQuery/', 'is sorted by URI desc');
-    done();
-  });
-};
-
-exports.testHostMultiQuery = function (assert, done) {
-  all([
-    createBookmark({
-      url: 'http://firefox.com/testHostMultiQuery/',
-      tags: ['firefox', 'mozilla']
-    }),
-    createBookmark({
-      url: 'http://mozilla.com/testHostMultiQuery/',
-      tags: ['mozilla']
-    }),
-    createBookmark({ url: 'http://thunderbird.com/testHostMultiQuery/' })
-  ]).then(data => {
-    return send('sdk-places-query', {
-      queries: [{ tags: ['firefox'] }, { uri: 'http://thunderbird.com/testHostMultiQuery/' }],
-      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
-    });
-  }).then(results => {
-    assert.equal(results.length, 2, 'should return 2 results ORing queries');
-    assert.equal(results[0].url,
-      'http://firefox.com/testHostMultiQuery/', 'should match URL or tag');
-    assert.equal(results[1].url,
-      'http://thunderbird.com/testHostMultiQuery/', 'should match URL or tag');
-    return send('sdk-places-query', {
-      queries: [{ tags: ['firefox'], url: 'http://mozilla.com/testHostMultiQuery/' }],
-      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
-    });
-  }).then(results => {
-    assert.equal(results.length, 0, 'query props should be AND\'d');
-    done();
-  });
-};
-
-exports.testGetAllBookmarks = function (assert, done) {
-  createBookmarkTree().then(() => {
-    return send('sdk-places-bookmarks-get-all', {});
-  }).then(res => {
-    assert.equal(res.length, 8, 'all bookmarks returned');
-    done();
-  }, assert.fail);
-};
-
-exports.testGetAllChildren = function (assert, done) {
-  createBookmarkTree().then(results => {
-    return send('sdk-places-bookmarks-get-children', {
-      id: results.filter(({title}) => title === 'mozgroup')[0].id
-    });
-  }).then(results => {
-    assert.equal(results.length, 5,
-      'should return all children and folders at a single depth');
-    done();
-  });
-};
-
-before(exports, (name, assert, done) => resetPlaces(done));
-after(exports, (name, assert, done) => resetPlaces(done));
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/lib/test-places-utils.js
+++ /dev/null
@@ -1,78 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { defer, all } = require('sdk/core/promise');
-const { setTimeout } = require('sdk/timers');
-const { TreeNode } = require('sdk/places/utils');
-
-exports['test construct tree'] = function (assert) {
-  let tree = TreeNode(1);
-  tree.add([2, 3, 4]);
-  tree.get(2).add([2.1, 2.2, 2.3]);
-  let newTreeNode = TreeNode(4.3);
-  newTreeNode.add([4.31, 4.32]);
-  tree.get(4).add([4.1, 4.2, newTreeNode]);
-
-  assert.equal(tree.get(2).value, 2, 'get returns node with correct value');
-  assert.equal(tree.get(2.3).value, 2.3, 'get returns node with correct value');
-  assert.equal(tree.get(4.32).value, 4.32, 'get returns node even if created from nested node');
-  assert.equal(tree.get(4).children.length, 3, 'nodes have correct children length');
-  assert.equal(tree.get(3).children.length, 0, 'nodes have correct children length');
-
-  assert.equal(tree.get(4).get(4.32).value, 4.32, 'node.get descends from itself');
-  assert.equal(tree.get(4).get(2), null, 'node.get descends from itself fails if not descendant');
-};
-
-exports['test walk'] = function (assert, done) {
-  let resultsAll = [];
-  let resultsNode = [];
-  let tree = TreeNode(1);
-  tree.add([2, 3, 4]);
-  tree.get(2).add([2.1, 2.2]);
-
-  tree.walk(function (node) {
-    resultsAll.push(node.value);
-  }).then(() => {
-    [1, 2, 2.1, 2.2, 3, 4].forEach(num => {
-      assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
-    });
-    return tree.get(2).walk(node => resultsNode.push(node.value));
-  }).then(() => {
-    [2, 2.1, 2.2].forEach(function (num) {
-      assert.ok(~resultsNode.indexOf(num), 'function applied to each node from node');
-    });
-  }).catch(assert.fail).then(done);
-};
-
-exports['test async walk'] = function (assert, done) {
-  let resultsAll = [];
-  let tree = TreeNode(1);
-  tree.add([2, 3, 4]);
-  tree.get(2).add([2.1, 2.2]);
-
-  tree.walk(function (node) {
-    let deferred = defer();
-    setTimeout(function () {
-      resultsAll.push(node.value);
-      deferred.resolve(node.value);
-    }, node.value === 2 ? 50 : 5);
-    return deferred.promise;
-  }).then(function () {
-    [1, 2, 2.1, 2.2, 3, 4].forEach(function (num) {
-      assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
-    });
-    assert.ok(resultsAll.indexOf(2) < resultsAll.indexOf(2.1),
-      'child should wait for parent to complete');
-    assert.ok(resultsAll.indexOf(2) < resultsAll.indexOf(2.2),
-      'child should wait for parent to complete');
-    done();
-  });
-};
deleted file mode 100644
--- a/addon-sdk/source/test/addons/places/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-places@jetpack",
-  "main": "./lib/main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/predefined-id-with-at/lib/main.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { id, preferencesBranch } = require('sdk/self');
-const simple = require('sdk/simple-prefs');
-const service = require('sdk/preferences/service');
-const { getAddonByID } = require('sdk/addon/manager');
-
-const expected_id = 'predefined-id@test';
-
-exports.testExpectedID = function(assert) {
-  assert.equal(id, expected_id, 'ID is as expected');
-  assert.equal(preferencesBranch, expected_id, 'preferences-branch is ' + expected_id);
-
-  assert.equal(simple.prefs.test, 5, 'test pref is 5');
-
-  simple.prefs.test2 = '25';
-  assert.equal(service.get('extensions.'+expected_id+'.test2'), '25', 'test pref is 25');
-  assert.equal(service.get('extensions.'+expected_id+'.test2'), simple.prefs.test2, 'test pref is 25');
-}
-
-exports.testSelfID = function*(assert) {
-  assert.equal(typeof(id), 'string', 'self.id is a string');
-  assert.ok(id.length > 0, 'self.id not empty');
-
-  let addon = yield getAddonByID(id);
-  assert.equal(addon.id, id, 'found addon with self.id');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/predefined-id-with-at/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "id": "predefined-id@test",
-    "fullName": "predefined ID test",
-    "author": "Erik Vold",
-    "preferences": [{
-        "name": "test",
-        "type": "integer",
-        "title": "test",
-        "value": 5
-    }],
-    "main": "./lib/main.js",
-    "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/preferences-branch/lib/main.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { id, preferencesBranch } = require('sdk/self');
-const simple = require('sdk/simple-prefs');
-const service = require('sdk/preferences/service');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testPreferencesBranch = function(assert) {
-  assert.equal(preferencesBranch, 'human-readable', 'preferencesBranch is human-readable');
-  assert.equal(simple.prefs.test42, true, 'test42 is true');
-
-  simple.prefs.test43 = 'movie';
-  assert.equal(service.get('extensions.human-readable.test43'), 'movie', 'test43 is a movie');
-
-}
-
-// from `/test/test-self.js`, adapted to `sdk/test/assert` API
-exports.testSelfID = function*(assert) {
-  assert.equal(typeof(id), 'string', 'self.id is a string');
-  assert.ok(id.length > 0, 'self.id not empty');
-  let addon = yield getAddonByID(id);
-  assert.ok(addon, 'found addon with self.id');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/preferences-branch/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "id": "test-preferences-branch@jetpack",
-    "fullName": "preferences-branch test",
-    "author": "Tomislav Jovanovic",
-    "preferences": [{
-        "name": "test42",
-        "type": "bool",
-        "title": "test42",
-        "value": true
-    }],
-    "preferences-branch": "human-readable",
-    "main": "./lib/main.js",
-    "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/main.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { merge } = require('sdk/util/object');
-const app = require('sdk/system/xul-app');
-
-merge(module.exports,
-  require('./test-tabs'),
-  require('./test-page-mod'),
-  require('./test-private-browsing'),
-  require('./test-sidebar')
-);
-
-// Doesn't make sense to test window-utils and windows on fennec,
-// as there is only one window which is never private. Also ignore
-// unsupported modules (panel, selection)
-if (!app.is('Fennec')) {
-  merge(module.exports,
-    require('./test-selection'),
-    require('./test-panel'),
-    require('./test-window-tabs'),
-    require('./test-windows')
-  );
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-	"id": "private-browsing-mode-test@jetpack",
-	"permissions": {
-		"private-browsing": true
-	},
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/sidebar/utils.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/. */
-'use strict';
-
-const { Cu } = require('chrome');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { fromIterator } = require('sdk/util/array');
-
-const BUILTIN_SIDEBAR_MENUITEMS = exports.BUILTIN_SIDEBAR_MENUITEMS = [
-  'menu_socialSidebar',
-  'menu_historySidebar',
-  'menu_bookmarksSidebar',
-];
-
-function isSidebarShowing(window) {
-  window = window || getMostRecentBrowserWindow();
-  let sidebar = window.document.getElementById('sidebar-box');
-  return !sidebar.hidden;
-}
-exports.isSidebarShowing = isSidebarShowing;
-
-function getSidebarMenuitems(window) {
-  window = window || getMostRecentBrowserWindow();
-  return fromIterator(window.document.querySelectorAll('#viewSidebarMenu menuitem'));
-}
-exports.getSidebarMenuitems = getSidebarMenuitems;
-
-function getExtraSidebarMenuitems() {
-  let menuitems = getSidebarMenuitems();
-  return menuitems.filter(function(mi) {
-    return BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) < 0;
-  });
-}
-exports.getExtraSidebarMenuitems = getExtraSidebarMenuitems;
-
-function makeID(id) {
-  return 'jetpack-sidebar-' + id;
-}
-exports.makeID = makeID;
-
-function simulateCommand(ele) {
-  let window = ele.ownerGlobal;
-  let { document } = window;
-  var evt = document.createEvent('XULCommandEvent');
-  evt.initCommandEvent('command', true, true, window,
-    0, false, false, false, false, null, 0);
-  ele.dispatchEvent(evt);
-}
-exports.simulateCommand = simulateCommand;
-
-function simulateClick(ele) {
-  let window = ele.ownerGlobal;
-  let { document } = window;
-  let evt = document.createEvent('MouseEvents');
-  evt.initMouseEvent('click', true, true, window,
-    0, 0, 0, 0, 0, false, false, false, false, 0, null);
-  ele.dispatchEvent(evt);
-}
-exports.simulateClick = simulateClick;
-
-// OSX and Windows exhibit different behaviors when 'checked' is false,
-// so compare against the consistent 'true'. See bug 894809.
-function isChecked(node) {
-  return node.getAttribute('checked') === 'true';
-};
-exports.isChecked = isChecked;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-page-mod.js
+++ /dev/null
@@ -1,119 +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 { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { PageMod } = require("sdk/page-mod");
-const { getActiveTab, setTabURL, openTab, closeTab } = require('sdk/tabs/utils');
-const xulApp = require('sdk/system/xul-app');
-const windowHelpers = require('sdk/window/helpers');
-const { defer } = require("sdk/core/promise");
-const { isPrivate } = require('sdk/private-browsing');
-const { isTabPBSupported, isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { cleanUI } = require('sdk/test/utils');
-
-function openWebpage(url, enablePrivate) {
-  return new Promise((resolve, reject) => {
-    if (xulApp.is("Fennec")) {
-      let chromeWindow = getMostRecentBrowserWindow();
-      let rawTab = openTab(chromeWindow, url, {
-        isPrivate: enablePrivate
-      });
-
-      resolve(() => new Promise(resolve => {
-        closeTab(rawTab);
-        resolve();
-      }));
-    }
-    else {
-      windowHelpers.open("", {
-        features: {
-          toolbar: true,
-          private: enablePrivate
-        }
-      }).
-        then((chromeWindow) => {
-          if (isPrivate(chromeWindow) !== !!enablePrivate) {
-            reject(new Error("Window should have Private set to " + !!enablePrivate));
-          }
-
-          let tab = getActiveTab(chromeWindow);
-          setTabURL(tab, url);
-
-          resolve(() => windowHelpers.close(chromeWindow));
-        }).
-        catch(reject);
-    }
-  });
-}
-
-exports["test page-mod on private tab"] = function*(assert) {
-  // Only set private mode when explicitely supported.
-  // (fennec 19 has some intermediate PB support where isTabPBSupported
-  // will be false, but isPrivate(worker.tab) will be true if we open a private
-  // tab)
-  let setPrivate = isTabPBSupported || isWindowPBSupported;
-
-  let id = Date.now().toString(36);
-  let frameUri = "data:text/html;charset=utf-8," + id;
-  let uri = "data:text/html;charset=utf-8," +
-            encodeURIComponent(id + "<iframe src='" + frameUri + "'><iframe>");
-
-  let count = 0;
-
-  let close = yield openWebpage(uri, setPrivate);
-  yield new Promise(resolve => {
-    PageMod({
-      include: [uri, frameUri],
-
-      onAttach: function(worker) {
-        assert.ok(worker.tab.url == uri || worker.tab.url == frameUri,
-                  "Got a worker attached to the private window tab");
-
-        if (setPrivate) {
-          assert.ok(isPrivate(worker), "The worker is really private");
-          assert.ok(isPrivate(worker.tab), "The document is really private");
-        }
-        else {
-          assert.ok(!isPrivate(worker),
-                    "private browsing isn't supported, " +
-                    "so that the worker isn't private");
-          assert.ok(!isPrivate(worker.tab),
-                    "private browsing isn't supported, " +
-                    "so that the document isn't private");
-        }
-
-        if (++count == 2) {
-          this.destroy();
-          resolve();
-        }
-      }
-    });
-  });
-  yield close();
-  yield cleanUI();
-};
-
-exports["test page-mod on non-private tab"] = function*(assert) {
-  let id = Date.now().toString(36);
-  let url = "data:text/html;charset=utf-8," + encodeURIComponent(id);
-
-  let close = yield openWebpage(url, false);
-  let mod;
-  let worker = yield new Promise(resolve => {
-    mod = PageMod({
-      include: url,
-      onAttach: resolve
-    });
-  });
-
-  assert.equal(worker.tab.url, url,
-               "Got a worker attached to the private window tab");
-  assert.ok(!isPrivate(worker), "The worker is really non-private");
-  assert.ok(!isPrivate(worker.tab), "The document is really non-private");
-
-  mod.destroy();
-  yield close();
-  yield cleanUI();
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-panel.js
+++ /dev/null
@@ -1,99 +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 { open, focus, close } = require('sdk/window/helpers');
-const { isPrivate } = require('sdk/private-browsing');
-const { defer } = require('sdk/core/promise');
-const { browserWindows: windows } = require('sdk/windows');
-const { getInnerId, getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { getActiveView } = require('sdk/view/core');
-
-const BROWSER = 'chrome://browser/content/browser.xul';
-
-exports.testRequirePanel = function(assert) {
-  require('sdk/panel');
-  assert.ok('the panel module should not throw an error');
-};
-
-exports.testShowPanelInPrivateWindow = function(assert, done) {
-  let panel = require('sdk/panel').Panel({
-    contentURL: "data:text/html;charset=utf-8,I'm a leaf on the wind"
-  });
-
-  assert.ok(windows.length > 0, 'there is at least one open window');
-  for (let window of windows) {
-    assert.equal(isPrivate(window), false, 'open window is private');
-  }
-
-  let panelView = getActiveView(panel);
-  let expectedWindowId = getInnerId(panelView.backgroundFrame.contentWindow);
-
-  function checkPanelFrame() {
-    let iframe = panelView.firstChild;
-
-    assert.equal(panelView.viewFrame, iframe, 'panel has the correct viewFrame value');
-
-    let windowId = getInnerId(iframe.contentWindow);
-
-    assert.equal(windowId, expectedWindowId, 'panel has the correct window visible');
-
-    assert.equal(iframe.contentDocument.body.textContent,
-                 "I'm a leaf on the wind",
-                 'the panel has the expected content');
-  }
-
-  function testPanel(window) {
-    let { promise, resolve } = defer();
-
-    assert.ok(!panel.isShowing, 'the panel is not showing [1]');
-
-    panel.once('show', function() {
-      assert.ok(panel.isShowing, 'the panel is showing');
-
-      checkPanelFrame();
-
-      panel.once('hide', function() {
-        assert.ok(!panel.isShowing, 'the panel is not showing [2]');
-
-        resolve(window);
-      });
-
-      panel.hide();
-    });
-
-    panel.show();
-
-    return promise;
-  };
-
-  let initialWindow = getMostRecentBrowserWindow();
-
-  testPanel(initialWindow).
-    then(makeEmptyPrivateBrowserWindow).
-    then(focus).
-    then(function(window) {
-      assert.equal(isPrivate(window), true, 'opened window is private');
-      assert.pass('private window was focused');
-      return window;
-    }).
-    then(testPanel).
-    then(close).
-    then(() => focus(initialWindow)).
-    then(testPanel).
-    then(done).
-    then(null, assert.fail);
-};
-
-
-function makeEmptyPrivateBrowserWindow(options) {
-  options = options || {};
-  return open(BROWSER, {
-    features: {
-      chrome: true,
-      toolbar: true,
-      private: true
-    }
-  });
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-private-browsing.js
+++ /dev/null
@@ -1,111 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Ci } = require('chrome');
-const { isPrivateBrowsingSupported } = require('sdk/self');
-const tabs = require('sdk/tabs');
-const { browserWindows: windows } = require('sdk/windows');
-const { isPrivate } = require('sdk/private-browsing');
-const { is } = require('sdk/system/xul-app');
-const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
-const { cleanUI } = require('sdk/test/utils');
-
-const TAB_URL = 'about:addons';
-
-exports.testIsPrivateBrowsingTrue = function(assert) {
-  assert.ok(isPrivateBrowsingSupported,
-            'isPrivateBrowsingSupported property is true');
-};
-
-// test that it is possible to open a private tab
-exports.testTabOpenPrivate = function(assert, done) {
-  tabs.open({
-    url: TAB_URL,
-    isPrivate: true,
-    onReady: function(tab) {
-      assert.equal(tab.url, TAB_URL, 'opened correct tab');
-      assert.equal(isPrivate(tab), (isWindowPBSupported || isTabPBSupported), "tab is private");
-      cleanUI().then(done).catch(console.exception);
-    }
-  });
-}
-
-
-// test that it is possible to open a non private tab
-exports.testTabOpenPrivateDefault = function(assert, done) {
-  tabs.open({
-    url: TAB_URL,
-    onReady: function(tab) {
-      assert.equal(tab.url, TAB_URL, 'opened correct tab');
-      assert.equal(isPrivate(tab), false, "tab is not private");
-      cleanUI().then(done).catch(console.exception);
-    }
-  });
-}
-
-// test that it is possible to open a non private tab in explicit case
-exports.testTabOpenPrivateOffExplicit = function(assert, done) {
-  tabs.open({
-    url: TAB_URL,
-    isPrivate: false,
-    onReady: function(tab) {
-      assert.equal(tab.url, TAB_URL, 'opened correct tab');
-      assert.equal(isPrivate(tab), false, "tab is not private");
-      cleanUI().then(done).catch(console.exception);
-    }
-  });
-}
-
-// test windows.open with isPrivate: true
-// test isPrivate on a window
-if (!is('Fennec')) {
-  // test that it is possible to open a private window
-  exports.testWindowOpenPrivate = function(assert, done) {
-    windows.open({
-      url: TAB_URL,
-      isPrivate: true,
-      onOpen: function(window) {
-        let tab = window.tabs[0];
-        tab.once('ready', function() {
-          assert.equal(tab.url, TAB_URL, 'opened correct tab');
-          assert.equal(isPrivate(tab), isWindowPBSupported, 'tab is private');
-          cleanUI().then(done).catch(console.exception);
-        });
-      }
-    });
-  };
-
-  exports.testIsPrivateOnWindowOn = function(assert, done) {
-    windows.open({
-      isPrivate: true,
-      onOpen: function(window) {
-        assert.equal(isPrivate(window), isWindowPBSupported, 'isPrivate for a window is true when it should be');
-        assert.equal(isPrivate(window.tabs[0]), isWindowPBSupported, 'isPrivate for a tab is false when it should be');
-        cleanUI().then(done).catch(console.exception);
-      }
-    });
-  };
-
-  exports.testIsPrivateOnWindowOffImplicit = function(assert, done) {
-    windows.open({
-      onOpen: function(window) {
-        assert.equal(isPrivate(window), false, 'isPrivate for a window is false when it should be');
-        assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
-        cleanUI().then(done).catch(console.exception);
-      }
-    })
-  }
-
-  exports.testIsPrivateOnWindowOffExplicit = function(assert, done) {
-    windows.open({
-      isPrivate: false,
-      onOpen: function(window) {
-        assert.equal(isPrivate(window), false, 'isPrivate for a window is false when it should be');
-        assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
-        cleanUI().then(done).catch(console.exception);
-      }
-    })
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-selection.js
+++ /dev/null
@@ -1,447 +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 HTML = "<html>\
-  <body>\
-    <div>foo</div>\
-    <div>and</div>\
-    <textarea>noodles</textarea>\
-  </body>\
-</html>";
-
-const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
-
-const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
-const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
-
-const { defer } = require("sdk/core/promise");
-const { browserWindows } = require("sdk/windows");
-const tabs = require("sdk/tabs");
-const { setTabURL, getActiveTab, getTabContentWindow, closeTab, getTabs,
-  getTabTitle } = require("sdk/tabs/utils");
-const { getMostRecentBrowserWindow, isFocused } = require("sdk/window/utils");
-const { open: openNewWindow, close: closeWindow, focus } = require("sdk/window/helpers");
-const { Loader } = require("sdk/test/loader");
-const { merge } = require("sdk/util/object");
-const { isPrivate } = require("sdk/private-browsing");
-
-// General purpose utility functions
-
-/**
- * Opens the url given and return a promise, that will be resolved with the
- * content window when the document is ready.
- *
- * I believe this approach could be useful in most of our unit test, that
- * requires to open a tab and need to access to its content.
- */
-function open(url, options) {
-  let { promise, resolve } = defer();
-
-  if (options && typeof(options) === "object") {
-    openNewWindow("", {
-      features: merge({ toolbar: true }, options)
-    }).then(function(chromeWindow) {
-      if (isPrivate(chromeWindow) !== !!options.private)
-        throw new Error("Window should have Private set to " + !!options.private);
-
-      let tab = getActiveTab(chromeWindow);
-
-      tab.linkedBrowser.addEventListener("load", function ready(event) {
-        let { document } = getTabContentWindow(tab);
-
-        if (document.readyState === "complete" && document.URL === url) {
-          this.removeEventListener(event.type, ready);
-
-          if (options.title)
-            document.title = options.title;
-
-          resolve(document.defaultView);
-        }
-      }, true);
-
-      setTabURL(tab, url);
-    });
-
-    return promise;
-  };
-
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      // Unfortunately there is no way to get a XUL Tab from SDK Tab on Firefox,
-      // only on Fennec. We should implement `tabNS` also on Firefox in order
-      // to have that.
-
-      // Here we assuming that the most recent browser window is the one we're
-      // doing the test, and the active tab is the one we just opened.
-      let window = getTabContentWindow(getActiveTab(getMostRecentBrowserWindow()));
-
-      resolve(window);
-    }
-  });
-
-  return promise;
-};
-
-/**
- * Reload the window given and return a promise, that will be resolved with the
- * content window after a small delay.
- */
-function reload(window) {
-  let { promise, resolve } = defer();
-
-  // Here we assuming that the most recent browser window is the one we're
-  // doing the test, and the active tab is the one we just opened.
-  let tab = tabs.activeTab;
-
-  tab.once("ready", function () {
-    resolve(window);
-  });
-
-  window.location.reload(true);
-
-  return promise;
-}
-
-// Selection's unit test utility function
-
-/**
- * Select the first div in the page, adding the range to the selection.
- */
-function selectFirstDiv(window) {
-  let div = window.document.querySelector("div");
-  let selection = window.getSelection();
-  let range = window.document.createRange();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  range.selectNode(div);
-  selection.addRange(range);
-
-  return window;
-}
-
-/**
- * Select all divs in the page, adding the ranges to the selection.
- */
-function selectAllDivs(window) {
-  let divs = window.document.getElementsByTagName("div");
-  let selection = window.getSelection();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  for (let i = 0; i < divs.length; i++) {
-    let range = window.document.createRange();
-
-    range.selectNode(divs[i]);
-    selection.addRange(range);
-  }
-
-  return window;
-}
-
-/**
- * Select the textarea content
- */
-function selectTextarea(window) {
-  let selection = window.getSelection();
-  let textarea = window.document.querySelector("textarea");
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  textarea.setSelectionRange(0, textarea.value.length);
-  textarea.focus();
-
-  return window;
-}
-
-/**
- * Select the content of the first div
- */
-function selectContentFirstDiv(window) {
-  let div = window.document.querySelector("div");
-  let selection = window.getSelection();
-  let range = window.document.createRange();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  range.selectNodeContents(div);
-  selection.addRange(range);
-
-  return window;
-}
-
-/**
- * Dispatch the selection event for the selection listener added by
- * `nsISelectionPrivate.addSelectionListener`
- */
-function dispatchSelectionEvent(window) {
-  // We modify the selection in order to dispatch the selection's event, by
-  // contract the selection by one character. So if the text selected is "foo"
-  // will be "fo".
-  window.getSelection().modify("extend", "backward", "character");
-
-  return window;
-}
-
-/**
- * Dispatch the selection event for the selection listener added by
- * `window.onselect` / `window.addEventListener`
- */
-function dispatchOnSelectEvent(window) {
-  let { document } = window;
-  let textarea = document.querySelector("textarea");
-  let event = document.createEvent("UIEvents");
-
-  event.initUIEvent("select", true, true, window, 1);
-
-  textarea.dispatchEvent(event);
-
-  return window;
-}
-
-// Test cases
-
-exports["test PWPB Selection Listener"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "PWPB Selection Listener"}).
-    then(function(window) {
-      selection.once("select", function() {
-        assert.equal(browserWindows.length, 2, "there should be only two windows open.");
-        assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
-                     getTabs().map(tab => getTabTitle(tab)).join("', '") +
-                     "'."
-        );
-
-        // window should be focused, but force the focus anyhow.. see bug 841823
-        focus(window).then(function() {
-          // check state of window
-          assert.ok(isFocused(window), "the window is focused");
-          assert.ok(isPrivate(window), "the window should be a private window");
-
-          assert.equal(selection.text, "fo");
-
-          closeWindow(window).
-            then(loader.unload).
-            then(done).
-            catch(assert.fail);
-        });
-      });
-      return window;
-    }).
-    then(selectContentFirstDiv).
-    then(dispatchSelectionEvent).
-    catch(assert.fail);
-};
-
-exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "PWPB OnSelect Listener"}).
-    then(function(window) {
-      selection.once("select", function() {
-        assert.equal(browserWindows.length, 2, "there should be only two windows open.");
-        assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
-                     getTabs().map(tab => getTabTitle(tab)).join("', '") +
-                     "'."
-        );
-
-        // window should be focused, but force the focus anyhow.. see bug 841823
-        focus(window).then(function() {
-          assert.equal(selection.text, "noodles");
-
-          closeWindow(window).
-            then(loader.unload).
-            then(done).
-            catch(assert.fail);
-        });
-      });
-      return window;
-    }).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent).
-    catch(assert.fail);
-};
-
-exports["test PWPB Single DOM Selection"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "PWPB Single DOM Selection"}).
-    then(selectFirstDiv).
-    then(focus).then(function(window) {
-      assert.equal(selection.isContiguous, true,
-        "selection.isContiguous with single DOM Selection works.");
-
-      assert.equal(selection.text, "foo",
-        "selection.text with single DOM Selection works.");
-
-      assert.equal(selection.html, "<div>foo</div>",
-        "selection.html with single DOM Selection works.");
-
-      let selectionCount = 0;
-      for (let sel of selection) {
-        selectionCount++;
-
-        assert.equal(sel.text, "foo",
-          "iterable selection.text with single DOM Selection works.");
-
-        assert.equal(sel.html, "<div>foo</div>",
-          "iterable selection.html with single DOM Selection works.");
-      }
-
-      assert.equal(selectionCount, 1,
-        "One iterable selection");
-
-      return closeWindow(window);
-    }).then(loader.unload).then(done).catch(assert.fail);
-}
-
-exports["test PWPB Textarea Selection"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "PWPB Textarea Listener"}).
-    then(selectTextarea).
-    then(focus).
-    then(function(window) {
-
-      assert.equal(selection.isContiguous, true,
-        "selection.isContiguous with Textarea Selection works.");
-
-      assert.equal(selection.text, "noodles",
-        "selection.text with Textarea Selection works.");
-
-      assert.strictEqual(selection.html, null,
-        "selection.html with Textarea Selection works.");
-
-      let selectionCount = 0;
-      for (let sel of selection) {
-        selectionCount++;
-
-        assert.equal(sel.text, "noodles",
-          "iterable selection.text with Textarea Selection works.");
-
-        assert.strictEqual(sel.html, null,
-          "iterable selection.html with Textarea Selection works.");
-      }
-
-      assert.equal(selectionCount, 1,
-        "One iterable selection");
-
-      return closeWindow(window);
-    }).then(loader.unload).then(done).catch(assert.fail);
-};
-
-exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "PWPB Set HTML in Multiple DOM Selection"}).
-    then(selectAllDivs).
-    then(focus).
-    then(function(window) {
-      let html = "<span>b<b>a</b>r</span>";
-
-      let expectedText = ["bar", "and"];
-      let expectedHTML = [html, "<div>and</div>"];
-
-      selection.html = html;
-
-      assert.equal(selection.text, expectedText[0],
-        "set selection.text with DOM Selection works.");
-
-      assert.equal(selection.html, expectedHTML[0],
-        "selection.html with DOM Selection works.");
-
-      let selectionCount = 0;
-      for (let sel of selection) {
-
-        assert.equal(sel.text, expectedText[selectionCount],
-          "iterable selection.text with multiple DOM Selection works.");
-
-        assert.equal(sel.html, expectedHTML[selectionCount],
-          "iterable selection.html with multiple DOM Selection works.");
-
-        selectionCount++;
-      }
-
-      assert.equal(selectionCount, 2,
-        "Two iterable selections");
-
-      return closeWindow(window);
-    }).then(loader.unload).then(done).catch(assert.fail);
-};
-
-exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  open(URL, {private: true, title: "test PWPB Set Text in Textarea Selection"}).
-    then(selectTextarea).
-    then(focus).
-    then(function(window) {
-
-      let text = "bar";
-
-      selection.text = text;
-
-      assert.equal(selection.text, text,
-        "set selection.text with Textarea Selection works.");
-
-      assert.strictEqual(selection.html, null,
-        "selection.html with Textarea Selection works.");
-
-      let selectionCount = 0;
-      for (let sel of selection) {
-        selectionCount++;
-
-        assert.equal(sel.text, text,
-          "iterable selection.text with Textarea Selection works.");
-
-        assert.strictEqual(sel.html, null,
-          "iterable selection.html with Textarea Selection works.");
-      }
-
-      assert.equal(selectionCount, 1,
-        "One iterable selection");
-
-      return closeWindow(window);
-    }).then(loader.unload).then(done).catch(assert.fail);
-};
-
-// If the platform doesn't support the PBPW, we're replacing PBPW tests
-if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
-  module.exports = {
-    "test PBPW Unsupported": function Unsupported (assert) {
-      assert.pass("Private Window Per Browsing is not supported on this platform.");
-    }
-  }
-}
-
-// If the module doesn't support the app we're being run in, require() will
-// throw.  In that case, remove all tests above from exports, and add one dummy
-// test that passes.
-try {
-  require("sdk/selection");
-}
-catch (err) {
-  if (!/^Unsupported Application/.test(err.message))
-    throw err;
-
-  module.exports = {
-    "test Unsupported Application": function Unsupported (assert) {
-      assert.pass(err.message);
-    }
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-sidebar.js
+++ /dev/null
@@ -1,212 +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 { Loader } = require('sdk/test/loader');
-const { show, hide } = require('sdk/ui/sidebar/actions');
-const { isShowing } = require('sdk/ui/sidebar/utils');
-const { getMostRecentBrowserWindow, isWindowPrivate } = require('sdk/window/utils');
-const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
-const { setTimeout } = require('sdk/timers');
-const { isPrivate } = require('sdk/private-browsing');
-const { data } = require('sdk/self');
-const { URL } = require('sdk/url');
-
-const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing,
-        getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand,
-        simulateClick, isChecked } = require('./sidebar/utils');
-
-exports.testSideBarIsInNewPrivateWindows = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSideBarIsInNewPrivateWindows';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  let startWindow = getMostRecentBrowserWindow();
-  let ele = startWindow.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added');
-
-  open(null, { features: { private: true } }).then(function(window) {
-      let ele = window.document.getElementById(makeID(testName));
-      assert.ok(isPrivate(window), 'the new window is private');
-      assert.ok(!!ele, 'sidebar element was added');
-
-      sidebar.destroy();
-      assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-      assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
-
-      return close(window);
-  }).then(done).catch(assert.fail);
-}
-
-// Disabled in order to land other fixes, see bug 910647 for further details.
-/*
-exports.testSidebarIsOpenInNewPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarIsOpenInNewPrivateWindow';
-  let window = getMostRecentBrowserWindow();
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  assert.equal(isPrivate(window), false, 'the window is not private');
-
-  sidebar.on('show', function() {
-    assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-    assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-    windowPromise(window.OpenBrowserWindow({private: true}), 'DOMContentLoaded').then(function(window2) {
-      assert.equal(isPrivate(window2), true, 'the new window is private');
-
-      let sidebarEle = window2.document.getElementById('sidebar');
-
-      // wait for the sidebar to load something
-      function onSBLoad() {
-        sidebarEle.contentDocument.getElementById('web-panels-browser').addEventListener('load', function() {
-          assert.equal(isSidebarShowing(window), true, 'the sidebar is showing in old window still');
-          assert.equal(isSidebarShowing(window2), true, 'the sidebar is showing in the new private window');
-          assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-          sidebar.destroy();
-          close(window2).then(done);
-        }, true);
-      }
-
-      sidebarEle.addEventListener('load', onSBLoad, true);
-
-      assert.pass('waiting for the sidebar to open...');
-    }, assert.fail).then(null, assert.fail);
-  });
-
-  sidebar.show();
-}
-*/
-// TEST: edge case where web panel is destroyed while loading
-exports.testDestroyEdgeCaseBugWithPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testDestroyEdgeCaseBug';
-  let window = getMostRecentBrowserWindow();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  // NOTE: purposely not listening to show event b/c the event happens
-  //       between now and then.
-  sidebar.show();
-
-  assert.equal(isPrivate(window), false, 'the new window is not private');
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-
-  //assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-  open(null, { features: { private: true } }).then(focus).then(function(window2) {
-    assert.equal(isPrivate(window2), true, 'the new window is private');
-    assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing');
-    assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-
-    sidebar.destroy();
-    assert.pass('destroying the sidebar');
-
-    close(window2).then(function() {
-      let loader = Loader(module);
-
-      assert.equal(isPrivate(window), false, 'the current window is not private');
-
-      let sidebar = loader.require('sdk/ui/sidebar').Sidebar({
-        id: testName,
-        title: testName,
-        url:  'data:text/html;charset=utf-8,'+ testName,
-        onShow: function() {
-          assert.pass('onShow works for Sidebar');
-          loader.unload();
-
-          for (let mi of getSidebarMenuitems()) {
-            assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar')
-            assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
-          }
-          assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-          assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-
-          done();
-        }
-      })
-
-      sidebar.show();
-      assert.pass('showing the sidebar');
-    }).catch(assert.fail);
-  }).catch(assert.fail);
-}
-
-exports.testShowInPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowInPrivateWindow';
-  let window1 = getMostRecentBrowserWindow();
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-  let menuitemID = makeID(sidebar1.id);
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  assert.ok(!isChecked(window1.document.getElementById(menuitemID)),
-               'the menuitem is not checked');
-  assert.equal(isSidebarShowing(window1), false, 'the new window sidebar is not showing');
-
-  windowPromise(window1.OpenBrowserWindow({ private: true }), 'load').then(function(window) {
-    let { document } = window;
-    assert.equal(isWindowPrivate(window), true, 'new window is private');
-    assert.equal(isPrivate(window), true, 'new window is private');
-
-    sidebar1.show().then(
-      function good() {
-        assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-        assert.ok(!!document.getElementById(menuitemID),
-                  'the menuitem exists on the private window');
-        assert.equal(isSidebarShowing(window), true, 'the new window sidebar is showing');
-
-        sidebar1.destroy();
-        assert.equal(isSidebarShowing(window), false, 'the new window sidebar is showing');
-        assert.ok(!window1.document.getElementById(menuitemID),
-                  'the menuitem on the new window dne');
-
-        // test old window state
-        assert.equal(isSidebarShowing(window1), false, 'the old window sidebar is not showing');
-        assert.equal(window1.document.getElementById(menuitemID),
-                     null,
-                     'the menuitem on the old window dne');
-
-        close(window).then(done).catch(assert.fail);
-      },
-      function bad() {
-        assert.fail('a successful show should not happen here..');
-      });
-  }).catch(assert.fail);
-}
-
-// If the module doesn't support the app we're being run in, require() will
-// throw.  In that case, remove all tests above from exports, and add one dummy
-// test that passes.
-try {
-  require('sdk/ui/sidebar');
-}
-catch (err) {
-  if (!/^Unsupported Application/.test(err.message))
-    throw err;
-
-  module.exports = {
-    'test Unsupported Application': assert => assert.pass(err.message)
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-tabs.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const tabs = require('sdk/tabs');
-const { isPrivate } = require('sdk/private-browsing');
-const pbUtils = require('sdk/private-browsing/utils');
-
-exports.testPrivateTabsAreListed = function (assert, done) {
-  let originalTabCount = tabs.length;
-
-  tabs.open({
-    url: 'about:blank',
-    isPrivate: true,
-    onOpen: function(tab) {
-      // PWPB case
-      if (pbUtils.isWindowPBSupported || pbUtils.isTabPBSupported) {
-        assert.ok(isPrivate(tab), "tab is private");
-        assert.equal(tabs.length, originalTabCount + 1,
-                     'New private window\'s tab are visible in tabs list');
-      }
-      else {
-      // Global case, openDialog didn't opened a private window/tab
-        assert.ok(!isPrivate(tab), "tab isn't private");
-        assert.equal(tabs.length, originalTabCount + 1,
-                     'New non-private window\'s tab is visible in tabs list');
-      }
-
-      tab.close(done);
-    }
-  });
-};
-
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-window-tabs.js
+++ /dev/null
@@ -1,75 +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 tabs = require('sdk/tabs');
-const { isPrivate } = require('sdk/private-browsing');
-const { promise: windowPromise, close, focus } = require('sdk/window/helpers');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-
-exports.testOpenTabWithPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
-  let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
-
-  windowPromise(window, 'load').then(focus).then(function (window) {
-    assert.ok(isPrivate(window), 'new window is private');
-
-    tabs.open({
-      url: 'about:blank',
-      onOpen: function(tab) {
-        assert.ok(isPrivate(tab), 'new tab is private');
-        close(window).then(done).catch(assert.fail);
-      }
-    })
-  }).catch(assert.fail);
-}
-
-exports.testOpenTabWithNonPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
-  let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
-
-  windowPromise(window, 'load').then(focus).then(function (window) {
-    assert.equal(isPrivate(window), false, 'new window is not private');
-
-    tabs.open({
-      url: 'about:blank',
-      onOpen: function(tab) {
-        assert.equal(isPrivate(tab), false, 'new tab is not private');
-        close(window).then(done).catch(assert.fail);
-      }
-    })
-  }).catch(assert.fail);
-}
-
-exports.testOpenTabWithPrivateActiveWindowWithIsPrivateOptionTrue = function(assert, done) {
-  let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
-
-  windowPromise(window, 'load').then(focus).then(function (window) {
-    assert.ok(isPrivate(window), 'new window is private');
-
-    tabs.open({
-      url: 'about:blank',
-      isPrivate: true,
-      onOpen: function(tab) {
-        assert.ok(isPrivate(tab), 'new tab is private');
-        close(window).then(done).catch(assert.fail);
-      }
-    })
-  }).catch(assert.fail);
-}
-
-exports.testOpenTabWithNonPrivateActiveWindowWithIsPrivateOptionFalse = function(assert, done) {
-  let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
-
-  windowPromise(window, 'load').then(focus).then(function (window) {
-    assert.equal(isPrivate(window), false, 'new window is not private');
-
-    tabs.open({
-      url: 'about:blank',
-      isPrivate: false,
-      onOpen: function(tab) {
-        assert.equal(isPrivate(tab), false, 'new tab is not private');
-        close(window).then(done).catch(assert.fail);
-      }
-    })
-  }).catch(assert.fail);
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-windows.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { isPrivate } = require('sdk/private-browsing');
-const { isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { onFocus, getMostRecentWindow, getWindowTitle, getInnerId,
-        getFrames, windows, open: openWindow, isWindowPrivate } = require('sdk/window/utils');
-const { open, close, focus, promise } = require('sdk/window/helpers');
-const { browserWindows } = require("sdk/windows");
-const winUtils = require("sdk/deprecated/window-utils");
-const { fromIterator: toArray } = require('sdk/util/array');
-const tabs = require('sdk/tabs');
-const { cleanUI } = require('sdk/test/utils');
-
-const WM = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
-
-const BROWSER = 'chrome://browser/content/browser.xul';
-
-function makeEmptyBrowserWindow(options) {
-  options = options || {};
-  return open(BROWSER, {
-    features: {
-      chrome: true,
-      private: !!options.private
-    }
-  }).then(focus);
-}
-
-exports.testWindowTrackerIgnoresPrivateWindows = function(assert, done) {
-  var myNonPrivateWindowId, myPrivateWindowId;
-  var privateWindowClosed = false;
-  var privateWindowOpened = false;
-  var trackedWindowIds = [];
-
-  let wt = winUtils.WindowTracker({
-    onTrack: function(window) {
-      let id = getInnerId(window);
-      trackedWindowIds.push(id);
-    },
-    onUntrack: function(window) {
-      let id = getInnerId(window);
-      if (id === myPrivateWindowId) {
-        privateWindowClosed = true;
-      }
-
-      if (id === myNonPrivateWindowId) {
-        assert.equal(privateWindowClosed, true, 'private window was untracked');
-        wt.unload();
-        done();
-      }
-    }
-  });
-
-  // make a new private window
-  makeEmptyBrowserWindow({ private: true }).then(function(window) {
-    myPrivateWindowId = getInnerId(window);
-
-    assert.ok(trackedWindowIds.indexOf(myPrivateWindowId) >= 0, 'private window was tracked');
-    assert.equal(isPrivate(window), isWindowPBSupported, 'private window isPrivate');
-    assert.equal(isWindowPrivate(window), isWindowPBSupported);
-    assert.ok(getFrames(window).length > 1, 'there are frames for private window');
-    assert.equal(getWindowTitle(window), window.document.title,
-                 'getWindowTitle works');
-
-    return close(window).then(function() {
-      assert.pass('private window was closed');
-
-      return makeEmptyBrowserWindow().then(function(window) {
-        myNonPrivateWindowId = getInnerId(window);
-        assert.notEqual(myPrivateWindowId, myNonPrivateWindowId, 'non private window was opened');
-        return close(window);
-      });
-    });
-  }).catch(assert.fail);
-};
-
-// Test setting activeWIndow and onFocus for private windows
-exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
-  let browserWindow = WM.getMostRecentWindow("navigator:browser");
-  let testSteps;
-
-  assert.equal(winUtils.activeBrowserWindow, browserWindow,
-               "Browser window is the active browser window.");
-  assert.ok(!isPrivate(browserWindow), "Browser window is not private.");
-
-  // make a new private window
-  makeEmptyBrowserWindow({
-    private: true
-  }).then(function(window) {
-    let continueAfterFocus = window => onFocus(window).then(nextTest);
-
-    // PWPB case
-    if (isWindowPBSupported) {
-      assert.ok(isPrivate(window), "window is private");
-      assert.notStrictEqual(winUtils.activeBrowserWindow, browserWindow);
-    }
-    // Global case
-    else {
-      assert.ok(!isPrivate(window), "window is not private");
-    }
-
-    assert.strictEqual(winUtils.activeBrowserWindow, window,
-                 "Correct active browser window pb supported");
-    assert.notStrictEqual(browserWindow, window,
-                 "The window is not the old browser window");
-
-    testSteps = [
-      function() {
-        // test setting a non private window
-        continueAfterFocus(winUtils.activeWindow = browserWindow);
-      },
-      function() {
-        assert.strictEqual(winUtils.activeWindow, browserWindow,
-                           "Correct active window [1]");
-        assert.strictEqual(winUtils.activeBrowserWindow, browserWindow,
-                           "Correct active browser window [1]");
-
-        // test focus(window)
-        focus(window).then(nextTest);
-      },
-      function(w) {
-        assert.strictEqual(w, window, 'require("sdk/window/helpers").focus on window works');
-        assert.strictEqual(winUtils.activeBrowserWindow, window,
-                           "Correct active browser window [2]");
-        assert.strictEqual(winUtils.activeWindow, window,
-                           "Correct active window [2]");
-
-        // test setting a private window
-        continueAfterFocus(winUtils.activeWindow = window);
-      },
-      function() {
-        assert.strictEqual(winUtils.activeBrowserWindow, window,
-                          "Correct active browser window [3]");
-        assert.strictEqual(winUtils.activeWindow, window,
-                          "Correct active window [3]");
-
-        // just to get back to original state
-        continueAfterFocus(winUtils.activeWindow = browserWindow);
-      },
-      function() {
-        assert.strictEqual(winUtils.activeBrowserWindow, browserWindow,
-                          "Correct active browser window when pb mode is supported [4]");
-        assert.strictEqual(winUtils.activeWindow, browserWindow,
-                          "Correct active window when pb mode is supported [4]");
-
-        close(window).then(done).catch(assert.fail);
-      }
-    ];
-
-    function nextTest() {
-      let args = arguments;
-      if (testSteps.length) {
-        require('sdk/timers').setTimeout(function() {
-          (testSteps.shift()).apply(null, args);
-        }, 0);
-      }
-    }
-    nextTest();
-  });
-};
-
-exports.testActiveWindowDoesNotIgnorePrivateWindow = function*(assert) {
-  // make a new private window
-  let window = yield makeEmptyBrowserWindow({
-    private: true
-  });
-
-  // PWPB case
-  if (isWindowPBSupported) {
-    assert.equal(isPrivate(winUtils.activeWindow), true,
-                 "active window is private");
-    assert.equal(isPrivate(winUtils.activeBrowserWindow), true,
-                 "active browser window is private");
-    assert.ok(isWindowPrivate(window), "window is private");
-    assert.ok(isPrivate(window), "window is private");
-
-    // pb mode is supported
-    assert.ok(
-      isWindowPrivate(winUtils.activeWindow),
-      "active window is private when pb mode is supported");
-    assert.ok(
-      isWindowPrivate(winUtils.activeBrowserWindow),
-      "active browser window is private when pb mode is supported");
-    assert.ok(isPrivate(winUtils.activeWindow),
-              "active window is private when pb mode is supported");
-    assert.ok(isPrivate(winUtils.activeBrowserWindow),
-      "active browser window is private when pb mode is supported");
-  }
-
-  yield cleanUI();
-}
-
-exports.testWindowIteratorIgnoresPrivateWindows = function*(assert) {
-  // make a new private window
-  let window = yield makeEmptyBrowserWindow({
-    private: true
-  });
-
-  assert.equal(isWindowPrivate(window), isWindowPBSupported);
-  assert.ok(toArray(winUtils.windowIterator()).indexOf(window) > -1,
-            "window is in windowIterator()");
-
-  yield cleanUI();
-};
-
-// test that it is not possible to find a private window in
-// windows module's iterator
-exports.testWindowIteratorPrivateDefault = function(assert, done) {
-  // there should only be one window open here, if not give us the
-  // the urls
-  if (browserWindows.length > 1) {
-    for (let tab of tabs) {
-      assert.fail("TAB URL: " + tab.url);
-    }
-  }
-  else {
-    assert.equal(browserWindows.length, 1, 'only one window open');
-  }
-
-  open('chrome://browser/content/browser.xul', {
-    features: {
-      private: true,
-      chrome: true
-    }
-  }).then(focus).then(function(window) {
-    // test that there is a private window opened
-    assert.equal(isPrivate(window), isWindowPBSupported, 'there is a private window open');
-    assert.equal(isPrivate(winUtils.activeWindow), isWindowPBSupported);
-    assert.equal(isPrivate(getMostRecentWindow()), isWindowPBSupported);
-    assert.equal(isPrivate(browserWindows.activeWindow), isWindowPBSupported);
-
-    assert.equal(browserWindows.length, 2, '2 windows open');
-    assert.equal(windows(null, { includePrivate: true }).length, 2);
-
-    return close(window);
-  }).then(done).catch(assert.fail);
-};
deleted file mode 100644
--- a/addon-sdk/source/test/addons/remote/main.js
+++ /dev/null
@@ -1,578 +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 LOCAL_URI = "about:robots";
-const REMOTE_URI = "data:text/html;charset=utf-8,remote";
-
-const { Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const { getTabs, openTab, closeTab, setTabURL, getBrowserForTab, getURI } = require('sdk/tabs/utils');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { cleanUI } = require("sdk/test/utils");
-const { setTimeout } = require("sdk/timers");
-const { promiseEvent, promiseDOMEvent, promiseEventOnItemAndContainer,
-        waitForProcesses, getChildFrameCount, isE10S } = require("./utils");
-const { after } = require('sdk/test/utils');
-const { processID } = require('sdk/system/runtime');
-
-const { set } = require('sdk/preferences/service');
-// The hidden preload browser messes up our frame counts
-set('browser.newtab.preload', false);
-
-function promiseTabFrameAttach(frames) {
-  return new Promise(resolve => {
-    let listener = function(frame, ...args) {
-      if (!frame.isTab)
-        return;
-      frames.off("attach", listener);
-      resolve([frame, ...args]);
-    }
-
-    frames.on("attach", listener);
-  });
-}
-
-// Check that we see a process stop and start
-exports["test process restart"] = function*(assert) {
-  if (!isE10S) {
-    assert.pass("Skipping test in non-e10s mode");
-    return;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-  let tab = tabs[0];
-  let browser = getBrowserForTab(tab);
-
-  let loader = new Loader(module);
-  let { processes, frames } = yield waitForProcesses(loader);
-
-  let remoteProcess = Array.filter(processes, p => p.isRemote)[0];
-  let localProcess = Array.filter(processes, p => !p.isRemote)[0];
-  let remoteFrame = Array.filter(frames, f => f.process == remoteProcess)[0];
-
-  // Switch the remote tab to a local URI which should kill the remote process
-
-  let frameDetach = promiseEventOnItemAndContainer(assert, remoteFrame, frames, 'detach');
-  let frameAttach = promiseTabFrameAttach(frames);
-  let processDetach = promiseEventOnItemAndContainer(assert, remoteProcess, processes, 'detach');
-  let browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, LOCAL_URI);
-  // The load should kill the remote frame
-  yield frameDetach;
-  // And create a new frame in the local process
-  let [newFrame] = yield frameAttach;
-  assert.equal(newFrame.process, localProcess, "New frame should be in the local process");
-  // And kill the process
-  yield processDetach;
-  yield browserLoad;
-
-  frameDetach = promiseEventOnItemAndContainer(assert, newFrame, frames, 'detach');
-  let processAttach = promiseEvent(processes, 'attach');
-  frameAttach = promiseTabFrameAttach(frames);
-  browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, REMOTE_URI);
-  // The load should kill the remote frame
-  yield frameDetach;
-  // And create a new remote process
-  [remoteProcess] = yield processAttach;
-  assert.ok(remoteProcess.isRemote, "Process should be remote");
-  // And create a new frame in the remote process
-  [newFrame] = yield frameAttach;
-  assert.equal(newFrame.process, remoteProcess, "New frame should be in the remote process");
-  yield browserLoad;
-
-  browserLoad = promiseDOMEvent(browser, "load", true);
-  setTabURL(tab, "about:blank");
-  yield browserLoad;
-
-  loader.unload();
-};
-
-// Test that we find the right number of processes and that messaging between
-// them works and none of the streams cross
-exports["test process list"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = loader.require('sdk/remote/parent');
-
-  let processCount = 0;
-  processes.forEvery(processes => processCount++);
-
-  yield waitForProcesses(loader);
-
-  let remoteProcesses = Array.filter(processes, process => process.isRemote);
-  let localProcesses = Array.filter(processes, process => !process.isRemote);
-
-  assert.equal(localProcesses.length, 1, "Should always be one process");
-
-  if (isE10S) {
-    assert.equal(remoteProcesses.length, 1, "Should be one remote process");
-  }
-  else {
-    assert.equal(remoteProcesses.length, 0, "Should be no remote processes");
-  }
-
-  assert.equal(processCount, processes.length, "Should have seen all processes");
-
-  processCount = 0;
-  processes.forEvery(process => processCount++);
-
-  assert.equal(processCount, processes.length, "forEvery should send existing processes to the listener");
-
-  localProcesses[0].port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "local", "Should not have seen a pong from the local process with the wrong key");
-  });
-
-  if (isE10S) {
-    remoteProcesses[0].port.on('sdk/test/pong', (process, key) => {
-      assert.equal(key, "remote", "Should not have seen a pong from the remote process with the wrong key");
-    });
-  }
-
-  let promise = promiseEventOnItemAndContainer(assert, localProcesses[0].port, processes.port, 'sdk/test/pong', localProcesses[0]);
-  localProcesses[0].port.emit('sdk/test/ping', "local");
-
-  let reply = yield promise;
-  assert.equal(reply[0], "local", "Saw the process reply with the right key");
-
-  if (isE10S) {
-    promise = promiseEventOnItemAndContainer(assert, remoteProcesses[0].port, processes.port, 'sdk/test/pong', remoteProcesses[0]);
-    remoteProcesses[0].port.emit('sdk/test/ping', "remote");
-
-    reply = yield promise;
-    assert.equal(reply[0], "remote", "Saw the process reply with the right key");
-
-    assert.notEqual(localProcesses[0], remoteProcesses[0], "Processes should be different");
-  }
-
-  loader.unload();
-};
-
-// Test that the frame lists are kept up to date
-exports["test frame list"] = function*(assert) {
-  function browserFrames(list) {
-    return Array.filter(list, b => b.isTab).length;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-
-  let loader = new Loader(module);
-  let { processes, frames } = yield waitForProcesses(loader);
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab1 = openTab(window, LOCAL_URI);
-  let [frame1] = yield promise;
-  assert.ok(!!frame1, "Should have seen the new frame");
-  assert.ok(!frame1.process.isRemote, "Frame should not be remote");
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  promise = promiseTabFrameAttach(frames);
-  let tab2 = openTab(window, REMOTE_URI);
-  let [frame2] = yield promise;
-  assert.ok(!!frame2, "Should have seen the new frame");
-  if (isE10S)
-    assert.ok(frame2.process.isRemote, "Frame should be remote");
-  else
-    assert.ok(!frame2.process.isRemote, "Frame should not be remote");
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  frames.port.emit('sdk/test/ping')
-  yield new Promise(resolve => {
-    let count = 0;
-    let listener = () => {
-      console.log("Saw pong");
-      count++;
-      if (count == frames.length) {
-        frames.port.off('sdk/test/pong', listener);
-        resolve();
-      }
-    };
-    frames.port.on('sdk/test/pong', listener);
-  });
-
-  let badListener = () => {
-    assert.fail("Should not have seen a response through this frame");
-  }
-  frame1.port.on('sdk/test/pong', badListener);
-  frame2.port.emit('sdk/test/ping', 'b');
-  let [key] = yield promiseEventOnItemAndContainer(assert, frame2.port, frames.port, 'sdk/test/pong', frame2);
-  assert.equal(key, 'b', "Should have seen the right response");
-  frame1.port.off('sdk/test/pong', badListener);
-
-  frame2.port.on('sdk/test/pong', badListener);
-  frame1.port.emit('sdk/test/ping', 'b');
-  [key] = yield promiseEventOnItemAndContainer(assert, frame1.port, frames.port, 'sdk/test/pong', frame1);
-  assert.equal(key, 'b', "Should have seen the right response");
-  frame2.port.off('sdk/test/pong', badListener);
-
-  promise = promiseEventOnItemAndContainer(assert, frame1, frames, 'detach');
-  closeTab(tab1);
-  yield promise;
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  promise = promiseEventOnItemAndContainer(assert, frame2, frames, 'detach');
-  closeTab(tab2);
-  yield promise;
-
-  assert.equal(browserFrames(frames), getTabs(window).length, "Should be the right number of browser frames.");
-  assert.equal((yield getChildFrameCount(processes)), frames.length, "Child processes should have the right number of frames");
-
-  loader.unload();
-};
-
-// Test that multiple loaders get their own loaders in the child and messages
-// don't cross. Unload should work
-exports["test new loader"] = function*(assert) {
-  let loader1 = new Loader(module);
-  let { processes: processes1 } = yield waitForProcesses(loader1);
-
-  let loader2 = new Loader(module);
-  let { processes: processes2 } = yield waitForProcesses(loader2);
-
-  let process1 = [...processes1][0];
-  let process2 = [...processes2][0];
-
-  process1.port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "a", "Should have seen the right pong");
-  });
-
-  process2.port.on('sdk/test/pong', (process, key) => {
-    assert.equal(key, "b", "Should have seen the right pong");
-  });
-
-  process1.port.emit('sdk/test/ping', 'a');
-  yield promiseEvent(process1.port, 'sdk/test/pong');
-
-  process2.port.emit('sdk/test/ping', 'b');
-  yield promiseEvent(process2.port, 'sdk/test/pong');
-
-  loader1.unload();
-
-  process2.port.emit('sdk/test/ping', 'b');
-  yield promiseEvent(process2.port, 'sdk/test/pong');
-
-  loader2.unload();
-};
-
-// Test that unloading the loader unloads the child instances
-exports["test unload"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:,<html/>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  promise = promiseDOMEvent(browser, 'hashchange');
-  frame.port.emit('sdk/test/testunload');
-  loader.unload("shutdown");
-  yield promise;
-
-  let hash = getURI(tab).replace(/.*#/, "");
-  assert.equal(hash, "unloaded:shutdown", "Saw the correct hash change.")
-
-  closeTab(tab);
-}
-
-// Test that unloading the loader causes the child to see frame detach events
-exports["test frame detach on unload"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:,<html/>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  promise = promiseDOMEvent(browser, 'hashchange');
-  frame.port.emit('sdk/test/testdetachonunload');
-  loader.unload("shutdown");
-  yield promise;
-
-  let hash = getURI(tab).replace(/.*#/, "");
-  assert.equal(hash, "unloaded", "Saw the correct hash change.")
-
-  closeTab(tab);
-}
-
-// Test that DOM event listener on the frame object works
-exports["test frame event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframeevent');
-  promise = Promise.all([
-    promiseEvent(frame.port, 'sdk/test/sawreply'),
-    promiseEvent(frame.port, 'sdk/test/eventsent')
-  ]);
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  frame.port.emit('sdk/test/unregisterframeevent');
-  promise = promiseEvent(frame.port, 'sdk/test/eventsent');
-  frame.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader.unload();
-}
-
-// Test that DOM event listener on the frames object works
-exports["test frames event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = promiseTabFrameAttach(frames);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  assert.ok(!!frame, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframesevent');
-  promise = Promise.all([
-    promiseEvent(frame.port, 'sdk/test/sawreply'),
-    promiseEvent(frame.port, 'sdk/test/eventsent')
-  ]);
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  frame.port.emit('sdk/test/unregisterframesevent');
-  promise = promiseEvent(frame.port, 'sdk/test/eventsent');
-  frame.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader.unload();
-}
-
-// Test that unloading unregisters frame DOM events
-exports["test unload removes frame event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let loader2 = new Loader(module);
-  let { frames: frames2 } = yield waitForProcesses(loader2);
-
-  let promise = promiseTabFrameAttach(frames);
-  let promise2 = promiseTabFrameAttach(frames2);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  let [frame2] = yield promise2;
-  assert.ok(!!frame && !!frame2, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframeevent');
-  promise = Promise.all([
-    promiseEvent(frame2.port, 'sdk/test/sawreply'),
-    promiseEvent(frame2.port, 'sdk/test/eventsent')
-  ]);
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  loader.unload();
-
-  promise = promiseEvent(frame2.port, 'sdk/test/eventsent');
-  frame2.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader2.unload();
-}
-
-// Test that unloading unregisters frames DOM events
-exports["test unload removes frames event listeners"] = function*(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let loader2 = new Loader(module);
-  let { frames: frames2 } = yield waitForProcesses(loader2);
-
-  let promise = promiseTabFrameAttach(frames);
-  let promise2 = promiseTabFrameAttach(frames2);
-  let tab = openTab(window, "data:text/html,<html></html>");
-  let browser = getBrowserForTab(tab);
-  yield promiseDOMEvent(browser, "load", true);
-  let [frame] = yield promise;
-  let [frame2] = yield promise2;
-  assert.ok(!!frame && !!frame2, "Should have seen the new frame");
-
-  frame.port.emit('sdk/test/registerframesevent');
-  promise = Promise.all([
-    promiseEvent(frame2.port, 'sdk/test/sawreply'),
-    promiseEvent(frame2.port, 'sdk/test/eventsent')
-  ]);
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  loader.unload();
-
-  promise = promiseEvent(frame2.port, 'sdk/test/eventsent');
-  frame2.port.on('sdk/test/sawreply', () => {
-    assert.fail("Should not have seen the event listener reply");
-  });
-
-  frame2.port.emit('sdk/test/sendevent');
-  yield promise;
-
-  closeTab(tab);
-  loader2.unload();
-}
-
-// Check that the child frame has the right properties
-exports["test frame properties"] = function*(assert) {
-  let loader = new Loader(module);
-  let { frames } = yield waitForProcesses(loader);
-
-  let promise = new Promise(resolve => {
-    let count = frames.length;
-    let listener = (frame, properties) => {
-      assert.equal(properties.isTab, frame.isTab,
-                   "Child frame should have the same isTab property");
-
-      if (--count == 0) {
-        frames.port.off('sdk/test/replyproperties', listener);
-        resolve();
-      }
-    }
-
-    frames.port.on('sdk/test/replyproperties', listener);
-  })
-
-  frames.port.emit('sdk/test/checkproperties');
-  yield promise;
-
-  loader.unload();
-}
-
-// Check that non-remote processes have the same process ID and remote processes
-// have different IDs
-exports["test processID"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  for (let process of processes) {
-    process.port.emit('sdk/test/getprocessid');
-    let [p, ID] = yield promiseEvent(process.port, 'sdk/test/processid');
-    if (process.isRemote) {
-      assert.notEqual(ID, processID, "Remote processes should have a different process ID");
-    }
-    else {
-      assert.equal(ID, processID, "Remote processes should have the same process ID");
-    }
-  }
-
-  loader.unload();
-}
-
-// Check that sdk/remote/parent and sdk/remote/child can only be loaded in the
-// appropriate loaders
-exports["test cannot load in wrong loader"] = function*(assert) {
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  try {
-    require('sdk/remote/child');
-    assert.fail("Should not have been able to load sdk/remote/child");
-  }
-  catch (e) {
-    assert.ok(/Cannot load sdk\/remote\/child in a main process loader/.test(e),
-              "Should have seen the right exception.");
-  }
-
-  for (let process of processes) {
-    processes.port.emit('sdk/test/parentload');
-    let [_, isChildLoader, loaded, message] = yield promiseEvent(processes.port, 'sdk/test/parentload');
-    assert.ok(isChildLoader, "Process should see itself in a child loader.");
-    assert.ok(!loaded, "Process couldn't load sdk/remote/parent.");
-    assert.ok(/Cannot load sdk\/remote\/parent in a child loader/.test(message),
-              "Should have seen the right exception.");
-  }
-
-  loader.unload();
-};
-
-exports["test send cpow"] = function*(assert) {
-  if (!isE10S) {
-    assert.pass("Skipping test in non-e10s mode");
-    return;
-  }
-
-  let window = getMostRecentBrowserWindow();
-
-  let tabs = getTabs(window);
-  assert.equal(tabs.length, 1, "Should have just the one tab to start with");
-  let tab = tabs[0];
-  let browser = getBrowserForTab(tab);
-
-  assert.ok(Cu.isCrossProcessWrapper(browser.contentWindow),
-            "Should have a CPOW for the browser content window");
-
-  let loader = new Loader(module);
-  let { processes } = yield waitForProcesses(loader);
-
-  processes.port.emitCPOW('sdk/test/cpow', ['foobar'], { window: browser.contentWindow });
-  let [process, arg, id] = yield promiseEvent(processes.port, 'sdk/test/cpow');
-
-  assert.ok(process.isRemote, "Response should come from the remote process");
-  assert.equal(arg, "foobar", "Argument should have passed through");
-  assert.equal(id, browser.outerWindowID, "Should have got the ID from the child");
-};
-
-after(exports, function*(name, assert) {
-  yield cleanUI();
-});
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/remote/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "remote",
-  "title": "remote",
-  "id": "remote@jetpack",
-  "description": "Run remote tests",
-  "version": "1.0.0",
-  "main": "main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/remote/remote-module.js
+++ /dev/null
@@ -1,129 +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 { when } = require('sdk/system/unload');
-const { process, frames } = require('sdk/remote/child');
-const { loaderID } = require('@loader/options');
-const { processID } = require('sdk/system/runtime');
-const system = require('sdk/system/events');
-const { Cu } = require('chrome');
-const { isChildLoader } = require('sdk/remote/core');
-const { getOuterId } = require('sdk/window/utils');
-
-function log(str) {
-  console.log("remote[" + loaderID + "][" + processID + "]: " + str);
-}
-
-log("module loaded");
-
-process.port.emit('sdk/test/load');
-
-process.port.on('sdk/test/ping', (process, key) => {
-  log("received process ping");
-  process.port.emit('sdk/test/pong', key);
-});
-
-var frameCount = 0;
-frames.forEvery(frame => {
-  frameCount++;
-  frame.on('detach', () => {
-    frameCount--;
-  });
-
-  frame.port.on('sdk/test/ping', (frame, key) => {
-    log("received frame ping");
-    frame.port.emit('sdk/test/pong', key);
-  });
-});
-
-frames.port.on('sdk/test/checkproperties', frame => {
-  frame.port.emit('sdk/test/replyproperties', {
-    isTab: frame.isTab
-  });
-});
-
-process.port.on('sdk/test/count', () => {
-  log("received count ping");
-  process.port.emit('sdk/test/count', frameCount);
-});
-
-process.port.on('sdk/test/getprocessid', () => {
-  process.port.emit('sdk/test/processid', processID);
-});
-
-frames.port.on('sdk/test/testunload', (frame) => {
-  // Cache the content since the frame will have been destroyed by the time
-  // we see the unload event.
-  let content = frame.content;
-  when((reason) => {
-    content.location = "#unloaded:" + reason;
-  });
-});
-
-frames.port.on('sdk/test/testdetachonunload', (frame) => {
-  let content = frame.content;
-  frame.on('detach', () => {
-    console.log("Detach from " + frame.content.location);
-    frame.content.location = "#unloaded";
-  });
-});
-
-frames.port.on('sdk/test/sendevent', (frame) => {
-  let doc = frame.content.document;
-
-  let listener = () => {
-    frame.port.emit('sdk/test/sawreply');
-  }
-
-  system.on("Test:Reply", listener);
-  let event = new frame.content.CustomEvent("Test:Event");
-  doc.dispatchEvent(event);
-  system.off("Test:Reply", listener);
-  frame.port.emit('sdk/test/eventsent');
-});
-
-process.port.on('sdk/test/parentload', () => {
-  let loaded = false;
-  let message = "";
-  try {
-    require('sdk/remote/parent');
-    loaded = true;
-  }
-  catch (e) {
-    message = "" + e;
-  }
-
-  process.port.emit('sdk/test/parentload',
-    isChildLoader,
-    loaded,
-    message
-  )
-});
-
-function listener(event) {
-  // Use the raw observer service here since it will be usable even if the
-  // loader has unloaded
-  let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-  Services.obs.notifyObservers(null, "Test:Reply");
-}
-
-frames.port.on('sdk/test/registerframesevent', (frame) => {
-  frames.addEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/unregisterframesevent', (frame) => {
-  frames.removeEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/registerframeevent', (frame) => {
-  frame.addEventListener("Test:Event", listener, true);
-});
-
-frames.port.on('sdk/test/unregisterframeevent', (frame) => {
-  frame.removeEventListener("Test:Event", listener, true);
-});
-
-process.port.on('sdk/test/cpow', (process, arg, cpows) => {
-  process.port.emit('sdk/test/cpow', arg, getOuterId(cpows.window));
-});
deleted file mode 100644
--- a/addon-sdk/source/test/addons/remote/utils.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Cu } = require('chrome');
-const { Task: { async } } = Cu.import('resource://gre/modules/Task.jsm', {});
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-
-const REMOTE_MODULE = "./remote-module";
-
-function promiseEvent(emitter, event) {
-  console.log("Waiting for " + event);
-  return new Promise(resolve => {
-    emitter.once(event, (...args) => {
-      console.log("Saw " + event);
-      resolve(args);
-    });
-  });
-}
-exports.promiseEvent = promiseEvent;
-
-function promiseDOMEvent(target, event, isCapturing = false) {
-  console.log("Waiting for " + event);
-  return new Promise(resolve => {
-    let listener = (event) => {
-      target.removeEventListener(event, listener, isCapturing);
-      resolve(event);
-    };
-    target.addEventListener(event, listener, isCapturing);
-  })
-}
-exports.promiseDOMEvent = promiseDOMEvent;
-
-const promiseEventOnItemAndContainer = async(function*(assert, itemport, container, event, item = itemport) {
-  let itemEvent = promiseEvent(itemport, event);
-  let containerEvent = promiseEvent(container, event);
-
-  let itemArgs = yield itemEvent;
-  let containerArgs = yield containerEvent;
-
-  assert.equal(containerArgs[0], item, "Should have seen a container event for the right item");
-  assert.equal(JSON.stringify(itemArgs), JSON.stringify(containerArgs), "Arguments should have matched");
-
-  // Strip off the item from the returned arguments
-  return itemArgs.slice(1);
-});
-exports.promiseEventOnItemAndContainer = promiseEventOnItemAndContainer;
-
-const waitForProcesses = async(function*(loader) {
-  console.log("Starting remote");
-  let { processes, frames, remoteRequire } = loader.require('sdk/remote/parent');
-  remoteRequire(REMOTE_MODULE, module);
-
-  let events = [];
-
-  // In e10s we should expect to see two processes
-  let expectedCount = isE10S ? 2 : 1;
-
-  yield new Promise(resolve => {
-    let count = 0;
-
-    // Wait for a process to be detected
-    let listener = process => {
-      console.log("Saw a process attach");
-      // Wait for the remote module to load in this process
-      process.port.once('sdk/test/load', () => {
-        console.log("Saw a remote module load");
-        count++;
-        if (count == expectedCount) {
-          processes.off('attach', listener);
-          resolve();
-        }
-      });
-    }
-    processes.on('attach', listener);
-  });
-
-  console.log("Remote ready");
-  return { processes, frames, remoteRequire };
-});
-exports.waitForProcesses = waitForProcesses;
-
-// Counts the frames in all the child processes
-const getChildFrameCount = async(function*(processes) {
-  let frameCount = 0;
-
-  for (let process of processes) {
-    process.port.emit('sdk/test/count');
-    let [p, count] = yield promiseEvent(process.port, 'sdk/test/count');
-    frameCount += count;
-  }
-
-  return frameCount;
-});
-exports.getChildFrameCount = getChildFrameCount;
-
-const mainWindow = getMostRecentBrowserWindow();
-const isE10S = mainWindow.gMultiProcessBrowser;
-exports.isE10S = isE10S;
-
-if (isE10S) {
-  console.log("Testing in E10S mode");
-  // We expect a child process to already be present, make sure that is the case
-  mainWindow.XULBrowserWindow.forceInitialBrowserRemote();
-}
-else {
-  console.log("Testing in non-E10S mode");
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/list.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-exports.local = true;
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/main.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var { isNative } = require("@loader/options");
-
-exports["test local vs sdk module"] = function (assert) {
-  assert.notEqual(require("list"),
-                  require("sdk/util/list"),
-                  "Local module takes the priority over sdk modules");
-  assert.ok(require("list").local,
-            "this module is really the local one");
-}
-
-if (!isNative) {
-  exports["test 3rd party vs sdk module"] = function (assert) {
-    // We are testing with a 3rd party package called `tabs` with 3 modules
-    // main, page-mod and third-party
-
-    // the only way to require 3rd party package modules are to use absolute paths
-    // require("tabs/main"), require("tabs/page-mod"),
-    // require("tabs/third-party") and also require("tabs") which will refer
-    // to tabs's main package module.
-
-    // So require(page-mod) shouldn't map the 3rd party
-    assert.equal(require("page-mod"),
-                 require("sdk/page-mod"),
-                 "Third party modules don't overload sdk modules");
-
-    assert.ok(require("page-mod").PageMod,
-              "page-mod module is really the sdk one");
-
-    assert.equal(require("tabs/page-mod").id, "page-mod",
-                 "tabs/page-mod is the 3rd party");
-
-    // But require(tabs) will map to 3rd party main module
-    // *and* overload the sdk module
-    // and also any local module with the same name
-    assert.equal(require("tabs").id, "tabs-main",
-                 "Third party main module overload sdk modules");
-
-    assert.equal(require("tabs"),
-                 require("tabs/main"),
-                 "require(tabs) maps to require(tabs/main)");
-
-    // So that you have to use relative path to ensure getting the local module
-    assert.equal(require("./tabs").id,
-                 "local-tabs",
-                 "require(./tabs) maps to the local module");
-
-    // It should still be possible to require sdk module with absolute path
-    assert.ok(require("sdk/tabs").open,
-              "We can bypass this overloading with absolute path to sdk modules");
-
-    assert.equal(require("sdk/tabs"),
-                 require("addon-kit/tabs"),
-                 "Old and new layout both work");
-  }
-}
-
-// /!\ Always use distinct module for each test.
-//     Otherwise, the linker can correctly parse and allow the first usage of it
-//     but still silently fail on the second.
-
-exports.testRelativeRequire = function (assert) {
-  assert.equal(require('./same-folder').id, 'same-folder');
-}
-
-exports.testRelativeSubFolderRequire = function (assert) {
-  assert.equal(require('./sub-folder/module').id, 'sub-folder');
-}
-
-exports.testMultipleRequirePerLine = function (assert) {
-  var a=require('./multiple/a'),b=require('./multiple/b');
-  assert.equal(a.id, 'a');
-  assert.equal(b.id, 'b');
-}
-
-exports.testSDKRequire = function (assert) {
-  assert.deepEqual(Object.keys(require('sdk/page-worker')), ['Page']);
-  if (!isNative) {
-    assert.equal(require('page-worker'), require('sdk/page-worker'));
-  }
-}
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/multiple/a.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = 'a';
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/multiple/b.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = 'b';
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "test-require@jetpack",
-  "name": "test-require",
-  "packages": "packages",
-  "ignore-deprecated-path": true,
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/packages/tabs/main.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = "tabs-main";
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/packages/tabs/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "id": "test-panel"
-}
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/packages/tabs/page-mod.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = "page-mod";
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/same-folder.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = 'same-folder';
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/sub-folder/module.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = 'sub-folder';
deleted file mode 100644
--- a/addon-sdk/source/test/addons/require/tabs.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.id = "local-tabs";
deleted file mode 100644
--- a/addon-sdk/source/test/addons/self/data/data.md
+++ /dev/null
@@ -1,1 +0,0 @@
-# hello world
deleted file mode 100644
--- a/addon-sdk/source/test/addons/self/main.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/. */
-"use strict";
-
-const self = require("sdk/self");
-
-exports["test self.data.load"] = assert => {
-
-  assert.equal(self.data.load("data.md").trim(),
-               "# hello world",
-               "paths work");
-
-  assert.equal(self.data.load("./data.md").trim(),
-               "# hello world",
-               "relative paths work");
-};
-
-exports["test self.id"] = assert => {
-  assert.equal(self.id, "test-self@jetpack", "self.id should be correct.");
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/self/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-self@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-l10n/locale/en.properties
+++ /dev/null
@@ -1,5 +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/.
-
-somePreference_title=A
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-l10n/main.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cu } = require('chrome');
-const sp = require('sdk/simple-prefs');
-const app = require('sdk/system/xul-app');
-const self = require('sdk/self');
-const tabs = require('sdk/tabs');
-const { preferencesBranch } = require('sdk/self');
-
-const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
-
-// Once Bug 903018 is resolved, just move the application testing to
-// module.metadata.engines
-//
-// This should work in Fennec, needs to be refactored to work, via bug 979645
-if (app.is('Firefox')) {
-  exports.testAOMLocalization = function(assert, done) {
-      tabs.open({
-        url: 'about:addons',
-        onReady: function(tab) {
-          tab.attach({
-            contentScriptWhen: 'end',
-            contentScript: 'function onLoad() {\n' +
-                             'unsafeWindow.removeEventListener("load", onLoad, false);\n' +
-                             'AddonManager.getAddonByID("' + self.id + '", function(aAddon) {\n' +
-                               'unsafeWindow.gViewController.viewObjects.detail.node.addEventListener("ViewChanged", function whenViewChanges() {\n' +
-                                 'unsafeWindow.gViewController.viewObjects.detail.node.removeEventListener("ViewChanged", whenViewChanges, false);\n' +
-                                 'setTimeout(function() {\n' + // TODO: figure out why this is necessary..
-                                     'self.postMessage({\n' +
-                                       'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[data-jetpack-id=\'' + self.id + '\']"))\n' +
-                                     '});\n' +
-                                 '}, 250);\n' +
-                               '}, false);\n' +
-                               'unsafeWindow.gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);\n' +
-                             '});\n' +
-                             'function getAttributes(ele) {\n' +
-                               'if (!ele) return {};\n' +
-                               'return {\n' +
-                                 'title: ele.getAttribute("title")\n' +
-                               '}\n' +
-                             '}\n' +
-                           '}\n' +
-                           // Wait for the load event ?
-                           'if (document.readyState == "complete") {\n' +
-                             'onLoad()\n' +
-                           '} else {\n' +
-                             'unsafeWindow.addEventListener("load", onLoad, false);\n' +
-                           '}\n',
-            onMessage: function(msg) {
-              // test somePreference
-              assert.equal(msg.somePreference.title, 'A', 'somePreference title is correct');
-              tab.close(done);
-            }
-          });
-        }
-      });
-  }
-} else {
-  exports['test unsupported'] = (assert) => assert.pass('This test is unsupported.');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-l10n/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "id": "test-simple-prefs-l10n",
-  "preferences": [{
-    "name": "somePreference",
-    "title": "some-title",
-    "description": "Some short description for the preference",
-    "type": "string",
-    "value": "TEST"
-  }]
-}
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/app-extension/application.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[App]
-Vendor=Varma
-Name=Test App
-Version=1.0
-BuildID=20060101
-Copyright=Copyright (c) 2009 Atul Varma
-ID=xulapp@toolness.com
-
-[Gecko]
-MinVersion=1.9.2.0
-MaxVersion=2.0.*
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/app-extension/bootstrap.js
+++ /dev/null
@@ -1,339 +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/. */
-
-// @see http://dxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp
-
-'use strict';
-
-// IMPORTANT: Avoid adding any initialization tasks here, if you need to do
-// something before add-on is loaded consider addon/runner module instead!
-
-const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
-        results: Cr, manager: Cm } = Components;
-const ioService = Cc['@mozilla.org/network/io-service;1'].
-                  getService(Ci.nsIIOService);
-const resourceHandler = ioService.getProtocolHandler('resource').
-                        QueryInterface(Ci.nsIResProtocolHandler);
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const prefService = Cc['@mozilla.org/preferences-service;1'].
-                    getService(Ci.nsIPrefService).
-                    QueryInterface(Ci.nsIPrefBranch);
-const appInfo = Cc["@mozilla.org/xre/app-info;1"].
-                getService(Ci.nsIXULAppInfo);
-const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
-           getService(Ci.nsIVersionComparator);
-
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm");
-
-const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
-                 'install', 'uninstall', 'upgrade', 'downgrade' ];
-
-const bind = Function.call.bind(Function.bind);
-
-var loader = null;
-var unload = null;
-var cuddlefishSandbox = null;
-var nukeTimer = null;
-
-// Utility function that synchronously reads local resource from the given
-// `uri` and returns content string.
-function readURI(uri) {
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(uri, "UTF-8"),
-    loadUsingSystemPrincipal: true
-  });
-  let stream = channel.open2();
-
-  let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
-    createInstance(Ci.nsIConverterInputStream);
-  cstream.init(stream, 'UTF-8', 0, 0);
-
-  let str = {};
-  let data = '';
-  let read = 0;
-  do {
-    read = cstream.readString(0xffffffff, str);
-    data += str.value;
-  } while (read != 0);
-
-  cstream.close();
-
-  return data;
-}
-
-// We don't do anything on install & uninstall yet, but in a future
-// we should allow add-ons to cleanup after uninstall.
-function install(data, reason) {}
-function uninstall(data, reason) {}
-
-function startup(data, reasonCode) {
-  try {
-    let reason = REASON[reasonCode];
-    // URI for the root of the XPI file.
-    // 'jar:' URI if the addon is packed, 'file:' URI otherwise.
-    // (Used by l10n module in order to fetch `locale` folder)
-    let rootURI = data.resourceURI.spec;
-
-    // TODO: Maybe we should perform read harness-options.json asynchronously,
-    // since we can't do anything until 'sessionstore-windows-restored' anyway.
-    let options = JSON.parse(readURI(rootURI + './harness-options.json'));
-
-    let id = options.jetpackID;
-    let name = options.name;
-
-    // Clean the metadata
-    options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {};
-
-    // freeze the permissionss
-    Object.freeze(options.metadata[name]['permissions']);
-    // freeze the metadata
-    Object.freeze(options.metadata[name]);
-
-    // Register a new resource 'domain' for this addon which is mapping to
-    // XPI's `resources` folder.
-    // Generate the domain name by using jetpack ID, which is the extension ID
-    // by stripping common characters that doesn't work as a domain name:
-    let uuidRe =
-      /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
-
-    let domain = id.
-      toLowerCase().
-      replace(/@/g, '-at-').
-      replace(/\./g, '-dot-').
-      replace(uuidRe, '$1');
-
-    let prefixURI = 'resource://' + domain + '/';
-    let resourcesURI = ioService.newURI(rootURI + '/resources/');
-    resourceHandler.setSubstitution(domain, resourcesURI);
-
-    // Create path to URLs mapping supported by loader.
-    let paths = {
-      // Relative modules resolve to add-on package lib
-      './': prefixURI + name + '/lib/',
-      './tests/': prefixURI + name + '/tests/',
-      '': 'resource://gre/modules/commonjs/'
-    };
-
-    // Maps addon lib and tests ressource folders for each package
-    paths = Object.keys(options.metadata).reduce(function(result, name) {
-      result[name + '/'] = prefixURI + name + '/lib/'
-      result[name + '/tests/'] = prefixURI + name + '/tests/'
-      return result;
-    }, paths);
-
-    // We need to map tests folder when we run sdk tests whose package name
-    // is stripped
-    if (name == 'addon-sdk')
-      paths['tests/'] = prefixURI + name + '/tests/';
-
-    let useBundledSDK = options['force-use-bundled-sdk'];
-    if (!useBundledSDK) {
-      try {
-        useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK");
-      }
-      catch (e) {
-        // Pref doesn't exist, allow using Firefox shipped SDK
-      }
-    }
-
-    // Starting with Firefox 21.0a1, we start using modules shipped into firefox
-    // Still allow using modules from the xpi if the manifest tell us to do so.
-    // And only try to look for sdk modules in xpi if the xpi actually ship them
-    if (options['is-sdk-bundled'] &&
-        (vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) {
-      // Maps sdk module folders to their resource folder
-      paths[''] = prefixURI + 'addon-sdk/lib/';
-      // test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
-      // so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
-      // until we no longer support SDK modules in XPI:
-      paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
-    }
-
-    // Retrieve list of module folder overloads based on preferences in order to
-    // eventually used a local modules instead of files shipped into Firefox.
-    let branch = prefService.getBranch('extensions.modules.' + id + '.path');
-    paths = branch.getChildList('', {}).reduce(function (result, name) {
-      // Allows overloading of any sub folder by replacing . by / in pref name
-      let path = name.substr(1).split('.').join('/');
-      // Only accept overloading folder by ensuring always ending with `/`
-      if (path) path += '/';
-      let fileURI = branch.getCharPref(name);
-
-      // On mobile, file URI has to end with a `/` otherwise, setSubstitution
-      // takes the parent folder instead.
-      if (fileURI[fileURI.length-1] !== '/')
-        fileURI += '/';
-
-      // Maps the given file:// URI to a resource:// in order to avoid various
-      // failure that happens with file:// URI and be close to production env
-      let resourcesURI = ioService.newURI(fileURI);
-      let resName = 'extensions.modules.' + domain + '.commonjs.path' + name;
-      resourceHandler.setSubstitution(resName, resourcesURI);
-
-      result[path] = 'resource://' + resName + '/';
-      return result;
-    }, paths);
-
-    // Make version 2 of the manifest
-    let manifest = options.manifest;
-
-    // Import `cuddlefish.js` module using a Sandbox and bootstrap loader.
-    let cuddlefishPath = 'loader/cuddlefish.js';
-    let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath;
-    if (paths['sdk/']) { // sdk folder has been overloaded
-                         // (from pref, or cuddlefish is still in the xpi)
-      cuddlefishURI = paths['sdk/'] + cuddlefishPath;
-    }
-    else if (paths['']) { // root modules folder has been overloaded
-      cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath;
-    }
-
-    cuddlefishSandbox = loadSandbox(cuddlefishURI);
-    let cuddlefish = cuddlefishSandbox.exports;
-
-    // Normalize `options.mainPath` so that it looks like one that will come
-    // in a new version of linker.
-    let main = options.mainPath;
-
-    unload = cuddlefish.unload;
-    loader = cuddlefish.Loader({
-      paths: paths,
-      // modules manifest.
-      manifest: manifest,
-
-      // Add-on ID used by different APIs as a unique identifier.
-      id: id,
-      // Add-on name.
-      name: name,
-      // Add-on version.
-      version: options.metadata[name].version,
-      // Add-on package descriptor.
-      metadata: options.metadata[name],
-      // Add-on load reason.
-      loadReason: reason,
-
-      prefixURI: prefixURI,
-      // Add-on URI.
-      rootURI: rootURI,
-      // options used by system module.
-      // File to write 'OK' or 'FAIL' (exit code emulation).
-      resultFile: options.resultFile,
-      // Arguments passed as --static-args
-      staticArgs: options.staticArgs,
-
-      // Arguments related to test runner.
-      modules: {
-        '@test/options': {
-          allTestModules: options.allTestModules,
-          iterations: options.iterations,
-          filter: options.filter,
-          profileMemory: options.profileMemory,
-          stopOnError: options.stopOnError,
-          verbose: options.verbose,
-          parseable: options.parseable,
-          checkMemory: options.check_memory,
-        }
-      }
-    });
-
-    let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI);
-    let require = cuddlefish.Require(loader, module);
-
-    require('sdk/addon/runner').startup(reason, {
-      loader: loader,
-      main: main,
-      prefsURI: rootURI + 'defaults/preferences/prefs.js'
-    });
-  } catch (error) {
-    dump('Bootstrap error: ' +
-         (error.message ? error.message : String(error)) + '\n' +
-         (error.stack || error.fileName + ': ' + error.lineNumber) + '\n');
-    throw error;
-  }
-};
-
-function loadSandbox(uri) {
-  let proto = {
-    sandboxPrototype: {
-      loadSandbox: loadSandbox,
-      ChromeWorker: ChromeWorker
-    }
-  };
-  let sandbox = Cu.Sandbox(systemPrincipal, proto);
-  // Create a fake commonjs environnement just to enable loading loader.js
-  // correctly
-  sandbox.exports = {};
-  sandbox.module = { uri: uri, exports: sandbox.exports };
-  sandbox.require = function (id) {
-    if (id !== "chrome")
-      throw new Error("Bootstrap sandbox `require` method isn't implemented.");
-
-    return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
-      CC: bind(CC, Components), components: Components,
-      ChromeWorker: ChromeWorker });
-  };
-  scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
-  return sandbox;
-}
-
-function unloadSandbox(sandbox) {
-  if (Cu.getClassName(sandbox, true) == "Sandbox")
-    Cu.nukeSandbox(sandbox);
-}
-
-function setTimeout(callback, delay) {
-  let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-  timer.initWithCallback({ notify: callback }, delay,
-                         Ci.nsITimer.TYPE_ONE_SHOT);
-  return timer;
-}
-
-function shutdown(data, reasonCode) {
-  let reason = REASON[reasonCode];
-  if (loader) {
-    unload(loader, reason);
-    unload = null;
-
-    // Don't waste time cleaning up if the application is shutting down
-    if (reason != "shutdown") {
-      // Avoid leaking all modules when something goes wrong with one particular
-      // module. Do not clean it up immediatly in order to allow executing some
-      // actions on addon disabling.
-      // We need to keep a reference to the timer, otherwise it is collected
-      // and won't ever fire.
-      nukeTimer = setTimeout(nukeModules, 1000);
-    }
-  }
-};
-
-function nukeModules() {
-  nukeTimer = null;
-  // module objects store `exports` which comes from sandboxes
-  // We should avoid keeping link to these object to avoid leaking sandboxes
-  for (let key in loader.modules) {
-    delete loader.modules[key];
-  }
-  // Direct links to sandboxes should be removed too
-  for (let key in loader.sandboxes) {
-    let sandbox = loader.sandboxes[key];
-    delete loader.sandboxes[key];
-    // Bug 775067: From FF17 we can kill all CCW from a given sandbox
-    unloadSandbox(sandbox);
-  }
-  loader = null;
-
-  // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
-  // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when
-  // the addon is unload.
-
-  unloadSandbox(cuddlefishSandbox.loaderSandbox);
-  unloadSandbox(cuddlefishSandbox.xulappSandbox);
-
-  // Bug 764840: We need to unload cuddlefish otherwise it will stay alive
-  // and keep a reference to this compartment.
-  unloadSandbox(cuddlefishSandbox);
-  cuddlefishSandbox = null;
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/app-extension/defaults/preferences/prefs.js
+++ /dev/null
@@ -1,7 +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/. */
-
-pref("extensions.test-simple-prefs@jetpack.somePreference", "TEST");
-pref("extensions.test-simple-prefs@jetpack.myInteger", 8);
-pref("extensions.test-simple-prefs@jetpack.myHiddenInt", 5);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/app-extension/install.rdf
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.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/. -->
-
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>xulapp@toolness.com</em:id>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-    <em:unpack>false</em:unpack>
-
-    <!-- Firefox -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>21.0</em:minVersion>
-        <em:maxVersion>25.0a1</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Test App</em:name>
-    <em:description>Harness for tests.</em:description>
-    <em:creator>Mozilla Corporation</em:creator>
-    <em:homepageURL></em:homepageURL>
-    <em:optionsType></em:optionsType>
-    <em:optionsURL></em:optionsURL>
-    <em:updateURL></em:updateURL>
-  </Description>
-</RDF>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/app-extension/options.xul
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" ?>
-<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <setting data-jetpack-id="test-simple-prefs@jetpack" pref="extensions.test-simple-prefs@jetpack.somePreference" pref-name="somePreference" title="some-title" type="string">Some short description for the preference</setting>
-  <setting data-jetpack-id="test-simple-prefs@jetpack" pref="extensions.test-simple-prefs@jetpack.myInteger" pref-name="myInteger" title="my-int" type="integer">How many of them we have.</setting>
-</vbox>
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/lib/main.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cu } = require('chrome');
-const sp = require('sdk/simple-prefs');
-const app = require('sdk/system/xul-app');
-const tabs = require('sdk/tabs');
-const { preferencesBranch, id } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
-
-exports.testRegression = (assert) => {
-  assert.equal(preferencesBranch, id, 'preferencesBranch returns id here');
-}
-
-exports.testDefaultValues = (assert) => {
-  assert.equal(sp.prefs.myHiddenInt, 5, 'myHiddenInt default is 5');
-  assert.equal(sp.prefs.myInteger, 8, 'myInteger default is 8');
-  assert.equal(sp.prefs.somePreference, 'TEST', 'somePreference default is correct');
-}
-
-exports.testOptionsType = function*(assert) {
-  let addon = yield getAddonByID(id);
-  assert.equal(addon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, 'options type is inline');
-}
-
-if (app.is('Firefox')) {
-  exports.testAOM = function(assert, done) {
-      tabs.open({
-      	url: 'about:addons',
-      	onReady: function(tab) {
-          tab.attach({
-            contentScriptWhen: 'end',
-          	contentScript: 'function onLoad() {\n' +
-                             'unsafeWindow.removeEventListener("load", onLoad, false);\n' +
-                             'AddonManager.getAddonByID("' + id + '", function(aAddon) {\n' +
-                               'unsafeWindow.gViewController.viewObjects.detail.node.addEventListener("ViewChanged", function whenViewChanges() {\n' +
-                                 'unsafeWindow.gViewController.viewObjects.detail.node.removeEventListener("ViewChanged", whenViewChanges, false);\n' +
-                                 'setTimeout(function() {\n' + // TODO: figure out why this is necessary..
-                                     'self.postMessage({\n' +
-                                       'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[title=\'some-title\']")),\n' +
-                                       'myInteger: getAttributes(unsafeWindow.document.querySelector("setting[title=\'my-int\']")),\n' +
-                                       'myHiddenInt: getAttributes(unsafeWindow.document.querySelector("setting[title=\'hidden-int\']"))\n' +
-                                     '});\n' +
-                                 '}, 250);\n' +
-                               '}, false);\n' +
-                               'unsafeWindow.gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);\n' +
-                             '});\n' +
-                             'function getAttributes(ele) {\n' +
-                               'if (!ele) return {};\n' +
-                               'return {\n' +
-                                 'pref: ele.getAttribute("pref"),\n' +
-                                 'type: ele.getAttribute("type"),\n' +
-                                 'title: ele.getAttribute("title"),\n' +
-                                 'desc: ele.getAttribute("desc")\n' +
-                               '}\n' +
-                             '}\n' +
-                           '}\n' +
-                           // Wait for the load event ?
-                           'if (document.readyState == "complete") {\n' +
-                             'onLoad()\n' +
-                           '} else {\n' +
-                             'unsafeWindow.addEventListener("load", onLoad, false);\n' +
-                           '}\n',
-            onMessage: function(msg) {
-              // test somePreference
-              assert.equal(msg.somePreference.type, 'string', 'some pref is a string');
-              assert.equal(msg.somePreference.pref, 'extensions.'+preferencesBranch+'.somePreference', 'somePreference path is correct');
-              assert.equal(msg.somePreference.title, 'some-title', 'somePreference title is correct');
-              assert.equal(msg.somePreference.desc, 'Some short description for the preference', 'somePreference description is correct');
-
-              // test myInteger
-              assert.equal(msg.myInteger.type, 'integer', 'myInteger is a int');
-              assert.equal(msg.myInteger.pref, 'extensions.'+preferencesBranch+'.myInteger', 'extensions.test-simple-prefs.myInteger');
-              assert.equal(msg.myInteger.title, 'my-int', 'myInteger title is correct');
-              assert.equal(msg.myInteger.desc, 'How many of them we have.', 'myInteger desc is correct');
-
-              // test myHiddenInt
-              assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
-              assert.equal(msg.myHiddenInt.pref, undefined, 'myHiddenInt was not displayed');
-              assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
-              assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
-
-              tab.close(done);
-            }
-          });
-      	}
-      });
-  }
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs-regression/package.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "id": "test-simple-prefs",
-    "preferences": [{
-        "name": "somePreference",
-        "title": "some-title",
-        "description": "Some short description for the preference",
-        "type": "string",
-        "value": "TEST"
-    },
-    {
-        "description": "How many of them we have.",
-        "name": "myInteger",
-        "type": "integer",
-        "value": 8,
-        "title": "my-int"
-    }, {
-        "name": "myHiddenInt",
-        "type": "integer",
-        "hidden": true,
-        "value": 5,
-        "title": "hidden-int"
-    }],
-    "preferences-branch": "simple-prefs-regression"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs/lib/main.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cu } = require('chrome');
-const sp = require('sdk/simple-prefs');
-const app = require('sdk/system/xul-app');
-const { id, preferencesBranch } = require('sdk/self');
-const { open } = require('sdk/preferences/utils');
-const { getTabForId } = require('sdk/tabs/utils');
-const { modelFor } = require('sdk/model/core');
-const { getAddonByID } = require('sdk/addon/manager');
-const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
-require('sdk/tabs');
-
-exports.testDefaultValues = function (assert) {
-  assert.equal(sp.prefs.myHiddenInt, 5, 'myHiddenInt default is 5');
-  assert.equal(sp.prefs.myInteger, 8, 'myInteger default is 8');
-  assert.equal(sp.prefs.somePreference, 'TEST', 'somePreference default is correct');
-}
-
-exports.testOptionsType = function*(assert) {
-  let addon = yield getAddonByID(id);
-  assert.equal(addon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, 'options type is inline');
-}
-
-exports.testButton = function(assert, done) {
-  open({ id: id }).then(({ tabId, document }) => {
-    let tab = modelFor(getTabForId(tabId));
-    sp.once('sayHello', _ => {
-      assert.pass('The button was pressed!');
-      tab.close(done);
-    });
-
-    tab.attach({
-      contentScript: 'unsafeWindow.document.querySelector("button[label=\'Click me!\']").click();'
-    });
-  });
-}
-
-if (app.is('Firefox')) {
-  exports.testAOM = function(assert, done) {
-    open({ id: id }).then(({ tabId }) => {
-      let tab = modelFor(getTabForId(tabId));
-      assert.pass('the add-on prefs page was opened.');
-
-      tab.attach({
-        contentScriptWhen: "end",
-        contentScript: 'self.postMessage({\n' +
-                         'someCount: unsafeWindow.document.querySelectorAll("setting[title=\'some-title\']").length,\n' +
-                         'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[title=\'some-title\']")),\n' +
-                         'myInteger: getAttributes(unsafeWindow.document.querySelector("setting[title=\'my-int\']")),\n' +
-                         'myHiddenInt: getAttributes(unsafeWindow.document.querySelector("setting[title=\'hidden-int\']")),\n' +
-                         'sayHello: getAttributes(unsafeWindow.document.querySelector("button[label=\'Click me!\']"))\n' +
-                       '});\n' +
-                       'function getAttributes(ele) {\n' +
-                         'if (!ele) return {};\n' +
-                         'return {\n' +
-                           'pref: ele.getAttribute("pref"),\n' +
-                           'type: ele.getAttribute("type"),\n' +
-                           'title: ele.getAttribute("title"),\n' +
-                           'desc: ele.getAttribute("desc"),\n' +
-                           '"data-jetpack-id": ele.getAttribute(\'data-jetpack-id\')\n' +
-                         '}\n' +
-                       '}\n',
-        onMessage: msg => {
-          // test against doc caching
-          assert.equal(msg.someCount, 1, 'there is exactly one <setting> node for somePreference');
-
-          // test somePreference
-          assert.equal(msg.somePreference.type, 'string', 'some pref is a string');
-          assert.equal(msg.somePreference.pref, 'extensions.' + id + '.somePreference', 'somePreference path is correct');
-          assert.equal(msg.somePreference.title, 'some-title', 'somePreference title is correct');
-          assert.equal(msg.somePreference.desc, 'Some short description for the preference', 'somePreference description is correct');
-          assert.equal(msg.somePreference['data-jetpack-id'], id, 'data-jetpack-id attribute value is correct');
-
-          // test myInteger
-          assert.equal(msg.myInteger.type, 'integer', 'myInteger is a int');
-          assert.equal(msg.myInteger.pref, 'extensions.' + id + '.myInteger', 'extensions.test-simple-prefs.myInteger');
-          assert.equal(msg.myInteger.title, 'my-int', 'myInteger title is correct');
-          assert.equal(msg.myInteger.desc, 'How many of them we have.', 'myInteger desc is correct');
-          assert.equal(msg.myInteger['data-jetpack-id'], id, 'data-jetpack-id attribute value is correct');
-
-          // test myHiddenInt
-          assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
-          assert.equal(msg.myHiddenInt.pref, undefined, 'myHiddenInt was not displayed');
-          assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
-          assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
-
-          // test sayHello
-          assert.equal(msg.sayHello['data-jetpack-id'], id, 'data-jetpack-id attribute value is correct');
-
-          tab.close(done);
-        }
-      });
-    })
-  }
-
-  // run it again, to test against inline options document caching
-  // and duplication of <setting> nodes upon re-entry to about:addons
-  exports.testAgainstDocCaching = exports.testAOM;
-}
-
-exports.testDefaultPreferencesBranch = function(assert) {
-  assert.equal(preferencesBranch, id, 'preferencesBranch default the same as self.id');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/simple-prefs/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "id": "test-simple-prefs@jetpack",
-  "preferences": [{
-    "name": "somePreference",
-    "title": "some-title",
-    "description": "Some short description for the preference",
-    "type": "string",
-    "value": "TEST"
-  },
-  {
-    "description": "How many of them we have.",
-    "name": "myInteger",
-    "type": "integer",
-    "value": 8,
-    "title": "my-int"
-  },
-  {
-    "name": "sayHello",
-    "type": "control",
-    "label": "Click me!",
-    "title": "hello"
-  },
-  {
-    "name": "myHiddenInt",
-    "type": "integer",
-    "hidden": true,
-    "value": 5,
-    "title": "hidden-int"
-  }],
-  "main": "./lib/main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/standard-id/lib/main.js
+++ /dev/null
@@ -1,30 +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 { id, preferencesBranch } = require('sdk/self');
-const simple = require('sdk/simple-prefs');
-const service = require('sdk/preferences/service');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testStandardID = function(assert) {
-  assert.equal(id, 'standard-id@jetpack', 'standard ID is standard');
-
-  assert.equal(simple.prefs.test13, 26, 'test13 is 26');
-
-  simple.prefs.test14 = '15';
-  assert.equal(service.get('extensions.standard-id@jetpack.test14'), '15', 'test14 is 15');
-  assert.equal(service.get('extensions.standard-id@jetpack.test14'), simple.prefs.test14, 'simple test14 also 15');
-}
-
-// from `/test/test-self.js`, adapted to `sdk/test/assert` API
-exports.testSelfID = function*(assert) {
-  assert.equal(typeof(id), 'string', 'self.id is a string');
-  assert.ok(id.length > 0, 'self.id not empty');
-  let addon = yield getAddonByID(id);
-  assert.ok(addon, 'found addon with self.id');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/standard-id/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "id": "standard-id@jetpack",
-    "fullName": "standard ID test",
-    "author": "Tomislav Jovanovic",
-    "preferences": [{
-        "name": "test13",
-        "type": "integer",
-        "title": "test13",
-        "value": 26
-    }],
-    "main": "./lib/main.js",
-    "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/tab-close-on-startup/main.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/. */
-'use strict';
-
-const { setTimeout } = require('sdk/timers');
-const tabs = require('sdk/tabs');
-
-var closeEvents = 0;
-const closeEventDetector = _ => closeEvents++;
-
-exports.testNoTabCloseOnStartup = function(assert, done) {
-  setTimeout(_ => {
-    assert.equal(closeEvents, 0, 'there were no tab close events detected');
-    tabs.open({
-      url: 'about:mozilla',
-      inBackground: true,
-      onReady: tab => tab.close(),
-      onClose: _ => {
-        assert.equal(closeEvents, 1, 'there was one tab close event detected');
-        done();
-      }
-    })
-  });
-}
-
-exports.main = function() {
-  tabs.on('close', closeEventDetector);
-
-  require("sdk/test/runner").runTestsFromModule(module);
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/tab-close-on-startup/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "test-tabs@jetpack",
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/toolkit-require-reload/main.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require("chrome");
-
-const toolkit = require("toolkit/require");
-
-const {tmpdir} = require("node/os");
-const {join} = require("sdk/fs/path");
-const {writeFile, unlink} = require("sdk/io/fs");
-const {fromFilename} = require("sdk/url");
-
-const makeCallback = (resolve, reject) => (error, result) => {
-  if (error) reject(error);
-  else resolve(result);
-};
-
-const remove = path => new Promise((resolve, reject) =>
-  unlink(path, makeCallback(resolve, reject)));
-
-const write = (...params) => new Promise((resolve, reject) =>
-  writeFile(...params, makeCallback(resolve, reject)));
-
-exports.testReload = function*(assert) {
-  const modulePath = join(tmpdir(), "toolkit-require-reload.js");
-  const moduleURI = fromFilename(modulePath);
-
-  yield write(modulePath, `exports.version = () => 1;`);
-
-  const v1 = toolkit.require(moduleURI);
-
-  assert.equal(v1.version(), 1, "module exports version");
-
-  yield write(modulePath, `exports.version = () => 2;`);
-
-  assert.equal(v1, toolkit.require(moduleURI),
-               "require does not reload modules");
-
-  const v2 = toolkit.require(moduleURI, {reload: true});
-  assert.equal(v2.version(), 2, "module was updated");
-
-  yield remove(modulePath);
-};
-
-exports.testReloadAll = function*(assert) {
-  const parentPath = join(tmpdir(), "toolkit-require-reload-parent.js");
-  const childPath = join(tmpdir(), "toolkit-require-reload-child.js");
-
-  const parentURI = fromFilename(parentPath);
-  const childURI = fromFilename(childPath);
-
-  yield write(childPath, `exports.name = () => "child"`);
-  yield write(parentPath, `const child = require("./toolkit-require-reload-child");
-                           exports.greet = () => "Hello " + child.name();`);
-
-  const parent1 = toolkit.require(parentURI);
-  assert.equal(parent1.greet(), "Hello child");
-
-  yield write(childPath, `exports.name = () => "father"`);
-  yield write(parentPath, `const child = require("./toolkit-require-reload-child");
-                           exports.greet = () => "Hello " + child.name() + "!";`);
-
-  const parent2 = toolkit.require(parentURI, {reload: true});
-  assert.equal(parent2.greet(), "Hello child!",
-               "only parent changes were picked up");
-
-  const parent3 = toolkit.require(parentURI, {reload: true, all: true});
-  assert.equal(parent3.greet(), "Hello father!",
-               "all changes were picked up");
-
-  yield remove(childPath);
-  yield remove(parentPath);
-};
-
-exports.main = _ => require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/toolkit-require-reload/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "@toolkit-require-reload",
-  "version": "0.0.1",
-  "main": "main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/translators/main.js
+++ /dev/null
@@ -1,20 +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 { id } = require('sdk/self');
-const { getAddonByID } = require('sdk/addon/manager');
-
-exports.testTranslators = function*(assert) {
-  let addon = yield getAddonByID(id);
-  let count = 0;
-  addon.translators.forEach(function({ name }) {
-    count++;
-    assert.equal(name, 'Erik Vold', 'The translator keys are correct');
-  });
-  assert.equal(count, 1, 'The translator key count is correct');
-  assert.equal(addon.translators.length, 1, 'The translator key length is correct');
-}
-
-require('sdk/test/runner').runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/translators/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "test-translators@jetpack",
-  "translators": [
-    "Erik Vold"
-  ],
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/addons/unsafe-content-script/main.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { create: makeFrame } = require("sdk/frame/utils");
-const { window } = require("sdk/addon/window");
-const { Loader } = require('sdk/test/loader');
-
-exports.testMembranelessMode = function(assert, done) {
-  const loader = Loader(module);
-  const Worker = loader.require("sdk/content/worker").Worker;
-
-  let url = "data:text/html;charset=utf-8," + encodeURIComponent(
-    '<script>' +
-    'function runTest() {' +
-    '  assert(fuu.bar == 42, "Content-script objects should be accessible to content with' +
-    '         the unsafe-content-script flag on.");' +
-    '}' +
-    '</script>'
-  );
-
-  let element = makeFrame(window.document, {
-    nodeName: "iframe",
-    type: "content",
-    allowJavascript: true,
-    allowPlugins: true,
-    allowAuth: true,
-    uri: url
-  });
-
-  element.addEventListener("DOMContentLoaded", onDOMReady);
-
-  function onDOMReady() {
-    let worker = Worker({
-      window: element.contentWindow,
-      contentScript:
-        'new ' + function () {
-          var assert = function assert(v, msg) {
-            self.port.emit("assert", { assertion: v, msg: msg });
-          }
-          var done = function done() {
-            self.port.emit("done");
-          }
-          window.wrappedJSObject.fuu = { bar: 42 };
-          window.wrappedJSObject.assert = assert;
-          window.wrappedJSObject.runTest();
-          done();
-        }
-    });
-
-    worker.port.on("done", () => {
-      // cleanup
-      element.remove();
-      worker.destroy();
-      loader.unload();
-
-      done();
-    });
-
-    worker.port.on("assert", function (data) {
-      assert.ok(data.assertion, data.msg);
-    });
-
-  }
-};
-
-require("sdk/test/runner").runTestsFromModule(module);
deleted file mode 100644
--- a/addon-sdk/source/test/addons/unsafe-content-script/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "id": "content-permissions@jetpack",
-  "permissions": {
-    "unsafe-content-script": true
-  },
-  "main": "./main.js",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/buffers/test-read-types.js
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-const { Buffer } = require('sdk/io/buffer');
-
-exports.testReadDouble = helper('readDoubleLE/readDoubleBE', function (assert) {
-  var buffer = new Buffer(8);
-
-  buffer[0] = 0x55;
-  buffer[1] = 0x55;
-  buffer[2] = 0x55;
-  buffer[3] = 0x55;
-  buffer[4] = 0x55;
-  buffer[5] = 0x55;
-  buffer[6] = 0xd5;
-  buffer[7] = 0x3f;
-  assert.equal(1.1945305291680097e+103, buffer.readDoubleBE(0));
-  assert.equal(0.3333333333333333, buffer.readDoubleLE(0));
-
-  buffer[0] = 1;
-  buffer[1] = 0;
-  buffer[2] = 0;
-  buffer[3] = 0;
-  buffer[4] = 0;
-  buffer[5] = 0;
-  buffer[6] = 0xf0;
-  buffer[7] = 0x3f;
-  assert.equal(7.291122019655968e-304, buffer.readDoubleBE(0));
-  assert.equal(1.0000000000000002, buffer.readDoubleLE(0));
-
-  buffer[0] = 2;
-  assert.equal(4.778309726801735e-299, buffer.readDoubleBE(0));
-  assert.equal(1.0000000000000004, buffer.readDoubleLE(0));
-
-  buffer[0] = 1;
-  buffer[6] = 0;
-  buffer[7] = 0;
-  assert.equal(7.291122019556398e-304, buffer.readDoubleBE(0));
-  assert.equal(5e-324, buffer.readDoubleLE(0));
-
-  buffer[0] = 0xff;
-  buffer[1] = 0xff;
-  buffer[2] = 0xff;
-  buffer[3] = 0xff;
-  buffer[4] = 0xff;
-  buffer[5] = 0xff;
-  buffer[6] = 0x0f;
-  buffer[7] = 0x00;
-  assert.ok(isNaN(buffer.readDoubleBE(0)));
-  assert.equal(2.225073858507201e-308, buffer.readDoubleLE(0));
-
-  buffer[6] = 0xef;
-  buffer[7] = 0x7f;
-  assert.ok(isNaN(buffer.readDoubleBE(0)));
-  assert.equal(1.7976931348623157e+308, buffer.readDoubleLE(0));
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0;
-  buffer[3] = 0;
-  buffer[4] = 0;
-  buffer[5] = 0;
-  buffer[6] = 0xf0;
-  buffer[7] = 0x3f;
-  assert.equal(3.03865e-319, buffer.readDoubleBE(0));
-  assert.equal(1, buffer.readDoubleLE(0));
-
-  buffer[6] = 0;
-  buffer[7] = 0x40;
-  assert.equal(3.16e-322, buffer.readDoubleBE(0));
-  assert.equal(2, buffer.readDoubleLE(0));
-
-  buffer[7] = 0xc0;
-  assert.equal(9.5e-322, buffer.readDoubleBE(0));
-  assert.equal(-2, buffer.readDoubleLE(0));
-
-  buffer[6] = 0x10;
-  buffer[7] = 0;
-  assert.equal(2.0237e-320, buffer.readDoubleBE(0));
-  assert.equal(2.2250738585072014e-308, buffer.readDoubleLE(0));
-
-  buffer[6] = 0;
-  assert.equal(0, buffer.readDoubleBE(0));
-  assert.equal(0, buffer.readDoubleLE(0));
-  assert.equal(false, 1 / buffer.readDoubleLE(0) < 0);
-
-  buffer[7] = 0x80;
-  assert.equal(6.3e-322, buffer.readDoubleBE(0));
-  assert.equal(0, buffer.readDoubleLE(0));
-  assert.equal(true, 1 / buffer.readDoubleLE(0) < 0);
-
-  buffer[6] = 0xf0;
-  buffer[7] = 0x7f;
-  assert.equal(3.0418e-319, buffer.readDoubleBE(0));
-  assert.equal(Infinity, buffer.readDoubleLE(0));
-
-  buffer[6] = 0xf0;
-  buffer[7] = 0xff;
-  assert.equal(3.04814e-319, buffer.readDoubleBE(0));
-  assert.equal(-Infinity, buffer.readDoubleLE(0));
-});
-
-
-exports.testReadFloat = helper('readFloatLE/readFloatBE', function (assert) {
-  var buffer = new Buffer(4);
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0x80;
-  buffer[3] = 0x3f;
-  assert.equal(4.600602988224807e-41, buffer.readFloatBE(0));
-  assert.equal(1, buffer.readFloatLE(0));
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0;
-  buffer[3] = 0xc0;
-  assert.equal(2.6904930515036488e-43, buffer.readFloatBE(0));
-  assert.equal(-2, buffer.readFloatLE(0));
-
-  buffer[0] = 0xff;
-  buffer[1] = 0xff;
-  buffer[2] = 0x7f;
-  buffer[3] = 0x7f;
-  assert.ok(isNaN(buffer.readFloatBE(0)));
-  assert.equal(3.4028234663852886e+38, buffer.readFloatLE(0));
-
-  buffer[0] = 0xab;
-  buffer[1] = 0xaa;
-  buffer[2] = 0xaa;
-  buffer[3] = 0x3e;
-  assert.equal(-1.2126478207002966e-12, buffer.readFloatBE(0));
-  assert.equal(0.3333333432674408, buffer.readFloatLE(0));
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0;
-  buffer[3] = 0;
-  assert.equal(0, buffer.readFloatBE(0));
-  assert.equal(0, buffer.readFloatLE(0));
-  assert.equal(false, 1 / buffer.readFloatLE(0) < 0);
-
-  buffer[3] = 0x80;
-  assert.equal(1.793662034335766e-43, buffer.readFloatBE(0));
-  assert.equal(0, buffer.readFloatLE(0));
-  assert.equal(true, 1 / buffer.readFloatLE(0) < 0);
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0x80;
-  buffer[3] = 0x7f;
-  assert.equal(4.609571298396486e-41, buffer.readFloatBE(0));
-  assert.equal(Infinity, buffer.readFloatLE(0));
-
-  buffer[0] = 0;
-  buffer[1] = 0;
-  buffer[2] = 0x80;
-  buffer[3] = 0xff;
-  assert.equal(4.627507918739843e-41, buffer.readFloatBE(0));
-  assert.equal(-Infinity, buffer.readFloatLE(0));
-});
-
-
-exports.testReadInt8 = helper('readInt8', function (assert) {
-  var data = new Buffer(4);
-
-  data[0] = 0x23;
-  assert.equal(0x23, data.readInt8(0));
-
-  data[0] = 0xff;
-  assert.equal(-1, data.readInt8(0));
-
-  data[0] = 0x87;
-  data[1] = 0xab;
-  data[2] = 0x7c;
-  data[3] = 0xef;
-  assert.equal(-121, data.readInt8(0));
-  assert.equal(-85, data.readInt8(1));
-  assert.equal(124, data.readInt8(2));
-  assert.equal(-17, data.readInt8(3));
-});
-
-
-exports.testReadInt16 = helper('readInt16BE/readInt16LE', function (assert) {
-  var buffer = new Buffer(6);
-
-  buffer[0] = 0x16;
-  buffer[1] = 0x79;
-  assert.equal(0x1679, buffer.readInt16BE(0));
-  assert.equal(0x7916, buffer.readInt16LE(0));
-
-  buffer[0] = 0xff;
-  buffer[1] = 0x80;
-  assert.equal(-128, buffer.readInt16BE(0));
-  assert.equal(-32513, buffer.readInt16LE(0));
-
-  /* test offset with weenix */
-  buffer[0] = 0x77;
-  buffer[1] = 0x65;
-  buffer[2] = 0x65;
-  buffer[3] = 0x6e;
-  buffer[4] = 0x69;
-  buffer[5] = 0x78;
-  assert.equal(0x7765, buffer.readInt16BE(0));
-  assert.equal(0x6565, buffer.readInt16BE(1));
-  assert.equal(0x656e, buffer.readInt16BE(2));
-  assert.equal(0x6e69, buffer.readInt16BE(3));
-  assert.equal(0x6978, buffer.readInt16BE(4));
-  assert.equal(0x6577, buffer.readInt16LE(0));
-  assert.equal(0x6565, buffer.readInt16LE(1));
-  assert.equal(0x6e65, buffer.readInt16LE(2));
-  assert.equal(0x696e, buffer.readInt16LE(3));
-  assert.equal(0x7869, buffer.readInt16LE(4));
-});
-
-
-exports.testReadInt32 = helper('readInt32BE/readInt32LE', function (assert) {
-  var buffer = new Buffer(6);
-
-  buffer[0] = 0x43;
-  buffer[1] = 0x53;
-  buffer[2] = 0x16;
-  buffer[3] = 0x79;
-  assert.equal(0x43531679, buffer.readInt32BE(0));
-  assert.equal(0x79165343, buffer.readInt32LE(0));
-
-  buffer[0] = 0xff;
-  buffer[1] = 0xfe;
-  buffer[2] = 0xef;
-  buffer[3] = 0xfa;
-  assert.equal(-69638, buffer.readInt32BE(0));
-  assert.equal(-84934913, buffer.readInt32LE(0));
-
-  buffer[0] = 0x42;
-  buffer[1] = 0xc3;
-  buffer[2] = 0x95;
-  buffer[3] = 0xa9;
-  buffer[4] = 0x36;
-  buffer[5] = 0x17;
-  assert.equal(0x42c395a9, buffer.readInt32BE(0));
-  assert.equal(-1013601994, buffer.readInt32BE(1));
-  assert.equal(-1784072681, buffer.readInt32BE(2));
-  assert.equal(-1449802942, buffer.readInt32LE(0));
-  assert.equal(917083587, buffer.readInt32LE(1));
-  assert.equal(389458325, buffer.readInt32LE(2));
-});
-
-
-/*
- * We need to check the following things:
- *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
- *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-exports.testReadUInt8 = helper('readUInt8', function (assert) {
-  var data = new Buffer(4);
-
-  data[0] = 23;
-  data[1] = 23;
-  data[2] = 23;
-  data[3] = 23;
-  assert.equal(23, data.readUInt8(0));
-  assert.equal(23, data.readUInt8(1));
-  assert.equal(23, data.readUInt8(2));
-  assert.equal(23, data.readUInt8(3));
-
-  data[0] = 255; /* If it became a signed int, would be -1 */
-  assert.equal(255, data.readUInt8(0));
-});
-
-
-/*
- * Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
- * now some of the issues actually matter:
- *  - We are correctly resolving big endian
- *  - Correctly resolving little endian
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-exports.testReadUInt16 = helper('readUInt16LE/readUInt16BE', function (assert) {
-  var data = new Buffer(4);
-
-  data[0] = 0;
-  data[1] = 0x23;
-  data[2] = 0x42;
-  data[3] = 0x3f;
-  assert.equal(0x23, data.readUInt16BE(0));
-  assert.equal(0x2342, data.readUInt16BE(1));
-  assert.equal(0x423f, data.readUInt16BE(2));
-  assert.equal(0x2300, data.readUInt16LE(0));
-  assert.equal(0x4223, data.readUInt16LE(1));
-  assert.equal(0x3f42, data.readUInt16LE(2));
-
-  data[0] = 0xfe;
-  data[1] = 0xfe;
-  assert.equal(0xfefe, data.readUInt16BE(0));
-  assert.equal(0xfefe, data.readUInt16LE(0));
-});
-
-
-/*
- * Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
- * now some of the issues actually matter:
- *  - We are correctly resolving big endian
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-exports.testReadUInt32 = helper('readUInt32LE/readUInt32BE', function (assert) {
-  var data = new Buffer(8);
-
-  data[0] = 0x32;
-  data[1] = 0x65;
-  data[2] = 0x42;
-  data[3] = 0x56;
-  data[4] = 0x23;
-  data[5] = 0xff;
-  assert.equal(0x32654256, data.readUInt32BE(0));
-  assert.equal(0x65425623, data.readUInt32BE(1));
-  assert.equal(0x425623ff, data.readUInt32BE(2));
-  assert.equal(0x56426532, data.readUInt32LE(0));
-  assert.equal(0x23564265, data.readUInt32LE(1));
-  assert.equal(0xff235642, data.readUInt32LE(2));
-});
-
-function helper (description, fn) {
-  let bulkAssert = {
-    equal: function (a, b) {
-      if (a !== b) throw new Error('Error found in ' + description);
-    },
-    ok: function (value) {
-      if (!value) throw new Error('Error found in ' + description);
-    },
-    throws: function (shouldThrow) {
-      let didItThrow = false;
-      try {
-        shouldThrow();
-      } catch (e) {
-        didItThrow = e;
-      }
-      if (!didItThrow)
-        throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
-    }
-  };
-  return function (assert) {
-    fn(bulkAssert);
-    // If we get here, no errors thrown
-    assert.pass('All tests passed for ' + description);
-  };
-}
deleted file mode 100644
--- a/addon-sdk/source/test/buffers/test-write-types.js
+++ /dev/null
@@ -1,602 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-const { Buffer } = require('sdk/io/buffer');
-
-exports.testWriteDouble = helper('writeDoubleBE/writeDoubleLE', function (assert) {
-  var buffer = new Buffer(16);
-
-  buffer.writeDoubleBE(2.225073858507201e-308, 0);
-  buffer.writeDoubleLE(2.225073858507201e-308, 8);
-  assert.equal(0x00, buffer[0]);
-  assert.equal(0x0f, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0xff, buffer[3]);
-  assert.equal(0xff, buffer[4]);
-  assert.equal(0xff, buffer[5]);
-  assert.equal(0xff, buffer[6]);
-  assert.equal(0xff, buffer[7]);
-  assert.equal(0xff, buffer[8]);
-  assert.equal(0xff, buffer[9]);
-  assert.equal(0xff, buffer[10]);
-  assert.equal(0xff, buffer[11]);
-  assert.equal(0xff, buffer[12]);
-  assert.equal(0xff, buffer[13]);
-  assert.equal(0x0f, buffer[14]);
-  assert.equal(0x00, buffer[15]);
-
-  buffer.writeDoubleBE(1.0000000000000004, 0);
-  buffer.writeDoubleLE(1.0000000000000004, 8);
-  assert.equal(0x3f, buffer[0]);
-  assert.equal(0xf0, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x02, buffer[7]);
-  assert.equal(0x02, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0xf0, buffer[14]);
-  assert.equal(0x3f, buffer[15]);
-
-  buffer.writeDoubleBE(-2, 0);
-  buffer.writeDoubleLE(-2, 8);
-  assert.equal(0xc0, buffer[0]);
-  assert.equal(0x00, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.equal(0x00, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0x00, buffer[14]);
-  assert.equal(0xc0, buffer[15]);
-
-  buffer.writeDoubleBE(1.7976931348623157e+308, 0);
-  buffer.writeDoubleLE(1.7976931348623157e+308, 8);
-  assert.equal(0x7f, buffer[0]);
-  assert.equal(0xef, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0xff, buffer[3]);
-  assert.equal(0xff, buffer[4]);
-  assert.equal(0xff, buffer[5]);
-  assert.equal(0xff, buffer[6]);
-  assert.equal(0xff, buffer[7]);
-  assert.equal(0xff, buffer[8]);
-  assert.equal(0xff, buffer[9]);
-  assert.equal(0xff, buffer[10]);
-  assert.equal(0xff, buffer[11]);
-  assert.equal(0xff, buffer[12]);
-  assert.equal(0xff, buffer[13]);
-  assert.equal(0xef, buffer[14]);
-  assert.equal(0x7f, buffer[15]);
-
-  buffer.writeDoubleBE(0 * -1, 0);
-  buffer.writeDoubleLE(0 * -1, 8);
-  assert.equal(0x80, buffer[0]);
-  assert.equal(0x00, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.equal(0x00, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0x00, buffer[14]);
-  assert.equal(0x80, buffer[15]);
-
-  buffer.writeDoubleBE(Infinity, 0);
-  buffer.writeDoubleLE(Infinity, 8);
-  assert.equal(0x7F, buffer[0]);
-  assert.equal(0xF0, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.equal(0x00, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0xF0, buffer[14]);
-  assert.equal(0x7F, buffer[15]);
-  assert.equal(Infinity, buffer.readDoubleBE(0));
-  assert.equal(Infinity, buffer.readDoubleLE(8));
-
-  buffer.writeDoubleBE(-Infinity, 0);
-  buffer.writeDoubleLE(-Infinity, 8);
-  assert.equal(0xFF, buffer[0]);
-  assert.equal(0xF0, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.equal(0x00, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0xF0, buffer[14]);
-  assert.equal(0xFF, buffer[15]);
-  assert.equal(-Infinity, buffer.readDoubleBE(0));
-  assert.equal(-Infinity, buffer.readDoubleLE(8));
-
-  buffer.writeDoubleBE(NaN, 0);
-  buffer.writeDoubleLE(NaN, 8);
-  // Darwin ia32 does the other kind of NaN.
-  // Compiler bug.  No one really cares.
-  assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
-  assert.equal(0xF8, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.equal(0x00, buffer[8]);
-  assert.equal(0x00, buffer[9]);
-  assert.equal(0x00, buffer[10]);
-  assert.equal(0x00, buffer[11]);
-  assert.equal(0x00, buffer[12]);
-  assert.equal(0x00, buffer[13]);
-  assert.equal(0xF8, buffer[14]);
-  // Darwin ia32 does the other kind of NaN.
-  // Compiler bug.  No one really cares.
-  assert.ok(0x7F === buffer[15] || 0xFF === buffer[15]);
-  assert.ok(isNaN(buffer.readDoubleBE(0)));
-  assert.ok(isNaN(buffer.readDoubleLE(8)));
-});
-
-exports.testWriteFloat = helper('writeFloatBE/writeFloatLE', function (assert) {
-  var buffer = new Buffer(8);
-
-  buffer.writeFloatBE(1, 0);
-  buffer.writeFloatLE(1, 4);
-  assert.equal(0x3f, buffer[0]);
-  assert.equal(0x80, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x80, buffer[6]);
-  assert.equal(0x3f, buffer[7]);
-
-  buffer.writeFloatBE(1 / 3, 0);
-  buffer.writeFloatLE(1 / 3, 4);
-  assert.equal(0x3e, buffer[0]);
-  assert.equal(0xaa, buffer[1]);
-  assert.equal(0xaa, buffer[2]);
-  assert.equal(0xab, buffer[3]);
-  assert.equal(0xab, buffer[4]);
-  assert.equal(0xaa, buffer[5]);
-  assert.equal(0xaa, buffer[6]);
-  assert.equal(0x3e, buffer[7]);
-
-  buffer.writeFloatBE(3.4028234663852886e+38, 0);
-  buffer.writeFloatLE(3.4028234663852886e+38, 4);
-  assert.equal(0x7f, buffer[0]);
-  assert.equal(0x7f, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0xff, buffer[3]);
-  assert.equal(0xff, buffer[4]);
-  assert.equal(0xff, buffer[5]);
-  assert.equal(0x7f, buffer[6]);
-  assert.equal(0x7f, buffer[7]);
-
-  buffer.writeFloatLE(1.1754943508222875e-38, 0);
-  buffer.writeFloatBE(1.1754943508222875e-38, 4);
-  assert.equal(0x00, buffer[0]);
-  assert.equal(0x00, buffer[1]);
-  assert.equal(0x80, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x80, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-
-  buffer.writeFloatBE(0 * -1, 0);
-  buffer.writeFloatLE(0 * -1, 4);
-  assert.equal(0x80, buffer[0]);
-  assert.equal(0x00, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x80, buffer[7]);
-
-  buffer.writeFloatBE(Infinity, 0);
-  buffer.writeFloatLE(Infinity, 4);
-  assert.equal(0x7F, buffer[0]);
-  assert.equal(0x80, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x80, buffer[6]);
-  assert.equal(0x7F, buffer[7]);
-  assert.equal(Infinity, buffer.readFloatBE(0));
-  assert.equal(Infinity, buffer.readFloatLE(4));
-
-  buffer.writeFloatBE(-Infinity, 0);
-  buffer.writeFloatLE(-Infinity, 4);
-  // Darwin ia32 does the other kind of NaN.
-  // Compiler bug.  No one really cares.
-  assert.ok(0xFF === buffer[0] || 0x7F === buffer[0]);
-  assert.equal(0x80, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x80, buffer[6]);
-  assert.equal(0xFF, buffer[7]);
-  assert.equal(-Infinity, buffer.readFloatBE(0));
-  assert.equal(-Infinity, buffer.readFloatLE(4));
-
-  buffer.writeFloatBE(NaN, 0);
-  buffer.writeFloatLE(NaN, 4);
-  // Darwin ia32 does the other kind of NaN.
-  // Compiler bug.  No one really cares.
-  assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
-  assert.equal(0xc0, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0xc0, buffer[6]);
-  // Darwin ia32 does the other kind of NaN.
-  // Compiler bug.  No one really cares.
-  assert.ok(0x7F === buffer[7] || 0xFF === buffer[7]);
-  assert.ok(isNaN(buffer.readFloatBE(0)));
-  assert.ok(isNaN(buffer.readFloatLE(4)));
-});
-
-
-exports.testWriteInt8 = helper('writeInt8', function (assert) {
-  var buffer = new Buffer(2);
-
-  buffer.writeInt8(0x23, 0);
-  buffer.writeInt8(-5, 1);
-
-  assert.equal(0x23, buffer[0]);
-  assert.equal(0xfb, buffer[1]);
-
-  /* Make sure we handle truncation correctly */
-  assert.throws(function() {
-    buffer.writeInt8(0xabc, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt8(0xabc, 0);
-  });
-
-  /* Make sure we handle min/max correctly */
-  buffer.writeInt8(0x7f, 0);
-  buffer.writeInt8(-0x80, 1);
-
-  assert.equal(0x7f, buffer[0]);
-  assert.equal(0x80, buffer[1]);
-  assert.throws(function() {
-    buffer.writeInt8(0x7f + 1, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt8(-0x80 - 1, 0);
-  });
-});
-
-
-exports.testWriteInt16 = helper('writeInt16LE/writeInt16BE', function (assert) {
-  var buffer = new Buffer(6);
-
-  buffer.writeInt16BE(0x0023, 0);
-  buffer.writeInt16LE(0x0023, 2);
-  assert.equal(0x00, buffer[0]);
-  assert.equal(0x23, buffer[1]);
-  assert.equal(0x23, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-
-  buffer.writeInt16BE(-5, 0);
-  buffer.writeInt16LE(-5, 2);
-  assert.equal(0xff, buffer[0]);
-  assert.equal(0xfb, buffer[1]);
-  assert.equal(0xfb, buffer[2]);
-  assert.equal(0xff, buffer[3]);
-
-  buffer.writeInt16BE(-1679, 1);
-  buffer.writeInt16LE(-1679, 3);
-  assert.equal(0xf9, buffer[1]);
-  assert.equal(0x71, buffer[2]);
-  assert.equal(0x71, buffer[3]);
-  assert.equal(0xf9, buffer[4]);
-
-  /* Make sure we handle min/max correctly */
-  buffer.writeInt16BE(0x7fff, 0);
-  buffer.writeInt16BE(-0x8000, 2);
-  assert.equal(0x7f, buffer[0]);
-  assert.equal(0xff, buffer[1]);
-  assert.equal(0x80, buffer[2]);
-  assert.equal(0x00, buffer[3]);
-  assert.throws(function() {
-    buffer.writeInt16BE(0x7fff + 1, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt16BE(-0x8000 - 1, 0);
-  });
-
-  buffer.writeInt16LE(0x7fff, 0);
-  buffer.writeInt16LE(-0x8000, 2);
-  assert.equal(0xff, buffer[0]);
-  assert.equal(0x7f, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x80, buffer[3]);
-  assert.throws(function() {
-    buffer.writeInt16LE(0x7fff + 1, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt16LE(-0x8000 - 1, 0);
-  });
-});
-
-exports.testWriteInt32 = helper('writeInt32BE/writeInt32LE', function (assert) {
-  var buffer = new Buffer(8);
-
-  buffer.writeInt32BE(0x23, 0);
-  buffer.writeInt32LE(0x23, 4);
-  assert.equal(0x00, buffer[0]);
-  assert.equal(0x00, buffer[1]);
-  assert.equal(0x00, buffer[2]);
-  assert.equal(0x23, buffer[3]);
-  assert.equal(0x23, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-
-  buffer.writeInt32BE(-5, 0);
-  buffer.writeInt32LE(-5, 4);
-  assert.equal(0xff, buffer[0]);
-  assert.equal(0xff, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0xfb, buffer[3]);
-  assert.equal(0xfb, buffer[4]);
-  assert.equal(0xff, buffer[5]);
-  assert.equal(0xff, buffer[6]);
-  assert.equal(0xff, buffer[7]);
-
-  buffer.writeInt32BE(-805306713, 0);
-  buffer.writeInt32LE(-805306713, 4);
-  assert.equal(0xcf, buffer[0]);
-  assert.equal(0xff, buffer[1]);
-  assert.equal(0xfe, buffer[2]);
-  assert.equal(0xa7, buffer[3]);
-  assert.equal(0xa7, buffer[4]);
-  assert.equal(0xfe, buffer[5]);
-  assert.equal(0xff, buffer[6]);
-  assert.equal(0xcf, buffer[7]);
-
-  /* Make sure we handle min/max correctly */
-  buffer.writeInt32BE(0x7fffffff, 0);
-  buffer.writeInt32BE(-0x80000000, 4);
-  assert.equal(0x7f, buffer[0]);
-  assert.equal(0xff, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0xff, buffer[3]);
-  assert.equal(0x80, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x00, buffer[7]);
-  assert.throws(function() {
-    buffer.writeInt32BE(0x7fffffff + 1, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt32BE(-0x80000000 - 1, 0);
-  });
-
-  buffer.writeInt32LE(0x7fffffff, 0);
-  buffer.writeInt32LE(-0x80000000, 4);
-  assert.equal(0xff, buffer[0]);
-  assert.equal(0xff, buffer[1]);
-  assert.equal(0xff, buffer[2]);
-  assert.equal(0x7f, buffer[3]);
-  assert.equal(0x00, buffer[4]);
-  assert.equal(0x00, buffer[5]);
-  assert.equal(0x00, buffer[6]);
-  assert.equal(0x80, buffer[7]);
-  assert.throws(function() {
-    buffer.writeInt32LE(0x7fffffff + 1, 0);
-  });
-  assert.throws(function() {
-    buffer.writeInt32LE(-0x80000000 - 1, 0);
-  });
-});
-
-/*
- * We need to check the following things:
- *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
- *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-exports.testWriteUInt8 = helper('writeUInt8', function (assert) {
-  var data = new Buffer(4);
-
-  data.writeUInt8(23, 0);
-  data.writeUInt8(23, 1);
-  data.writeUInt8(23, 2);
-  data.writeUInt8(23, 3);
-  assert.equal(23, data[0]);
-  assert.equal(23, data[1]);
-  assert.equal(23, data[2]);
-  assert.equal(23, data[3]);
-
-  data.writeUInt8(23, 0);
-  data.writeUInt8(23, 1);
-  data.writeUInt8(23, 2);
-  data.writeUInt8(23, 3);
-  assert.equal(23, data[0]);
-  assert.equal(23, data[1]);
-  assert.equal(23, data[2]);
-  assert.equal(23, data[3]);
-
-  data.writeUInt8(255, 0);
-  assert.equal(255, data[0]);
-
-  data.writeUInt8(255, 0);
-  assert.equal(255, data[0]);
-});
-
-
-exports.testWriteUInt16 = helper('writeUInt16BE/writeUInt16LE', function (assert) {
-  var value = 0x2343;
-  var data = new Buffer(4);
-
-  data.writeUInt16BE(value, 0);
-  assert.equal(0x23, data[0]);
-  assert.equal(0x43, data[1]);
-
-  data.writeUInt16BE(value, 1);
-  assert.equal(0x23, data[1]);
-  assert.equal(0x43, data[2]);
-
-  data.writeUInt16BE(value, 2);
-  assert.equal(0x23, data[2]);
-  assert.equal(0x43, data[3]);
-
-  data.writeUInt16LE(value, 0);
-  assert.equal(0x23, data[1]);
-  assert.equal(0x43, data[0]);
-
-  data.writeUInt16LE(value, 1);
-  assert.equal(0x23, data[2]);
-  assert.equal(0x43, data[1]);
-
-  data.writeUInt16LE(value, 2);
-  assert.equal(0x23, data[3]);
-  assert.equal(0x43, data[2]);
-
-  value = 0xff80;
-  data.writeUInt16LE(value, 0);
-  assert.equal(0xff, data[1]);
-  assert.equal(0x80, data[0]);
-
-  data.writeUInt16BE(value, 0);
-  assert.equal(0xff, data[0]);
-  assert.equal(0x80, data[1]);
-});
-
-
-exports.testWriteUInt32 = helper('writeUInt32BE/writeUInt32LE', function (assert) {
-  var data = new Buffer(6);
-  var value = 0xe7f90a6d;
-
-  data.writeUInt32BE(value, 0);
-  assert.equal(0xe7, data[0]);
-  assert.equal(0xf9, data[1]);
-  assert.equal(0x0a, data[2]);
-  assert.equal(0x6d, data[3]);
-
-  data.writeUInt32BE(value, 1);
-  assert.equal(0xe7, data[1]);
-  assert.equal(0xf9, data[2]);
-  assert.equal(0x0a, data[3]);
-  assert.equal(0x6d, data[4]);
-
-  data.writeUInt32BE(value, 2);
-  assert.equal(0xe7, data[2]);
-  assert.equal(0xf9, data[3]);
-  assert.equal(0x0a, data[4]);
-  assert.equal(0x6d, data[5]);
-
-  data.writeUInt32LE(value, 0);
-  assert.equal(0xe7, data[3]);
-  assert.equal(0xf9, data[2]);
-  assert.equal(0x0a, data[1]);
-  assert.equal(0x6d, data[0]);
-
-  data.writeUInt32LE(value, 1);
-  assert.equal(0xe7, data[4]);
-  assert.equal(0xf9, data[3]);
-  assert.equal(0x0a, data[2]);
-  assert.equal(0x6d, data[1]);
-
-  data.writeUInt32LE(value, 2);
-  assert.equal(0xe7, data[5]);
-  assert.equal(0xf9, data[4]);
-  assert.equal(0x0a, data[3]);
-  assert.equal(0x6d, data[2]);
-});
-
-function helper (description, fn) {
-  return function (assert) {
-    let bulkAssert = {
-      equal: function (a, b) {
-        if (a !== b) throw new Error('Error found in ' + description);
-      },
-      ok: function (value) {
-        if (!value) throw new Error('Error found in ' + description);
-      },
-      /*
-       * TODO
-       * There should be errors when setting outside of the value range
-       * of the data type (like writeInt8 with value of 1000), but DataView
-       * does not throw; seems to just grab the appropriate max bits.
-       * So ignoring this test for now
-       */
-      throws: function (shouldThrow) {
-        assert.pass(description + ': Need to implement error handling for setting buffer values ' +
-          'outside of the data types\' range.');
-        /*
-        let didItThrow = false;
-        try {
-          shouldThrow();
-        } catch (e) {
-          didItThrow = e;
-        }
-        if (!didItThrow)
-          throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
-        */
-      }
-    };
-    fn(bulkAssert);
-    // If we get here, no errors thrown
-    assert.pass('All tests passed for ' + description);
-  };
-}
deleted file mode 100644
--- a/addon-sdk/source/test/commonjs-test-adapter/asserts.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const AssertBase = require("sdk/test/assert").Assert;
-
-/**
- * Generates custom assertion constructors that may be bundled with a test
- * suite.
- * @params {String}
- *    names of assertion function to be added to the generated Assert.
- */
-function Assert() {
-  let assertDescriptor = {};
-  Array.forEach(arguments, function(name) {
-    assertDescriptor[name] = { value: function(message) {
-      this.pass(message);
-    }}
-  });
-
-  return function Assert() {
-    return Object.create(AssertBase.apply(null, arguments), assertDescriptor);
-  };
-}
-
-exports["test suite"] = {
-  Assert: Assert("foo"),
-  "test that custom assertor is passed to test function": function(assert) {
-    assert.ok("foo" in assert, "custom assertion function `foo` is defined");
-    assert.foo("custom assertion function `foo` is called");
-  },
-  "test sub suite": {
-    "test that `Assert` is inherited by sub suits": function(assert) {
-      assert.ok("foo" in assert, "assertion function `foo` is not defined");
-    },
-    "test sub sub suite": {
-      Assert: Assert("bar"),
-      "test that custom assertor is passed to test function": function(assert) {
-        assert.ok("bar" in assert,
-                  "custom assertion function `bar` is defined");
-        assert.bar("custom assertion function `bar` is called");
-      },
-      "test that `Assert` is not inherited by sub sub suits": function(assert) {
-        assert.ok(!("foo" in assert),
-                  "assertion function `foo` is not defined");
-      }
-    }
-  }
-};
-
-if (module == require.main)
-  require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/context-menu/framescript.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const Ci = Components.interfaces;
-
-addMessageListener("sdk/test/context-menu/open", message => {
-  const {data, name} = message;
-  const target = data.target && content.document.querySelector(data.target);
-  if (target) {
-    target.scrollIntoView();
-  }
-  const rect = target ? target.getBoundingClientRect() :
-               {left:0, top:0, width:0, height:0};
-
-
-  content.
-    QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDOMWindowUtils).
-    sendMouseEvent("contextmenu",
-                   rect.left + (rect.width / 2),
-                   rect.top + (rect.height / 2),
-                   2, 1, 0);
-});
-
-addMessageListener("sdk/test/context-menu/select", message => {
-  const {data, name} = message;
-  const {document} = content;
-  if (data) {
-    if (typeof(data) === "string") {
-      const target = document.querySelector(data);
-      document.getSelection().selectAllChildren(target);
-    } else {
-      const target = document.querySelector(data.target);
-      target.focus();
-      target.setSelectionRange(data.start, data.end);
-    }
-  } else {
-    document.getSelection().collapse(document.documentElement, 0);
-  }
-
-  sendAsyncMessage("sdk/test/context-menu/selected");
-});
deleted file mode 100644
--- a/addon-sdk/source/test/context-menu/test-helper.js
+++ /dev/null
@@ -1,539 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-const { Ci } = require("chrome");
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { Loader } = require('sdk/test/loader');
-const { merge } = require("sdk/util/object");
-const observers = require("sdk/system/events");
-const { defer } = require("sdk/core/promise");
-const timer = require("sdk/timers");
-
-// These should match the same constants in the module.
-const ITEM_CLASS = "addon-context-menu-item";
-const SEPARATOR_CLASS = "addon-context-menu-separator";
-const OVERFLOW_THRESH_DEFAULT = 10;
-const OVERFLOW_THRESH_PREF =
-  "extensions.addon-sdk.context-menu.overflowThreshold";
-const OVERFLOW_MENU_CLASS = "addon-content-menu-overflow-menu";
-const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup";
-
-const TEST_DOC_URL = module.uri.replace(/context-menu\/test-helper\.js$/, "test-context-menu.html");
-
-// This makes it easier to run tests by handling things like opening the menu,
-// opening new windows, making assertions, etc.  Methods on |test| can be called
-// on instances of this class.  Don't forget to call done() to end the test!
-// WARNING: This looks up items in popups by comparing labels, so don't give two
-// items the same label.
-function TestHelper(assert, done) {
-  // Methods on the wrapped test can be called on this object.
-  for (var prop in assert)
-    this[prop] = (...args) => assert[prop].apply(assert, args);
-  this.assert = assert;
-  this.end = done;
-  this.loaders = [];
-  this.browserWindow = getMostRecentBrowserWindow();
-  this.overflowThreshValue = require("sdk/preferences/service").
-                             get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
-  this.done = this.done.bind(this);
-}
-
-TestHelper.prototype = {
-  get contextMenuPopup() {
-    return this.browserWindow.document.getElementById("contentAreaContextMenu");
-  },
-
-  get contextMenuSeparator() {
-    return this.browserWindow.document.querySelector("." + SEPARATOR_CLASS);
-  },
-
-  get overflowPopup() {
-    return this.browserWindow.document.querySelector("." + OVERFLOW_POPUP_CLASS);
-  },
-
-  get overflowSubmenu() {
-    return this.browserWindow.document.querySelector("." + OVERFLOW_MENU_CLASS);
-  },
-
-  get tabBrowser() {
-    return this.browserWindow.gBrowser;
-  },
-
-  // Asserts that elt, a DOM element representing item, looks OK.
-  checkItemElt: function (elt, item) {
-    let itemType = this.getItemType(item);
-
-    switch (itemType) {
-    case "Item":
-      this.assert.equal(elt.localName, "menuitem",
-                            "Item DOM element should be a xul:menuitem");
-      if (typeof(item.data) === "string") {
-        this.assert.equal(elt.getAttribute("value"), item.data,
-                              "Item should have correct data");
-      }
-      break
-    case "Menu":
-      this.assert.equal(elt.localName, "menu",
-                            "Menu DOM element should be a xul:menu");
-      let subPopup = elt.firstChild;
-      this.assert.ok(subPopup, "xul:menu should have a child");
-      this.assert.equal(subPopup.localName, "menupopup",
-                            "xul:menu's first child should be a menupopup");
-      break;
-    case "Separator":
-      this.assert.equal(elt.localName, "menuseparator",
-                         "Separator DOM element should be a xul:menuseparator");
-      break;
-    }
-
-    if (itemType === "Item" || itemType === "Menu") {
-      this.assert.equal(elt.getAttribute("label"), item.label,
-                            "Item should have correct title");
-
-      // validate accesskey prop
-      if (item.accesskey) {
-        this.assert.equal(elt.getAttribute("accesskey"),
-                          item.accesskey,
-                          "Item should have correct accesskey");
-      }
-      else {
-        this.assert.equal(elt.getAttribute("accesskey"),
-                          "",
-                          "Item should not have accesskey");
-      }
-
-      // validate image prop
-      if (typeof(item.image) === "string") {
-        this.assert.equal(elt.getAttribute("image"), item.image,
-                              "Item should have correct image");
-        if (itemType === "Menu")
-          this.assert.ok(elt.classList.contains("menu-iconic"),
-                           "Menus with images should have the correct class")
-        else
-          this.assert.ok(elt.classList.contains("menuitem-iconic"),
-                           "Items with images should have the correct class")
-      }
-      else {
-        this.assert.ok(!elt.getAttribute("image"),
-                         "Item should not have image");
-        this.assert.ok(!elt.classList.contains("menu-iconic") && !elt.classList.contains("menuitem-iconic"),
-                         "The iconic classes should not be present")
-      }
-    }
-  },
-
-  // Asserts that the context menu looks OK given the arguments.  presentItems
-  // are items that have been added to the menu.  absentItems are items that
-  // shouldn't match the current context.  removedItems are items that have been
-  // removed from the menu.
-  checkMenu: function (presentItems, absentItems, removedItems) {
-    // Count up how many top-level items there are
-    let total = 0;
-    for (let item of presentItems) {
-      if (absentItems.indexOf(item) < 0 && removedItems.indexOf(item) < 0)
-        total++;
-    }
-
-    let separator = this.contextMenuSeparator;
-    if (total == 0) {
-      this.assert.ok(!separator || separator.hidden,
-                       "separator should not be present");
-    }
-    else {
-      this.assert.ok(separator && !separator.hidden,
-                       "separator should be present");
-    }
-
-    let mainNodes = this.browserWindow.document.querySelectorAll("#contentAreaContextMenu > ." + ITEM_CLASS);
-    let overflowNodes = this.browserWindow.document.querySelectorAll("." + OVERFLOW_POPUP_CLASS + " > ." + ITEM_CLASS);
-
-    this.assert.ok(mainNodes.length == 0 || overflowNodes.length == 0,
-                     "Should only see nodes at the top level or in overflow");
-
-    let overflow = this.overflowSubmenu;
-    if (this.shouldOverflow(total)) {
-      this.assert.ok(overflow && !overflow.hidden,
-                       "overflow menu should be present");
-      this.assert.equal(mainNodes.length, 0,
-                            "should be no items in the main context menu");
-    }
-    else {
-      this.assert.ok(!overflow || overflow.hidden,
-                       "overflow menu should not be present");
-      // When visible nodes == 0 they could be in overflow or top level
-      if (total > 0) {
-        this.assert.equal(overflowNodes.length, 0,
-                              "should be no items in the overflow context menu");
-      }
-    }
-
-    // Iterate over wherever the nodes have ended up
-    let nodes = mainNodes.length ? mainNodes : overflowNodes;
-    this.checkNodes(nodes, presentItems, absentItems, removedItems)
-    let pos = 0;
-  },
-
-  // Recurses through the item hierarchy of presentItems comparing it to the
-  // node hierarchy of nodes. Any items in removedItems will be skipped (so
-  // should not exist in the XUL), any items in absentItems must exist and be
-  // hidden
-  checkNodes: function (nodes, presentItems, absentItems, removedItems) {
-    let pos = 0;
-    for (let item of presentItems) {
-      // Removed items shouldn't be in the list
-      if (removedItems.indexOf(item) >= 0)
-        continue;
-
-      if (nodes.length <= pos) {
-        this.assert.ok(false, "Not enough nodes");
-        return;
-      }
-
-      let hidden = absentItems.indexOf(item) >= 0;
-
-      this.checkItemElt(nodes[pos], item);
-      this.assert.equal(nodes[pos].hidden, hidden,
-                            "hidden should be set correctly");
-
-      // The contents of hidden menus doesn't matter so much
-      if (!hidden && this.getItemType(item) == "Menu") {
-        this.assert.equal(nodes[pos].firstChild.localName, "menupopup",
-                              "menu XUL should contain a menupopup");
-        this.checkNodes(nodes[pos].firstChild.childNodes, item.items, absentItems, removedItems);
-      }
-
-      if (pos > 0)
-        this.assert.equal(nodes[pos].previousSibling, nodes[pos - 1],
-                              "nodes should all be in the same group");
-      pos++;
-    }
-
-    this.assert.equal(nodes.length, pos,
-                          "should have checked all the XUL nodes");
-  },
-
-  // Attaches an event listener to node.  The listener is automatically removed
-  // when it's fired (so it's assumed it will fire), and callback is called
-  // after a short delay.  Since the module we're testing relies on the same
-  // event listeners to do its work, this is to give them a little breathing
-  // room before callback runs.  Inside callback |this| is this object.
-  // Optionally you can pass a function to test if the event is the event you
-  // want.
-  delayedEventListener: function (node, event, callback, useCapture, isValid) {
-    const self = this;
-    node.addEventListener(event, function handler(evt) {
-      if (isValid && !isValid(evt))
-        return;
-      node.removeEventListener(event, handler, useCapture);
-      timer.setTimeout(function () {
-        try {
-          callback.call(self, evt);
-        }
-        catch (err) {
-          self.assert.fail(err);
-          self.end();
-        }
-      }, 20);
-    }, useCapture);
-  },
-
-  // Call to finish the test.
-  done: function () {
-    const self = this;
-    function commonDone() {
-      this.closeTab();
-
-      while (this.loaders.length) {
-        this.loaders[0].unload();
-      }
-
-      require("sdk/preferences/service").set(OVERFLOW_THRESH_PREF, self.overflowThreshValue);
-
-      this.end();
-    }
-
-    function closeBrowserWindow() {
-      if (this.oldBrowserWindow) {
-        this.delayedEventListener(this.browserWindow, "unload", commonDone,
-                                  false);
-        this.browserWindow.close();
-        this.browserWindow = this.oldBrowserWindow;
-        delete this.oldBrowserWindow;
-      }
-      else {
-        commonDone.call(this);
-      }
-    };
-
-    if (this.contextMenuPopup.state == "closed") {
-      closeBrowserWindow.call(this);
-    }
-    else {
-      this.delayedEventListener(this.contextMenuPopup, "popuphidden",
-                                function () {
-                                  return closeBrowserWindow.call(this);
-                                },
-                                false);
-      this.contextMenuPopup.hidePopup();
-    }
-  },
-
-  closeTab: function() {
-    if (this.tab) {
-      this.tabBrowser.removeTab(this.tab);
-      this.tabBrowser.selectedTab = this.oldSelectedTab;
-      this.tab = null;
-    }
-  },
-
-  // Returns the DOM element in popup corresponding to item.
-  // WARNING: The element is found by comparing labels, so don't give two items
-  // the same label.
-  getItemElt: function (popup, item) {
-    let nodes = popup.childNodes;
-    for (let i = nodes.length - 1; i >= 0; i--) {
-      if (this.getItemType(item) === "Separator") {
-        if (nodes[i].localName === "menuseparator")
-          return nodes[i];
-      }
-      else if (nodes[i].getAttribute("label") === item.label)
-        return nodes[i];
-    }
-    return null;
-  },
-
-  // Returns "Item", "Menu", or "Separator".
-  getItemType: function (item) {
-    // Could use instanceof here, but that would require accessing the loader
-    // that created the item, and I don't want to A) somehow search through the
-    // this.loaders list to find it, and B) assume there are any live loaders at
-    // all.
-    return /^\[object (Item|Menu|Separator)/.exec(item.toString())[1];
-  },
-
-  // Returns a wrapper around a new loader: { loader, cm, unload, globalScope }.
-  // loader is a Cuddlefish sandboxed loader, cm is the context menu module,
-  // globalScope is the context menu module's global scope, and unload is a
-  // function that unloads the loader and associated resources.
-  newLoader: function () {
-    const self = this;
-    const selfModule = require('sdk/self');
-    let loader = Loader(module, null, null, {
-      modules: {
-        "sdk/self": merge({}, selfModule, {
-          data: merge({}, selfModule.data, require("../fixtures"))
-        })
-      }
-    });
-
-    let wrapper = {
-      loader: loader,
-      cm: loader.require("sdk/context-menu"),
-      globalScope: loader.sandbox("sdk/context-menu"),
-      unload: function () {
-        loader.unload();
-        let idx = self.loaders.indexOf(wrapper);
-        if (idx < 0)
-          throw new Error("Test error: tried to unload nonexistent loader");
-        self.loaders.splice(idx, 1);
-      }
-    };
-    this.loaders.push(wrapper);
-    return wrapper;
-  },
-
-  // As above but the loader has private-browsing support enabled.
-  newPrivateLoader: function() {
-    let base = require("@loader/options");
-
-    // Clone current loader's options adding the private-browsing permission
-    let options = merge({}, base, {
-      metadata: merge({}, base.metadata || {}, {
-        permissions: merge({}, base.metadata.permissions || {}, {
-          'private-browsing': true
-        })
-      })
-    });
-
-    const self = this;
-    let loader = Loader(module, null, options);
-    let wrapper = {
-      loader: loader,
-      cm: loader.require("sdk/context-menu"),
-      globalScope: loader.sandbox("sdk/context-menu"),
-      unload: function () {
-        loader.unload();
-        let idx = self.loaders.indexOf(wrapper);
-        if (idx < 0)
-          throw new Error("Test error: tried to unload nonexistent loader");
-        self.loaders.splice(idx, 1);
-      }
-    };
-    this.loaders.push(wrapper);
-    return wrapper;
-  },
-
-  // Returns true if the count crosses the overflow threshold.
-  shouldOverflow: function (count) {
-    return count >
-           (this.loaders.length ?
-            this.loaders[0].loader.require("sdk/preferences/service").
-              get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT) :
-            OVERFLOW_THRESH_DEFAULT);
-  },
-
-  // Loads scripts necessary in the content process
-  loadFrameScript: function(browser = this.browserWindow.gBrowser.selectedBrowser) {
-    function frame_script() {
-      let { interfaces: Ci } = Components;
-      addMessageListener('test:contextmenu', ({ data: { selectors } }) => {
-        let targetNode = null;
-        let contentWin = content;
-        if (selectors) {
-          while (selectors.length) {
-            targetNode = contentWin.document.querySelector(selectors.shift());
-            if (selectors.length)
-              contentWin = targetNode.contentWindow;
-          }
-        }
-
-        let rect = targetNode ?
-                   targetNode.getBoundingClientRect() :
-                   { left: 0, top: 0, width: 0, height: 0 };
-        contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindowUtils)
-                  .sendMouseEvent('contextmenu',
-                  rect.left + (rect.width / 2),
-                  rect.top + (rect.height / 2),
-                  2, 1, 0);
-      });
-
-      addMessageListener('test:ping', () => {
-        sendAsyncMessage('test:pong');
-      });
-
-      addMessageListener('test:select', ({ data: { selector, start, end } }) => {
-        let element = content.document.querySelector(selector);
-        element.focus();
-        if (end === null)
-          end = element.value.length;
-        element.setSelectionRange(start, end);
-      });
-    }
-
-    let messageManager = browser.messageManager;
-    messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", true);
-  },
-
-  selectRange: function(selector, start, end) {
-    let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager;
-    messageManager.sendAsyncMessage('test:select', { selector, start, end });
-  },
-
-  // Opens the context menu on the current page.  If selectors is null, the
-  // menu is opened in the top-left corner.  onShowncallback is passed the
-  // popup. selectors is an array of selectors. Starting from the main document
-  // each selector points to an iframe, the last selector gives the target node.
-  // In the simple case of a single selector just that string can be passed
-  // instead of an array
-  showMenu: function(selectors, onshownCallback) {
-    let { promise, resolve } = defer();
-
-    if (selectors && !Array.isArray(selectors))
-      selectors = [selectors];
-
-    let sendEvent = () => {
-      let menu = this.browserWindow.document.getElementById("contentAreaContextMenu");
-      this.delayedEventListener(menu, "popupshowing",
-        function (e) {
-          let popup = e.target;
-          if (onshownCallback) {
-            onshownCallback.call(this, popup);
-          }
-          resolve(popup);
-        }, false);
-
-      let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager;
-      messageManager.sendAsyncMessage('test:contextmenu', { selectors });
-    }
-
-    // Bounces an asynchronous message through the browser message manager.
-    // This ensures that any pending messages have been delivered to the frame
-    // scripts and so the remote proxies have been updated
-    let flushMessages = () => {
-      let listener = () => {
-        messageManager.removeMessageListener('test:pong', listener);
-        sendEvent();
-      };
-
-      let messageManager = this.browserWindow.gBrowser.selectedBrowser.messageManager;
-      messageManager.addMessageListener('test:pong', listener);
-      messageManager.sendAsyncMessage('test:ping');
-    }
-
-    // If a new tab or window has not yet been opened, open a new tab now.  For
-    // some reason using the tab already opened when the test starts causes
-    // leaks.  See bug 566351 for details.
-    if (!selectors && !this.oldSelectedTab && !this.oldBrowserWindow) {
-      this.oldSelectedTab = this.tabBrowser.selectedTab;
-      this.tab = this.tabBrowser.addTab("about:blank");
-      let browser = this.tabBrowser.getBrowserForTab(this.tab);
-
-      this.delayedEventListener(browser, "load", function () {
-        this.tabBrowser.selectedTab = this.tab;
-        this.loadFrameScript();
-        flushMessages();
-      }, true);
-    }
-    else {
-      flushMessages();
-    }
-
-    return promise;
-  },
-
-  hideMenu: function(onhiddenCallback) {
-    this.delayedEventListener(this.browserWindow, "popuphidden", onhiddenCallback);
-
-    this.contextMenuPopup.hidePopup();
-  },
-
-  // Opens a new browser window.  The window will be closed automatically when
-  // done() is called.
-  withNewWindow: function (onloadCallback, makePrivate = false) {
-    let win = this.browserWindow.OpenBrowserWindow({ private: makePrivate });
-    observers.once("browser-delayed-startup-finished", () => {
-      // Open a new tab so we can make sure it is remote and loaded
-      win.gBrowser.selectedTab = win.gBrowser.addTab();
-      this.loadFrameScript();
-      this.delayedEventListener(win.gBrowser.selectedBrowser, "load", onloadCallback, true);
-    });
-    this.oldBrowserWindow = this.browserWindow;
-    this.browserWindow = win;
-  },
-
-  // Opens a new private browser window.  The window will be closed
-  // automatically when done() is called.
-  withNewPrivateWindow: function (onloadCallback) {
-    this.withNewWindow(onloadCallback, true);
-  },
-
-  // Opens a new tab with our test page in the current window.  The tab will
-  // be closed automatically when done() is called.
-  withTestDoc: function (onloadCallback) {
-    this.oldSelectedTab = this.tabBrowser.selectedTab;
-    this.tab = this.tabBrowser.addTab(TEST_DOC_URL);
-    let browser = this.tabBrowser.getBrowserForTab(this.tab);
-
-    this.delayedEventListener(browser, "load", function () {
-      this.tabBrowser.selectedTab = this.tab;
-      this.loadFrameScript();
-      onloadCallback.call(this, browser.contentWindow, browser.contentDocument);
-    }, true, function(evt) {
-      return evt.target.location == TEST_DOC_URL;
-    });
-  }
-};
-exports.TestHelper = TestHelper;
deleted file mode 100644
--- a/addon-sdk/source/test/context-menu/util.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cc, Ci } = require("chrome");
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-const { open: openWindow, close: closeWindow } = require("sdk/window/helpers");
-const tabUtils = require("sdk/tabs/utils");
-const { map, filter, object, reduce, keys, symbols,
-        pairs, values, each, some, isEvery, count } = require("sdk/util/sequence");
-const { when } = require("sdk/dom/events");
-
-const { Task } = require("resource://gre/modules/Task.jsm");
-
-var observerService = Cc["@mozilla.org/observer-service;1"]
-                      .getService(Ci.nsIObserverService);
-
-const framescriptURI = require.resolve("./framescript");
-
-const _target = ({target}) => target;
-
-exports.openWindow = openWindow;
-exports.closeWindow = closeWindow;
-
-const getActiveTab = (window=getMostRecentBrowserWindow()) =>
-  tabUtils.getActiveTab(window)
-
-const openTab = (url, window=getMostRecentBrowserWindow()) => {
-  const tab = tabUtils.openTab(window, url);
-  const browser = tabUtils.getBrowserForTab(tab);
-  browser.messageManager.loadFrameScript(framescriptURI, false);
-
-  return when(browser, "load", true).then(_ => tab);
-};
-exports.openTab = openTab;
-
-const openContextMenu = (selector, tab=getActiveTab()) => {
-  const browser = tabUtils.getBrowserForTab(tab);
-  browser.
-    messageManager.
-    sendAsyncMessage("sdk/test/context-menu/open",
-                     {target: selector});
-
-  return when(tab.ownerGlobal, "popupshown").
-          then(_target);
-};
-exports.openContextMenu = openContextMenu;
-
-const closeContextMenu = (menu) => {
-  const result = when(menu.ownerGlobal, "popuphidden").
-                  then(_target);
-
-  menu.hidePopup();
-  return result;
-};
-exports.closeContextMenu = closeContextMenu;
-
-const closeTab = (tab) => {
-  const result = when(tab, "TabClose").then(_ => tab);
-  tabUtils.closeTab(tab);
-
-  return result;
-};
-exports.closeTab = closeTab;
-
-const select = (target, tab=getActiveTab()) =>
-  new Promise(resolve => {
-    const {messageManager} = tabUtils.getBrowserForTab(tab);
-    messageManager.
-      sendAsyncMessage("sdk/test/context-menu/select",
-                       target);
-
-    messageManager.addMessageListener("sdk/test/context-menu/selected", {
-      receiveMessage({name}) {
-        messageManager.removeMessageListener(name, this);
-        resolve();
-      }
-    });
-  });
-exports.select = select;
-
-const attributeBlocklist = new Set(["data-component-path"]);
-const attributeRenameTable = Object.assign(Object.create(null), {
-  class: "className"
-});
-const readAttributes = node =>
-  object(...map(({name, value}) => [attributeRenameTable[name] || name, value],
-                filter(({name}) => !attributeBlocklist.has(name),
-                       node.attributes)));
-exports.readAttributes = readAttributes;
-
-const readNode = node =>
-  Object.assign(readAttributes(node),
-                {tagName: node.tagName, namespaceURI: node.namespaceURI},
-                node.children.length ?
-                  {children: [...map(readNode, node.children)]} :
-                  {});
-exports.readNode = readNode;
-
-const captureContextMenu = (target=":root", options={}) => Task.spawn(function*() {
-  const window = options.window || getMostRecentBrowserWindow();
-  const tab = options.tab || tabUtils.getActiveTab(window);
-
-  const menu = yield openContextMenu(target, tab);
-  const tree = readNode(menu.querySelector(".sdk-context-menu-extension"));
-  yield closeContextMenu(menu);
-  return tree;
-});
-exports.captureContextMenu = captureContextMenu;
-
-const withTab = (test, uri="about:blank") => function*(assert) {
-  const tab = yield openTab(uri);
-  try {
-    yield* test(assert, tab);
-  }
-  finally {
-    yield closeTab(tab);
-  }
-};
-exports.withTab = withTab;
-
-const withWindow = () => function*(assert) {
-  const window = yield openWindow();
-  try {
-    yield* test(assert, window);
-  }
-  finally {
-    yield closeWindow(window);
-  }
-};
-exports.withWindow = withWindow;
-
-const withItems = (items, body) => function*() {
-  try {
-    yield* body(items);
-  } finally {
-      Object.keys(items).forEach(key => items[key].destroy());
-  }
-}();
-exports.withItems = withItems;
deleted file mode 100644
--- a/addon-sdk/source/test/event/helpers.js
+++ /dev/null
@@ -1,111 +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 { on, once, off, emit, count } = require("sdk/event/core");
-
-const { setImmediate, setTimeout } = require("sdk/timers");
-const { defer } = require("sdk/core/promise");
-
-/**
- * Utility function that returns a promise once the specified event's `type`
- * is emitted on the given `target`, or the delay specified is passed.
- *
- * @param {Object|Number} [target]
- *    The delay to wait, or the object that receives the event.
- *    If not given, the function returns a promise that will be resolved
- *    as soon as possible.
- * @param {String} [type]
- *    A string representing the event type to waiting for.
- * @param {Boolean} [capture]
- *    If `true`, `capture` indicates that the user wishes to initiate capture.
- *
- * @returns {Promise}
- *    A promise resolved once the delay given is passed, or the object
- *    receives the event specified
- */
-const wait = function(target, type, capture) {
-  let { promise, resolve, reject } = defer();
-
-  if (!arguments.length) {
-    setImmediate(resolve);
-  }
-  else if (typeof(target) === "number") {
-    setTimeout(resolve, target);
-  }
-  else if (typeof(target.once) === "function") {
-    target.once(type, resolve);
-  }
-  else if (typeof(target.addEventListener) === "function") {
-    target.addEventListener(type, function(...args) {
-      resolve(...args);
-    }, {capture, once: true});
-  }
-  else if (typeof(target) === "object" && target !== null) {
-    once(target, type, resolve);
-  }
-  else {
-    reject('Invalid target given.');
-  }
-
-  return promise;
-};
-exports.wait = wait;
-
-function scenario(setup) {
-  return function(unit) {
-    return function(assert) {
-      let actual = [];
-      let input = {};
-      unit(input, function(output, events, expected, message) {
-        let result = setup(output, expected, actual);
-
-        events.forEach(event => emit(input, "data", event));
-
-        assert.deepEqual(actual, result, message);
-      });
-    }
-  }
-}
-
-exports.emits = scenario(function(output, expected, actual) {
-  on(output, "data", function(data) {
-    return actual.push(this, data);
-  });
-
-  return expected.reduce(($$, $) => $$.concat(output, $), []);
-});
-
-exports.registerOnce = scenario(function(output, expected, actual) {
-  function listener(data) {
-    return actual.push(data);
-  }
-  on(output, "data", listener);
-  on(output, "data", listener);
-  on(output, "data", listener);
-
-  return expected;
-});
-
-exports.ignoreNew = scenario(function(output, expected, actual) {
-  on(output, "data", function(data) {
-    actual.push(data + "#1");
-    on(output, "data", function(data) {
-      actual.push(data + "#2");
-    });
-  });
-
-  return expected.map($ => $ + "#1");
-});
-
-exports.FIFO = scenario(function(target, expected, actual) {
-  on(target, "data", $ => actual.push($ + "#1"));
-  on(target, "data", $ => actual.push($ + "#2"));
-  on(target, "data", $ => actual.push($ + "#3"));
-
-  return expected.reduce(function(result, value) {
-    return result.concat(value + "#1", value + "#2", value + "#3");
-  }, []);
-});
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures.js
+++ /dev/null
@@ -1,41 +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 { uri } = module;
-const prefix = uri.substr(0, uri.lastIndexOf("/") + 1) + "fixtures/";
-
-exports.url = (path="") => path && path.includes(":")
-  ? path
-  : prefix + path.replace(/^\.\//, "");
-
-const base64jpeg = "data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F" +
-                  "2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCg" +
-                  "sOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD%2F2wBDAQMDAwQDBAgEBAgQCw" +
-                  "kLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ" +
-                  "EBAQEBAQEBD%2FwAARCAAgACADAREAAhEBAxEB%2F8QAHwAAAQUBAQEBAQ" +
-                  "EAAAAAAAAAAAECAwQFBgcICQoL%2F8QAtRAAAgEDAwIEAwUFBAQAAAF9AQ" +
-                  "IDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRol" +
-                  "JicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eX" +
-                  "qDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJ" +
-                  "ytLT1NXW19jZ2uHi4%2BTl5ufo6erx8vP09fb3%2BPn6%2F8QAHwEAAwEB" +
-                  "AQEBAQEBAQAAAAAAAAECAwQFBgcICQoL%2F8QAtREAAgECBAQDBAcFBAQA" +
-                  "AQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNO" +
-                  "El8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0" +
-                  "dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6ws" +
-                  "PExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3%2BPn6%2F9oADAMB" +
-                  "AAIRAxEAPwD5Kr8kP9CwoA5f4m%2F8iRqX%2FbH%2FANHJXr5F%2FwAjCn" +
-                  "8%2F%2FSWfnnir%2FwAkji%2F%2B4f8A6dgeD1%2BiH8bn1BX5If6FmFqW" +
-                  "pXtveyQwzbUXGBtB7D2r9l4U4UyjMsoo4rFUeacua75pLaUktFJLZH5NxN" +
-                  "xNmmX5pVw2Gq8sI8tlyxe8U3q03uzD8S3dxqOi3NneSeZDJs3LgDOHBHI5" +
-                  "6gV%2BkcG%2BH%2FDmJzuhSq4e8XzfbqfyS%2FvH5rx1xTm2MyDEUa1W8X" +
-                  "yXXLFbTi%2BkThv7B0r%2FAJ9f%2FH2%2Fxr90%2FwCIVcI%2F9An%2FAJ" +
-                  "Uq%2FwDyZ%2FO%2F16v%2FADfgv8j0r%2FhZvgj%2FAKDf%2FktN%2FwDE" +
-                  "V%2Fnr%2FYWYf8%2B%2Fxj%2Fmf3R%2FxFXhH%2FoL%2FwDKdX%2F5Azrv" +
-                  "xLouo3D3lne%2BZDJja3luM4GDwRnqDX9LeH%2FBud4nhzD1aVC8Xz%2Fa" +
-                  "h%2Fz8l%2FePx%2FinjrIMZm1WtRxF4vls%2BSa2jFdYlDUdRsp7OSKKbc" +
-                  "7YwNpHce1fqfCvCub5bm9HFYqjywjzXfNF7xklopN7s%2BC4l4lyvMMrq4" +
-                  "fD1bzfLZcsltJPqktkYlfsZ%2BUnBV%2FnufVnXaD%2FAMgqD%2FgX%2Fo" +
-                  "Rr%2BxvCr%2FkkcJ%2F3E%2F8ATsz5%2FHfx5fL8kX6%2FQjkCgD%2F%2F" +
-                  "2Q%3D%3D";
-exports.base64jpeg = base64jpeg;
deleted file mode 100644
index 516c1fc3c6cb17b8fa9624af09dedd6e7c4413fa..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon-sdk/data/border-style.css
+++ /dev/null
@@ -1,4 +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/. */
-div { border-style: dashed; }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon-sdk/data/test-contentScriptFile.js
+++ /dev/null
@@ -1,5 +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/. */
-
-self.postMessage("msg from contentScriptFile");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.html
+++ /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/. -->
-
-<html>
-<head>
-    <meta charset="UTF-8">
-    <title>Page Worker test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon-sdk/data/test-page-worker.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/. */
-
-
-// get title directly
-self.postMessage(["equal", document.title, "Page Worker test",
-            "Correct page title accessed directly"]);
-
-// get <p> directly
-var p = document.getElementById("paragraph");
-self.postMessage(["ok", !!p, "<p> can be accessed directly"]);
-self.postMessage(["equal", p.firstChild.nodeValue,
-            "Lorem ipsum dolor sit amet.",
-            "Correct text node expected"]);
-
-// Modify page
-var div = document.createElement("div");
-div.setAttribute("id", "block");
-div.appendChild(document.createTextNode("Test text created"));
-document.body.appendChild(div);
-
-// Check back the modification
-div = document.getElementById("block");
-self.postMessage(["ok", !!div, "<div> can be accessed directly"]);
-self.postMessage(["equal", div.firstChild.nodeValue,
-            "Test text created", "Correct text node expected"]);
-self.postMessage(["done"]);
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon-sdk/data/test.html
+++ /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/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>foo</title>
-  </head>
-  <body>
-    <p>bar</p>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon/bootstrap.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { utils: Cu } = Components;
-const {require} = Cu.import(`${ROOT}/toolkit/require.js`, {});
-const {Bootstrap} = require(`${ROOT}/sdk/addon/bootstrap.js`);
-var {startup, shutdown, install, uninstall} = new Bootstrap();
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon/index.js
+++ /dev/null
@@ -1,4 +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";
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/addon/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "id": "addon@jetpack",
-  "name": "addon",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap-addon/META-INF/manifest.mf
+++ /dev/null
@@ -1,17 +0,0 @@
-Manifest-Version: 1.0
-
-Name: install.rdf
-Digest-Algorithms: MD5 SHA1
-MD5-Digest: N643P4YjKKlwZUqrfLi4ow==
-SHA1-Digest: XK/2qoOrnuYo8xNYeLvB8DlUIik=
-
-Name: bootstrap.js
-Digest-Algorithms: MD5 SHA1
-MD5-Digest: XH+mMa/H9aj3hm/ZtVKviw==
-SHA1-Digest: LMmd1aTash/onjS1eAYIshgrdnM=
-
-Name: options.xul
-Digest-Algorithms: MD5 SHA1
-MD5-Digest: XeELNGdttv8Lq66lT8ykbQ==
-SHA1-Digest: 4KO6/RBoe10rYOGS+gFSHuuWi4Y=
-
deleted file mode 100644
index 6b1c3a9ce67eae755547ea9ae0e557c6b86f6ffa..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap-addon/META-INF/mozilla.sf
+++ /dev/null
@@ -1,4 +0,0 @@
-Signature-Version: 1.0
-MD5-Digest-Manifest: cnqbpqBEVoHgJi/ocCsKKA==
-SHA1-Digest-Manifest: eDmvBAkodeNbk/0ujttYgF8KDgI=
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap-addon/bootstrap.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';
-
-function install(data, reason) {}
-function uninstall(data, reason) {}
-
-function startup(data, reasonCode) {};
-function shutdown(data, reasonCode) {};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap-addon/install.rdf
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.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/. -->
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>test-bootstrap-addon@mozilla.com</em:id>
-    <em:name>Test Bootstrap Add-on</em:name>
-    <em:creator>Erik Vold</em:creator>
-    <em:optionsType>2</em:optionsType>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-    <em:unpack>false</em:unpack>
-
-    <!-- Firefox -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>26.0</em:minVersion>
-        <em:maxVersion>*</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-  </Description>
-</RDF>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap-addon/options.xul
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE mydialog SYSTEM "chrome://myaddon/locale/mydialog.dtd">
-<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"></vbox>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/bootstrap/utils.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu, Cc, Ci } = require("chrome");
-const { evaluate } = require("sdk/loader/sandbox");
-
-const ROOT = require.resolve("sdk/base64").replace("/sdk/base64.js", "");
-
-// Note: much of this test code is from
-// http://dxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm
-const BOOTSTRAP_REASONS = {
-  APP_STARTUP     : 1,
-  APP_SHUTDOWN    : 2,
-  ADDON_ENABLE    : 3,
-  ADDON_DISABLE   : 4,
-  ADDON_INSTALL   : 5,
-  ADDON_UNINSTALL : 6,
-  ADDON_UPGRADE   : 7,
-  ADDON_DOWNGRADE : 8
-};
-
-function createBootstrapScope(options) {
-  let { uri, id: aId } = options;
-  let principal = Cc["@mozilla.org/systemprincipal;1"].
-                  createInstance(Ci.nsIPrincipal);
-
-  let bootstrapScope = new Cu.Sandbox(principal, {
-    sandboxName: uri,
-    wantGlobalProperties: ["indexedDB"],
-    addonId: aId,
-    metadata: { addonID: aId, URI: uri }
-  });
-
-  // Copy the reason values from the global object into the bootstrap scope.
-  for (let name in BOOTSTRAP_REASONS)
-    bootstrapScope[name] = BOOTSTRAP_REASONS[name];
-
-  return bootstrapScope;
-}
-exports.create = createBootstrapScope;
-
-function evaluateBootstrap(options) {
-  let { uri, scope } = options;
-
-  evaluate(scope,
-    `${"Components"}.classes['@mozilla.org/moz/jssubscript-loader;1']
-                    .createInstance(${"Components"}.interfaces.mozIJSSubScriptLoader)
-                    .loadSubScript("${uri}");`, "ECMAv5");
-}
-exports.evaluate = evaluateBootstrap;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/border-style.css
+++ /dev/null
@@ -1,4 +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/. */
-div { border-style: dashed; }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/child-process-scripts.js
+++ /dev/null
@@ -1,81 +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 { platform, pathFor } = require('sdk/system');
-const { defer } = require('sdk/core/promise');
-const { emit } = require('sdk/event/core');
-const { join } = require('sdk/fs/path');
-const { writeFile, unlinkSync, existsSync } = require('sdk/io/fs');
-const PROFILE_DIR= pathFor('ProfD');
-const isWindows = platform.toLowerCase().indexOf('win') === 0;
-const isOSX = platform.toLowerCase().indexOf('darwin') === 0;
-
-var scripts = {
-  'args.sh': 'echo $1 $2 $3 $4',
-  'args.bat': 'echo %1 %2 %3 %4',
-  'check-env.sh': 'echo $CHILD_PROCESS_ENV_TEST',
-  'check-env.bat': 'echo %CHILD_PROCESS_ENV_TEST%',
-  'check-pwd.sh': 'echo $PWD',
-  'check-pwd.bat': 'cd',
-  'large-err.sh': 'for n in `seq 0 $1` ; do echo "E" 1>&2; done',
-  'large-err-mac.sh': 'for ((i=0; i<$1; i=i+1)); do echo "E" 1>&2; done',
-  'large-err.bat': 'FOR /l %%i in (0,1,%1) DO echo "E" 1>&2',
-  'large-out.sh': 'for n in `seq 0 $1` ; do echo "O"; done',
-  'large-out-mac.sh': 'for ((i=0; i<$1; i=i+1)); do echo "O"; done',
-  'large-out.bat': 'FOR /l %%i in (0,1,%1) DO echo "O"',
-  'wait.sh': 'sleep 2',
-  // Use `ping` to an invalid IP address because `timeout` isn't
-  // on all environments? http://stackoverflow.com/a/1672349/1785755
-  'wait.bat': 'ping 1.1.1.1 -n 1 -w 2000 > nul'
-};
-
-Object.keys(scripts).forEach(filename => {
-  if (/\.sh$/.test(filename))
-    scripts[filename] = '#!/bin/sh\n' + scripts[filename];
-  else if (/\.bat$/.test(filename))
-    scripts[filename] = '@echo off\n' + scripts[filename];
-});
-
-function getScript (name) {
-  // Use specific OSX script if exists
-  if (isOSX && scripts[name + '-mac.sh'])
-    name = name + '-mac';
-  let fileName = name + (isWindows ? '.bat' : '.sh');
-  return createFile(fileName, scripts[fileName]);
-}
-exports.getScript = getScript;
-
-function createFile (name, data) {
-  let { promise, resolve, reject } = defer();
-  let fileName = join(PROFILE_DIR, name);
-  writeFile(fileName, data, function (err) {
-    if (err) reject();
-    else {
-      makeExecutable(fileName);
-      resolve(fileName);
-    }
-  });
-  return promise;
-}
-
-// TODO Use fs.chmod once implemented, bug 914606
-function makeExecutable (name) {
-  let { CC } = require('chrome');
-  let nsIFile = CC('@mozilla.org/file/local;1', 'nsIFile', 'initWithPath');
-  let file = nsIFile(name);
-  file.permissions = 0o777;
-}
-
-function deleteFile (name) {
-  let file = join(PROFILE_DIR, name);
-  if (existsSync(file))
-    unlinkSync(file);
-}
-
-function cleanUp () {
-  Object.keys(scripts).forEach(deleteFile);
-}
-exports.cleanUp = cleanUp;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/addEventListener.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-postMessage('Hello');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/jsctypes.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-postMessage(typeof ctypes.open);
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/onerror.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-throw new Error('ok');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/onmessage.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-onmessage = function (event) {
-  postMessage(event.data);
-};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/setTimeout.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-setTimeout(function () {
-  postMessage('ok');
-}, 0);
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/chrome-worker/xhr.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/. */
-'use strict';
-
-var xhr = new XMLHttpRequest();
-xhr.open("GET", "data:text/plain,ok", true);
-xhr.onload = function () {
-  postMessage(xhr.responseText);
-};
-xhr.send(null);
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/create_xpi.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from os.path import abspath
-
-# TODO replace this script with a direct Python action invocation
-from mozbuild.action.zip import main as create_zip
-
-def main(output, input_dir):
-    output.close()
-
-    return create_zip(['-C', input_dir, abspath(output.name), '**'])
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/es5.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-exports.frozen = Object.freeze({});
-exports.sealed = Object.seal({});
-exports.inextensible = Object.preventExtensions({});
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/include-file.css
+++ /dev/null
@@ -1,4 +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/. */
-div { border: 10px solid black; }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>Add-on Page</title>
-  </head>
-  <body>
-    <p>This is an add-on page test!</p>
-    <script>
-    function getTestURL() {
-      return window.document.documentURI + "";
-    }
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/jsm-package/Test.jsm
+++ /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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["Test"];
-
-this.Test = {
-  square: function (x) { return x * x; }
-};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/jsm-package/index.js
+++ /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/. */
-
-'use strict';
-
-var { Test } = require('./Test.jsm');
-var { Test: Test2 } = require('./Test.jsm');
-exports.localJSM = Test.square(16) === 256;
-exports.localJSMCached = Test === Test2;
-
-(function () {
-var { Promise } = require('resource://gre/modules/Promise.jsm');
-var { defer } = require('resource://gre/modules/Promise.jsm').Promise;
-
-exports.isCachedAbsolute = Promise.defer === defer;
-
-exports.isLoadedAbsolute = function (val) {
-  let { promise, resolve } = Promise.defer();
-  resolve(val);
-  return promise;
-};
-})();
-
-(function () {
-var { Promise } = require('modules/Promise.jsm');
-var { defer } = require('modules/Promise.jsm').Promise;
-exports.isCachedPath = Promise.defer === defer;
-
-exports.isLoadedPath = function (val) {
-  let { promise, resolve } = Promise.defer();
-  resolve(val);
-  return promise;
-};
-})();
-
-(function () {
-var { defer } = require('resource://gre/modules/commonjs/sdk/core/promise.js');
-var { defer: defer2 } = require('resource://gre/modules/commonjs/sdk/core/promise.js');
-exports.isCachedJSAbsolute = defer === defer2;
-exports.isLoadedJSAbsolute = function (val) {
-  let { promise, resolve } = defer();
-  resolve(val);
-  return promise;
-};
-})();
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/jsm-package/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "name": "jsm-package"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/cycles/a.js
+++ /dev/null
@@ -1,7 +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.b = require('b');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/cycles/b.js
+++ /dev/null
@@ -1,7 +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.a = require('a');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/cycles/c.js
+++ /dev/null
@@ -1,7 +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.main = require('main');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/cycles/main.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-var a = require('a');
-var b = require('b');
-var c = require('c');
-
-exports.a = a;
-exports.b = b;
-exports.c = c;
-exports.main = exports;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/errors/boomer.js
+++ /dev/null
@@ -1,7 +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";
-
-throw Error("opening input stream (invalid filename?)");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/errors/main.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-var error = require('./boomer');
-
-exports.main = exports;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/exceptions/boomer.js
+++ /dev/null
@@ -1,9 +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.boom = function() {
-  throw Error("Boom!");
-};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/exceptions/main.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/. */
-
-'use strict';
-
-var boomer = require('./boomer');
-
-boomer.boom();
-
-exports.main = exports;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/globals/main.js
+++ /dev/null
@@ -1,7 +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.console = console;
-exports.globalFoo = (typeof globalFoo !== "undefined") ? globalFoo : null;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/invalid.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  invalidjson
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/manifest.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name": "Jetpack Loader Test",
-  "version": "1.0.1",
-  "dependencies": {
-    "async": "*",
-    "underscore": "*"
-  },
-  "contributors": [
-    "ash nazg durbatulûk",
-    "ash nazg gimbatul",
-    "ash nazg thrakatulûk",
-    "agh burzum-ishi krimpatul"
-  ]
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/mutation.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{ "value": 1 }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-module.exports = {
-  "filename": "nodotjson.json.js",
-  "data": {}
-};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/test.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "filename": "test.json"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/json/test.json.js
+++ /dev/null
@@ -1,7 +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/. */
-
-module.exports = {
-  "filename": "test.json.js"
-};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/lazy/main.js
+++ /dev/null
@@ -1,9 +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.useFoo= function () {
-  return require('foo');
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/missing-twice/file.json
+++ /dev/null
@@ -1,1 +0,0 @@
-an invalid json file
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/missing-twice/main.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-try {
-  require('./not-found');
-}
-catch (e1) {
-  exports.firstError = e1;
-  // It should throw again and not be cached
-  try {
-    require('./not-found');
-  }
-  catch (e2) {
-    exports.secondError = e2;
-  }
-}
-
-try {
-  require('./file.json');
-}
-catch (e) {
-  exports.invalidJSON1 = e;
-  try {
-    require('./file.json');
-  }
-  catch (e) {
-    exports.invalidJSON2 = e;
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/missing/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';
-
-var a = require('./not-found');
-
-exports.a = a;
-exports.main = exports;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/self/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var self = require("sdk/self");
-exports.self = self;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/syntax-error/error.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/. */
-
-'use strict';
-
-module.metadata = {
-  "status": "experimental"
-};
-
-exports.b = @ require('b');
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/syntax-error/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';
-
-var a = require('./error');
-
-exports.a = a;
-exports.main = exports;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/unsupported/fennec.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/. */
-
-module.metadata = {
-  "engines": {
-    "Fennec": "*"
-  }
-};
-module.exports = {};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/loader/unsupported/firefox.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/. */
-
-module.metadata = {
-  "engines": {
-    "Firefox": "*"
-  }
-};
-module.exports = {};
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/mofo_logo.SVG
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
-<svg version="1.1" id="svg2997" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="-0.5 -0.5 200 200" overflow="visible" enable-background="new -0.5 -0.5 200 200" xml:space="preserve">
-<path id="path85" fill="#FFFFFF" d="M-2559.936,6359.65c19.127,26.489,46.371,47.744,80.988,44.707  C-2479.339,6371.648-2523.898,6352.641-2559.936,6359.65z"/>
-<path id="path93" fill="#FFFFFF" d="M-2634.014,6073.506c4.082-7.232,2.571-17.81,3.831-26.684  c-9.019,4.635-15.506,14.72-24.551,18.641C-2652.134,6070.818-2640.447,6070.829-2634.014,6073.506z"/>
-<path id="path95" fill="#FFFFFF" d="M-2687.179,6018.109l-18.654,18.212c4.158,3.301,9.676,8.132,17.11,6.36L-2687.179,6018.109z"/>
-<path id="path97" fill="#FFFFFF" d="M-2731.117,5998.391c-4.356-0.363-14.41,20.156-18.785,19.857l14.762,8.728  C-2730.055,6027.281-2732.816,6001.961-2731.117,5998.391L-2731.117,5998.391z"/>
-<path id="path99" fill="#FFFFFF" d="M-2776.505,5989.09l4.736-11.668c-10.245,0.813-15.511,20.68-21.719,26.244  C-2776.37,6007.109-2775.727,6011.81-2776.505,5989.09z"/>
-<path id="path101" fill="#FFFFFF" d="M-2825.16,5962.186l-18.405,31.539l17.091,3.962L-2825.16,5962.186L-2825.16,5962.186z"/>
-<path id="path103" fill="#FFFFFF" d="M-2872.173,5967.636l-21.059,16.139C-2872.035,5992.07-2870.821,5995.181-2872.173,5967.636z"/>
-<path id="path105" fill="#FFFFFF" d="M-2922.987,5980.398c-3.084-9.172-0.18-20.226,0.396-29.914  c-4.952,9.422-16.338,16.166-17.745,27.299C-2935.489,5981.802-2928.796,5980.021-2922.987,5980.398L-2922.987,5980.398z"/>
-<g>
-	<path id="path9" d="M70.165,21.946C62.09,27.292,49.432,38.35,43.382,44.795c1.491,0.208,3.068-0.957,4.751-1.179l11.635-3.192   c-4.833,4.151-15.001,11.47-17.946,17.234c3.632-1.309,11.254-5.699,15.043-6.059c-3.309,3.038-10.214,8.801-12.378,12.469   c0.261,0.124,0.08,0.445,0.12,0.669c2.846-1.635,9.763-5.91,12.9-6.199c-3.229,3.484-9.169,10.193-10.47,14.688   c2.804-1.913,9.856-5.792,12.944-6.969c-0.703,1.773-2.262,3.09-3.276,4.864c-1.399,2.453-4.711,5.246-4.834,8.161   c2.46-2.375,5.51-4.474,8.571-6.148c-1.365,2.947-3.876,5.384-4.561,8.892c2.007-2.02,5.813-3.071,8.399-4.005l-0.312,0.311   c-0.224,0.191-3.136,2.335-5.121,4.727c1.765-0.114,0.449-0.334,2.707,0.18l-0.043,0.114   c-0.154,13.494,25.501,18.427,41.224,17.743c3.314-6.419,1.525-16.789,10.088-21.247c5.764-3.067,6.416-4.742,13.068-3.491   c3.596,0.674,11.461,3.392,15.227,2.534c3.514-2.033,5.221-2.928,8.332-5.37c3.01-4.574-23.988-19.398-2.164-0.171   c5.236,1.121,6.588,0.954,8.139-1.376c0.693-1.88,2.348-6.877,3.859-10.133l0.107-1.76c-1.467-4.414-1.111-11.965-1.852-13.053   c-4.842-6.713-22.34-7.764-30.256-16.596c1.35-4.384-1.482-7.997-4.367-10.738c-4.332-3.187-10.313-1.722-14.925-0.399   c-5.255-1.099-10.117-2.986-15.233-4.48C81.381,13.626,70.165,21.946,70.165,21.946L70.165,21.946z"/>
-	<path id="path11" fill="#FF1A00" d="M103.517,25.68l-3.771,1.438c-0.453-0.901,0.676-1.757,1.126-2.599   c0.322-0.616,1.247-0.961,1.465-1.705c-4.877-0.786-9.486-3.178-14.688-2.354c-5.563,0.878-8.802,3.003-12.005,5.54   c-1.617,0.885-2.396,2.142-3.968,3.201c-1.92,1.729-2.755,5.176-3.233,5.833c2.785-1.206,5.587-1.026,7.479-1.663   c-7.115,4.447-8.358,13.134-6.39,20.38l-0.116,0.159c-2.391-1.429-3.083-4.065-3.745-6.371c-0.471,1.515-0.538,3.44-0.859,5.132   c-0.764-0.713-1.184-1.734-1.61-2.644c-0.799,7.668,2.938,13.913,7.521,19.966c3.068,4.058-2.923,6.744-1.512,11.838l7.206-0.404   c0.929-0.348,0.64-0.223,0.64-0.223c-1.806,3.613-11.365,6.352-13.201,8.417c0.513,0.425,8.917-2.164,11.991-2.687l-9.045,5.112   c0.899,0.277-0.028,3.311,1.946,3.023c12.508,3.713,26.597,8.866,28.792,3.488c1.831-3.419,4.541-9.21,4.122-12.49l1.941-2.949   c-2.59,0.643-5.199,1.691-7.202,3.823c-0.599-1.256,0.342-2.763,0.81-3.951c1.343-2.41,4.026-3.686,6.151-5.056l-4.464-1.976   c-2.25-3.864-6.523-7.047-6.639-11.586l1.057,0.36c4.069,4.621,9.854,8.371,15.647,8.639c-3.943-0.338,16.471-2.743,15.271-4.472   c2.17,3.121,8.729,4.432,13.52,6.071c2.201-0.792,3.162-0.566,4.816-2.057c-0.705-0.765-1.795-1.39-2.844-1.787   c-6.295-1.738-21.162-4.796-24.365-10.986c-0.604,2.637,1.838,4.812,4.566,7.061l-5.873-0.826   c-10.331-4.782-9.083-12.984-6.813-20.78l0.785,6.508l2.025,3.548c3.851-6.966,1.835-6.1-5.898-15.494l5.832,2.228   c2.663,2.142,7.04,5.845,10.921,8.417c10.453,6.845,15.625,11.381,28.891,12.311l4.092,0.908c2.896-7.59-2.719-14.597-1.021-3.989   c-2.166-2.631-4.283-5.066-3.842-6.439c-0.76-1.147,3.143-4.014,2.811-5.319c-3.83-3.894-20.389-5.984-29.381-14.907   c-0.264,1.492,4.158,5.354,4.924,6.683c-8.918,0.088-14.174-2.651-15.127-5.542c-0.195-0.481,0.047-2.623,0.998-3.313   c1.287-0.672,2.541-1.693,4.02-1.83c-2.316-1.891-5.25,0.643-7.302,1.788c-1.594,2.737,0.889,5.788,1.202,8.014   c-2.175-0.549-5.111-4.378-5.471-6.782c-3.306,0.362-6.34-0.065-8.881-1.974c2.243-0.492,4.56-1.331,6.906-1.755   c6.143-1.34,12.598-7.655,18.803-2.72l-2.889-3.672C113.848,21.654,108.812,24.342,103.517,25.68L103.517,25.68z"/>
-	<path id="path13" d="M83.254,28.459c-1.649,1.924-3.302,3.85-3.687,6.437l0.369,0.434c1.102-1.326,2.753-2.437,4.274-3.207   c0.002,2.726,1.76,5.399,4.11,6.713l0.395,0.028c-0.498-2.879-0.166-6.399,0.96-8.998c1.793-1.508,4.151-2.106,5.668-3.692   c-3.797-0.888-7.411-0.136-10.658,1.1L83.254,28.459L83.254,28.459z"/>
-	<path id="path15" fill="#FFFFFF" d="M121.379,36.471c-1.561-2.157-3.777-3.888-6.594-3.642   C114.814,35.491,118.443,37.043,121.379,36.471z"/>
-	<path id="path17" d="M98.854,36.815c-2.445,0.187-4.736,0.622-7.041,1.224c1.017,0.937,2.302,1.252,3.266,2.129   c-3.017,1.137-6.176,1.861-8.813,4.186l0.546,0.325c4.878-1.015,10.645-0.929,15.732,0.16l0.294-0.212l-2.948-5.361l4.533-0.981   c-2.405-2.249-5.156-4.46-8.322-5.422C96.585,34.171,97.917,35.479,98.854,36.815L98.854,36.815L98.854,36.815z"/>
-	<path id="path19" d="M116.564,42.189c2.406,0.445,5.064,0.503,7.357,0.074c-3.787-1.932-8.625-1.552-11.639-4.944   C112.852,39.099,114.086,41.968,116.564,42.189z"/>
-	<path id="path21" d="M80.567,55.828c0.943,3.023-2.23,6.707,0.312,9.485c2.165,2.522,4.81,4.614,7.354,6.464l-0.225-0.943   c-2.266-2.647-4.349-5.569-5.396-8.716c2.656,0.928,5.463,2.216,8.496,2.646c-3.416-5.104-9.678-9.984-7.319-16.97   c0.129-1.154,1.655-2.041,1.271-3.113C81.49,47.408,79.996,51.435,80.567,55.828L80.567,55.828z"/>
-	<path id="path23" fill="#FFFFFF" d="M127.412,59.77c-0.334,0.589-0.213,1.45-0.316,2.174c0.738-0.379,1.264-1.199,2-1.518   C128.883,59.988,127.934,59.986,127.412,59.77z"/>
-	<path id="path25" fill="#FFFFFF" d="M131.738,64.284l1.518-1.487c-0.336-0.267-0.785-0.661-1.395-0.518L131.738,64.284z"/>
-	<path id="path27" fill="#FFFFFF" d="M135.316,65.887c0.355,0.026,1.174-1.643,1.531-1.618l-1.203-0.711   C135.229,63.532,135.455,65.593,135.316,65.887z"/>
-	<path id="path29" fill="#FFFFFF" d="M139.012,66.644l-0.385,0.95c0.836-0.067,1.264-1.684,1.766-2.138   C139.002,65.177,138.949,64.793,139.012,66.644z"/>
-	<path id="path31" fill="#FFFFFF" d="M142.977,68.834l1.498-2.569l-1.395-0.32L142.977,68.834z"/>
-	<path id="path33" fill="#FFFFFF" d="M146.801,68.39l1.715-1.312C146.789,66.4,146.691,66.147,146.801,68.39z"/>
-	<path id="path35" fill="#FFFFFF" d="M150.938,67.35c0.254,0.748,0.02,1.647-0.031,2.436c0.404-0.766,1.332-1.313,1.445-2.221   C151.957,67.233,151.412,67.382,150.938,67.35L150.938,67.35z"/>
-	<path id="path37" d="M99.399,96.021c0.547,1.031,0.572,2.285,1.119,3.315c1.295-2.793,1.147-6.148-0.533-8.659   c-2.923-1.288-5.745-2.625-8.264-4.671C92.768,89.577,96.192,93.513,99.399,96.021L99.399,96.021z"/>
-	<path id="path71" d="M117.387,36.775c-0.953-0.248-1.51-1.317-1.25-2.393c0.268-1.079,1.252-1.75,2.207-1.502   c0.955,0.245,1.512,1.318,1.25,2.393C119.328,36.348,118.34,37.021,117.387,36.775z"/>
-	<path id="path75" d="M98.356,103.161l2.835-2.31c-2.758-1.791-7.426-5.004-9.95-7.387C93.224,97.589,93.284,102.152,98.356,103.161   z"/>
-	<path id="path2225" d="M57.859,84.722c11.552,15.175,27.262,21.19,46.412,19.542l-1.629-3.542   c-17.031,0.631-31.21-3.592-40.875-17.588L57.859,84.722z"/>
-	<path id="path2343" d="M10.063,170.061c2.903,0.027,5.809-0.039,8.712,0.014l-0.375,2.293l-5.096,0.02l-0.021,3.24h4.088v2.342   h-4.088v6.334h-3.22V170.061z"/>
-	<path id="path3315" d="M30.648,184.227c-2.242-0.338-3.854-1.586-4.75-3.68c-0.511-1.191-0.656-2.105-0.596-3.748   c0.061-1.664,0.254-2.451,0.886-3.605c0.814-1.488,1.881-2.344,3.555-2.846c0.877-0.266,1.065-0.291,2.274-0.293   c1.095-0.004,1.446,0.029,2.078,0.201c2.303,0.627,3.802,2.172,4.426,4.559c0.288,1.105,0.265,3.764-0.042,4.846   c-0.697,2.463-2.385,4.098-4.674,4.527C33.093,184.322,31.412,184.342,30.648,184.227z M32.991,181.963   c0.926-0.281,1.579-1.137,1.876-2.463c0.205-0.91,0.238-3.596,0.058-4.547c-0.335-1.762-1.328-2.654-2.957-2.656   c-1.589-0.002-2.456,0.793-2.912,2.67c-0.214,0.883-0.238,3.438-0.041,4.396c0.279,1.357,0.877,2.211,1.761,2.512   C31.381,182.082,32.455,182.123,32.991,181.963z"/>
-	<path id="flowRoot5258" d="M47.563,170.053h3.446v8.381c0,1.154,0.179,1.98,0.537,2.48c0.364,0.492,0.955,0.883,1.772,0.883   c0.823,0,1.414-0.391,1.772-0.883c0.364-0.5,0.546-1.326,0.546-2.48v-8.381h3.445v8.381c0,1.979-0.474,3.451-1.423,4.418   c-0.948,0.967-2.396,1.451-4.34,1.451c-1.939,0-3.383-0.484-4.331-1.451c-0.949-0.967-1.423-2.439-1.423-4.418V170.053"/>
-	<path id="path6262" d="M68.606,170.053l3.509,0.051c1.381,2.793,2.899,5.531,4.078,8.41l0.197,0.504l-0.049-1.01l-0.18-7.951h2.948   v14.246h-3.182l-0.363-0.758c-1.15-2.398-3.13-6.629-3.602-7.697c-0.302-0.684-0.524-1.137-0.495-1.012   c0.029,0.127,0.083,2.309,0.119,4.848l0.065,4.619h-3.047V170.053z"/>
-	<path id="text8203" d="M92.398,182.191l0.931,0.002c0.986,0,1.843-1.076,2.366-1.844c0.522-0.766,0.977-1.873,0.977-3.322   c0-1.424-0.431-2.496-0.905-3.213c-0.469-0.725-1.17-1.424-2.104-1.424l-1.265-0.002v9.805 M88.878,184.303v-14.25h4.209   c1.173,0,2.12,0.104,2.84,0.311c0.72,0.201,1.357,0.529,1.912,0.986c0.8,0.65,1.393,1.455,1.776,2.41   c0.39,0.949,0.584,2.084,0.584,3.404c0,1.223-0.2,2.328-0.6,3.314c-0.4,0.986-0.981,1.813-1.744,2.482   c-0.544,0.475-1.155,0.818-1.832,1.031c-0.678,0.207-1.558,0.311-2.641,0.311H88.878"/>
-	<path id="path9182" d="M106.307,184.277l5.092-14.225h3.457c1.617,4.746,3.281,9.477,4.885,14.225l-3.457,0.023l-1.084-3.391   l-4.433,0.002l-1.083,3.389C108.559,184.289,107.431,184.324,106.307,184.277z M113.051,173.643l-1.51,4.887h2.873   C113.82,176.934,113.57,175.254,113.051,173.643z"/>
-	<path id="path10154" d="M127.924,172.535h-3.867v-2.48c3.799,0,7.6-0.004,11.4,0c-0.002,0-0.529,2.479-0.529,2.479l-3.748,0.002   v11.768h-3.256V172.535z"/>
-	<path id="path11126" d="M142.326,170.053h3.471v14.242h-3.471V170.053z"/>
-	<path id="path14040" d="M159.949,184.227c-2.24-0.338-3.854-1.586-4.748-3.68c-0.512-1.191-0.656-2.105-0.598-3.748   c0.061-1.664,0.254-2.451,0.885-3.605c0.816-1.488,1.883-2.344,3.557-2.846c0.877-0.266,1.064-0.291,2.275-0.293   c1.094-0.004,1.445,0.029,2.076,0.201c2.305,0.627,3.803,2.172,4.426,4.559c0.289,1.105,0.266,3.764-0.041,4.846   c-0.697,2.463-2.387,4.098-4.676,4.527C162.395,184.322,160.713,184.342,159.949,184.227z M162.293,181.963   c0.926-0.281,1.578-1.137,1.875-2.463c0.205-0.91,0.24-3.596,0.059-4.547c-0.336-1.762-1.328-2.654-2.957-2.656   c-1.59-0.002-2.457,0.793-2.912,2.67c-0.215,0.883-0.238,3.438-0.041,4.396c0.279,1.357,0.877,2.211,1.762,2.512   C160.682,182.082,161.756,182.123,162.293,181.963z"/>
-	<path id="path2224" d="M176.656,170.053l3.563,0.051c1.402,2.793,2.945,5.531,4.143,8.41l0.199,0.504l-0.049-1.01l-0.182-7.951   h2.992v14.246h-3.23l-0.369-0.758c-1.168-2.398-3.178-6.629-3.658-7.697c-0.305-0.684-0.531-1.137-0.502-1.012   c0.031,0.127,0.086,2.309,0.121,4.848l0.066,4.619h-3.094V170.053z"/>
-	<g id="g3173" transform="translate(-0.4495808,1251.722)">
-		<path id="path2320" d="M185.373-1089.163c-1.527-0.85-2.496-1.666-3.189-2.689l-0.402-0.596l-0.586,0.516    c-0.816,0.725-1.141,0.965-1.887,1.406c-1.727,1.02-4.043,1.439-6.92,1.252c-5.955-0.385-9.082-3.238-9.49-8.66    c-0.182-2.412,0.223-4.607,1.158-6.289c1.281-2.305,3.789-3.914,7.313-4.695c1.803-0.398,3.266-0.545,5.977-0.594l2.516-0.049    l-0.049-1.311c-0.027-0.723-0.09-1.543-0.137-1.824c-0.25-1.477-0.871-2.223-2.035-2.445c-0.902-0.17-1.32-0.18-2.357-0.053    c-2.006,0.246-4.098,1.066-6.678,2.623c-0.691,0.416-1.297,0.744-1.346,0.725c-0.096-0.037-3.463-5.682-3.461-5.799    c0.008-0.166,2.094-1.316,3.582-1.973c4.023-1.775,6.543-2.377,9.953-2.377c3.17,0,5.359,0.533,7.127,1.736    c0.693,0.473,1.736,1.551,2.115,2.186c0.35,0.586,0.777,1.646,1.012,2.51l0.189,0.691l-0.041,4.766    c-0.021,2.619-0.041,6.43-0.041,8.467c0,4.178,0,4.18,0.633,5.414c0.273,0.537,0.498,0.814,1.266,1.57    c0.855,0.842,0.922,0.93,0.809,1.059c-0.068,0.076-1.029,1.184-2.137,2.461c-1.109,1.275-2.057,2.328-2.107,2.338    C186.108-1088.786,185.756-1088.953,185.373-1089.163z M175.903-1095.453c1.229-0.154,2.246-0.641,3.182-1.518l0.508-0.477    l0.055-3.168l0.053-3.168l-1.316,0.057c-4.154,0.178-5.707,0.842-6.377,2.729c-0.213,0.596-0.295,2.16-0.146,2.787    c0.334,1.418,1.457,2.533,2.768,2.748c0.246,0.039,0.486,0.078,0.531,0.082C175.203-1095.374,175.539-1095.408,175.903-1095.453z     M137.623-1089.718c-1.318-0.205-2.459-0.68-3.502-1.459c-1.109-0.826-1.762-1.803-2.238-3.348    c-0.445-1.441-0.436-1.025-0.49-18.475c-0.051-15.838-0.057-16.158-0.236-18.186c-0.102-1.135-0.162-2.086-0.137-2.111    c0.074-0.074,8.055-1.891,8.154-1.857c0.098,0.037,0.248,1.135,0.361,2.654c0.162,10.801,0.012,21.605,0.156,32.406    c0.063,2.619,0.086,2.936,0.24,3.373c0.379,1.078,0.902,1.469,1.963,1.465c0.336,0,0.662-0.018,0.727-0.039    c0.105-0.033,0.479,1.133,1.371,4.289l0.162,0.578l-1.271,0.334C141.034-1089.607,139.186-1089.476,137.623-1089.718z     M154.555-1089.644c-1.066-0.125-1.982-0.391-2.85-0.822c-2.164-1.08-3.219-2.633-3.713-5.475    c-0.066-0.375-0.109-5.193-0.146-16.57c-0.053-15.98-0.055-16.049-0.25-18.383c-0.117-1.43-0.164-2.367-0.119-2.408    c0.102-0.088,8.1-1.91,8.152-1.857c0.088,0.088,0.268,1.711,0.348,3.148c0.213,11.125-0.035,22.258,0.162,33.383    c0.055,1.18,0.107,1.611,0.238,1.984c0.221,0.625,0.525,1.014,0.945,1.199c0.457,0.203,1.182,0.281,1.516,0.166    c0.174-0.063,0.283-0.066,0.316-0.014c0.078,0.129,1.402,4.816,1.369,4.85c-0.016,0.018-0.504,0.164-1.084,0.328    C158.041-1089.722,155.75-1089.501,154.555-1089.644z M67.676-1089.716c-0.134-0.018-0.61-0.076-1.059-0.127    c-0.447-0.053-1.237-0.215-1.756-0.363c-5.568-1.582-9.046-6.182-9.853-13.021c-0.124-1.047-0.123-3.988,0.001-5.09    c0.362-3.213,1.4-6.119,2.997-8.387c1.083-1.537,2.861-3.086,4.462-3.889c2.021-1.016,3.78-1.402,6.368-1.402    c2.15,0,3.536,0.219,5.156,0.816c3.931,1.449,7.106,5.004,8.254,9.238c0.922,3.398,0.905,8.645-0.037,12.051    c-0.744,2.691-2.024,4.861-3.966,6.725s-4.086,2.918-6.7,3.297C70.775-1089.757,68.143-1089.654,67.676-1089.716z M70.77-1096.027    c1.815-0.824,2.693-2.672,3.095-6.512c0.153-1.465,0.177-5.111,0.041-6.512c-0.375-3.879-1.335-5.748-3.356-6.531    c-1.055-0.41-2.505-0.303-3.577,0.262c-1.823,0.959-2.647,2.99-2.926,7.207c-0.158,2.404-0.013,5.633,0.343,7.572    c0.475,2.602,1.225,3.77,2.859,4.457c0.768,0.322,1.166,0.387,2.144,0.344C70.09-1095.769,70.293-1095.812,70.77-1096.027z     M10.314-1116.745c-0.13-1.063-0.376-2.029-0.667-2.621c-0.147-0.301-0.224-0.547-0.182-0.584c0.09-0.078,7.021-1.965,7.22-1.965    c0.204,0,0.671,0.98,0.915,1.92c0.112,0.432,0.204,0.855,0.204,0.939c0,0.086,0.027,0.152,0.061,0.152    c0.034-0.002,0.391-0.277,0.794-0.615c1.52-1.27,3.532-2.127,5.465-2.324c2.115-0.217,4.02,0.1,5.551,0.92    c0.98,0.527,2.146,1.512,2.768,2.336l0.488,0.646l0.314-0.326c0.76-0.789,2.256-1.92,3.307-2.496    c0.898-0.494,2.17-0.893,3.413-1.074c1.114-0.16,3.312-0.063,4.384,0.197c1.185,0.287,2.204,0.719,2.971,1.26    c1.574,1.109,2.172,2.082,2.584,4.207c0.172,0.885,0.174,1.025,0.203,13.373l0.029,12.479H42.15v-10.934    c0-7.029-0.03-11.18-0.084-11.623c-0.198-1.623-0.574-2.096-1.798-2.268c-1.429-0.199-3.438,0.574-5.267,2.025l-0.667,0.529    l0,22.27h-7.729c-0.473-7.383,0.652-15.438-0.186-22.727c-0.296-1.432-0.807-1.955-2.059-2.107    c-1.462-0.178-3.452,0.498-5.153,1.75l-0.664,0.488l-0.005,22.596h-7.979C10.282-1099.062,11.051-1108.048,10.314-1116.745z     M86.536-1095.492l14.459-19.949l-13.248-0.043v-5.779h23.043v5.578c-4.503,6.535-9.129,12.986-13.598,19.545l14.179,0.037    l-0.059,0.182l-1.888,5.559l-22.899,0.041L86.536-1095.492z M116.735-1120.853l0.184-0.041c2.588-0.43,5.186-0.809,7.775-1.227    l0.266-0.045v31.844h-8.225V-1120.853z M120.276-1124.939c-1.963-0.195-3.682-1.678-4.188-3.611    c-0.703-2.688,0.707-5.361,3.273-6.201c0.484-0.158,0.754-0.191,1.592-0.191c1.578,0,2.482,0.357,3.508,1.381    c0.986,0.986,1.412,2.068,1.418,3.586c0.004,1.563-0.406,2.584-1.457,3.637C123.332-1125.245,121.934-1124.773,120.276-1124.939z"/>
-	</g>
-</g>
-</svg>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/moz.build
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-fixtures = [
-    'native-addon-test',
-    'native-overrides-test',
-]
-
-output_dir = OBJDIR_FILES._tests.testing.mochitest['jetpack-package']['addon-sdk'].source.test.fixtures
-
-for fixture in fixtures:
-    xpi = '%s.xpi' % fixture
-
-    GENERATED_FILES += [xpi]
-    f = GENERATED_FILES[xpi]
-    f.script = 'create_xpi.py'
-    f.inputs = [fixture]
-
-    output_dir += ['!%s' % xpi]
deleted file mode 100644
index d44438903b751f4732f5365783eb0229b0501f9a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/a.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'dir/a';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/a/index.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'dir/a/index';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/b.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-module.exports = require('test-math');
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/c.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-module.exports = require('../package.json');
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/dummy.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-module.exports = 'this is a dummy module';
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/dir/test.jsm
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this['EXPORTED_SYMBOLS'] = ['test'];
-var test = 'this is a jsm';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/expectedmap.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "./index.js": {
-    "./dir/a": "./dir/a.js",
-    "./dir/b": "./dir/b.js",
-    "./dir/c": "./dir/c.js",
-    "./dir/dummy": "./dir/dummy.js",
-    "./dir/test.jsm": "./dir/test.jsm",
-    "./utils": "./utils/index.js",
-    "./newmodule": "./newmodule/lib/file.js",
-    "test-math": "./node_modules/test-math/index.js",
-    "test-custom-main": "./node_modules/test-custom-main/lib/custom-entry.js",
-    "test-custom-main-relative": "./node_modules/test-custom-main-relative/lib/custom-entry.js",
-    "test-default-main": "./node_modules/test-default-main/index.js"
-  },
-  "./dir/b.js": {
-    "test-math": "./node_modules/test-math/index.js"
-  },
-  "./dir/c.js": {
-    "../package.json": "./package.json"
-  },
-  "./node_modules/test-math/index.js": {
-    "test-add": "./node_modules/test-math/node_modules/test-add/index.js",
-    "test-subtract": "./node_modules/test-math/node_modules/test-subtract/index.js"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/index.js
+++ /dev/null
@@ -1,42 +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/. */
-
-// Added noise to test AST walker
-for (var i = 0; i < 5; i++) {
-  square(i);
-}
-
-exports.directoryDefaults = require('./utils');
-exports.directoryMain = require('./newmodule');
-exports.resolvesJSoverDir= require('./dir/a');
-exports.math = require('test-math');
-exports.mathInRelative = require('./dir/b');
-exports.customMainModule = require('test-custom-main');
-exports.customMainModuleRelative = require('test-custom-main-relative');
-exports.defaultMain = require('test-default-main');
-exports.testJSON = require('./dir/c');
-exports.dummyModule = require('./dir/dummy');
-
-exports.eventCore = require('sdk/event/core');
-exports.promise = require('sdk/core/promise');
-
-if (module.uri.startsWith("file:"))
-  // We can't load the same file multiple times with different URLs, so
-  // skip this one.
-  exports.localJSM = { test: "this is a jsm" };
-else
-  exports.localJSM = require('./dir/test.jsm');
-exports.promisejsm = require('modules/Promise.jsm').Promise;
-exports.require = require;
-
-var math = require('test-math');
-exports.areModulesCached = (math === exports.math);
-
-// Added noise to test AST walker
-function square (x) {
-  let tmp = x;
-  tmp *= x;
-  return tmp;
-}
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/newmodule/index.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'index.js';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/newmodule/lib/file.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'main from new module';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/newmodule/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "main":"lib/file.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/index.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = "assets!"
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "test-assets",
-  "version": "0.0.1",
-  "dependencies": {
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/styles.css
+++ /dev/null
@@ -1,7 +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/. */
-
-body {
-  background-color: #ff0077;
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main-relative/lib/custom-entry.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'custom entry file relative';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main-relative/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name" : "test-custom-main-relative",
-  "main" : "./lib/custom-entry"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main/lib/custom-entry.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'custom entry file';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-custom-main/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name" : "test-custom-main",
-  "main" : "lib/custom-entry"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-default-main/index.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 'default main';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-default-main/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "name" : "test-default-main"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/index.js
+++ /dev/null
@@ -1,9 +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.add = require('test-add');
-exports.subtract = require('test-subtract');
-exports.main = 'index.js';
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/lib/sqrt.js
+++ /dev/null
@@ -1,7 +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.exports = Math.sqrt;
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-add/index.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = function (a,b) { return a + b; }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-add/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "test-add",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-subtract/index.js
+++ /dev/null
@@ -1,7 +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.exports = function (a,b) { return a - b; }
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/node_modules/test-subtract/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "test-subtract",
-  "version": "0.0.1"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-math/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "test-math",
-  "version": "0.0.1",
-  "dependencies": {
-    "test-add": "*",
-    "test-subtract: "*"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "main":"index.js",
-  "dependencies": {
-    "test-math": "*",
-    "test-custom-main": "*",
-    "test-custom-main-relative": "*",
-    "test-default-main": "*",
-    "test-assets": "*"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-addon-test/utils/index.js
+++ /dev/null
@@ -1,7 +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.exports = 'utils';
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/ignore.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.bar = "do not ignore this export";
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-var foo = require("foo");
-var coolTabs = require("cool-tabs");
-
-exports.foo = foo.fs;
-exports.bar = foo.bar;
-exports.fs = require("sdk/io/file");
-exports.extra = require("fs-extra").extra;
-exports.overload = require("overload");
-exports.overloadLib = require("overload/lib/foo.js");
-exports.internal = require("internal").internal;
-exports.Tabs = require("sdk/tabs").Tabs;
-exports.CoolTabs = coolTabs.Tabs;
-exports.CoolTabsLib = coolTabs.TabsLib;
-exports.ignore = require("./lib/ignore").foo;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/lib/ignore.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.foo = require("../ignore").bar;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/lib/internal.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.internal = "test";
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/lib/tabs.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.Tabs = "no tabs exist";
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/index.js
+++ /dev/null
@@ -1,7 +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.Tabs = require("sdk/tabs").Tabs;
-exports.TabsLib = require("./lib/tabs").Tabs
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/lib/tabs.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.Tabs = "a cool tabs implementation";
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/cool-tabs/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "cool-tabs",
-  "main": "index.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/index.js
+++ /dev/null
@@ -1,7 +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.fs = require("fs");
-exports.bar = require("bar");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/lib/foo.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.fs = require("fs");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/node_modules/bar/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.exports = require("fs");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/node_modules/bar/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "bar",
-  "version": "0.0.1",
-  "main": "./index.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/foo/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "foo",
-  "version": "0.0.1",
-  "main": "./index.js",
-  "dependencies": {
-    "bar": "*"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/fs-extra/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-exports.extra = true;
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/node_modules/fs-extra/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "fs-extra",
-  "main": "index.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/native-overrides-test/package.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "name": "native-overrides-test",
-  "main": "index.js",
-  "dependencies": {
-    "cool-tabs": "*",
-    "foo": "*",
-    "fs-extra": "*"
-  },
-  "jetpack": {
-    "overrides": {
-      "fs": "sdk/io/file",
-      "overload": "foo",
-      "internal": "./lib/internal",
-      "sdk/tabs": "./lib/tabs",
-      "../ignore": "foo"
-    }
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/preferences/curly-id/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "id": "{34a1eae1-c20a-464f-9b0e-000000000000}",
-    "fullName": "curly ID test",
-    "author": "Tomislav Jovanovic",
-
-    "preferences": [{
-        "name": "test13",
-        "type": "integer",
-        "title": "test13",
-        "value": 26
-    }],
-
-    "preferences-branch": "invalid^branch*name"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/preferences/no-prefs/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "id": "no-prefs@jetpack",
-    "title": "No Prefs Test",
-    "author": "Erik Vold",
-    "loader": "lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/preferences/preferences-branch/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "id": "test-preferences-branch",
-    "fullName": "preferences-branch test",
-    "author": "Tomislav Jovanovic",
-
-    "preferences": [{
-        "name": "test42",
-        "type": "bool",
-        "title": "test42",
-        "value": true
-    }],
-
-    "preferences-branch": "human-readable"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/preferences/simple-prefs/package.json
+++ /dev/null
@@ -1,75 +0,0 @@
-{
-    "id": "simple-prefs@jetpack",
-    "title": "Simple Prefs Test",
-    "author": "Erik Vold",
-    "preferences": [{
-        "name": "test",
-        "type": "bool",
-        "title": "tëst",
-        "value": false,
-        "description": "descrïptiön"
-    },
-    {
-        "name": "test2",
-        "type": "string",
-        "title": "tëst",
-        "value": "ünicødé"
-    },
-    {
-        "name": "test3",
-        "type": "menulist",
-        "title": "\"><test",
-        "value": "1",
-        "options": [
-            {
-                "value": "0",
-                "label": "label1"
-            },
-            {
-                "value": "1",
-                "label": "label2"
-            }
-        ]
-    },
-    {
-        "name": "test4",
-        "type": "radio",
-        "title": "tëst",
-        "value": "red",
-        "options": [
-            {
-                "value": "red",
-                "label": "rouge"
-            },
-            {
-                "value": "blue",
-                "label": "bleu"
-            }
-        ]
-    },
-    {
-        "name": "test5",
-        "type": "boolint",
-        "title": "part part, particle",
-        "value": 7
-    },
-    {
-        "name": "test6",
-        "type": "color",
-        "title": "pop pop, popscicle",
-        "value": "#ff5e99"
-    },
-    {
-        "name": "test7",
-        "type": "file",
-        "title": "bike bike",
-        "value": "bicycle"
-    },
-    {
-        "name": "test8",
-        "type": "directory",
-        "title": "test test",
-        "value": "1-2-3"
-    }],
-    "loader": "lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/sandbox-complex-character.js
+++ /dev/null
@@ -1,5 +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 chars = 'გამარჯობა';
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/sandbox-normal.js
+++ /dev/null
@@ -1,7 +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 a = 1;
-this.b = 2;
-function f() { return 4; }
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-addon-extras-window.html
+++ /dev/null
@@ -1,21 +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 charset="UTF-8">
-    <title>Worker test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-  <script>
-    if ("addon" in window) {
-      var count = 1;
-      addon.port.on("get-result", () => {
-        addon.port.emit("result" + count++, extras.test().getTestURL())
-      });
-    }
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-addon-extras.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/. -->
-
-<html>
-<head>
-    <meta charset="UTF-8">
-    <title>Worker test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-  <script>
-    if ("addon" in window) {
-      var count = 1;
-      addon.port.on("get-result", () => {
-        console.log("get-result received");
-        addon.port.emit("result" + count++, extras && extras.test())
-      });
-    }
-
-    window.addEventListener("message", function getMessage({ data }) {
-      if (data.name == "start") {
-        window.postMessage({
-          name: "extras",
-          result: window.extras === undefined
-        }, '*');
-      }
-    });
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-contentScriptFile.js
+++ /dev/null
@@ -1,5 +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/. */
-
-self.postMessage("msg from contentScriptFile");
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-context-menu.js
+++ /dev/null
@@ -1,5 +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/. */
-
-self.on("context", () => true);
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-iframe-postmessage.html
+++ /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/. -->
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <script>
-    window.addEventListener("message", function(msg) {
-      parent.postMessage(msg.data, "*");
-    });
-
-    parent.postMessage({
-      first: "a string",
-      second: ["an", "array"],
-      third: {an: 'object'}
-    }, '*');
-    </script>
-  </head>
-  <body>
-    <h1>Inner iframe</h1>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-iframe.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<!DOCTYPE HTML>
-<html>
-<head>
-  <meta charset="UTF-8">
-</head>
-<body>
-  <iframe id="inner" src="about:blank"></iframe>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-iframe.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var count = 0;
-
-setTimeout(function() {
-  window.addEventListener("message", function(msg) {
-    if (++count > 1) {
-    	self.postMessage(msg.data);
-    }
-    else msg.source.postMessage(msg.data, '*');
-  });
-
-  document.getElementById('inner').src = iframePath;
-}, 0);
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-message-manager.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const TEST_VALUE = 11;
-
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-net-url.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello, ゼロ!
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-page-mod.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<head>
-    <meta charset="UTF-8">
-    <title>Page Mod test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-sidebar-addon-global.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<script>
-if ("addon" in window) {
-  addon.port.on('X', function(msg) {
-    // last message
-    addon.port.emit('X', msg + '3');
-  });
-
-  // start messaging chain
-  addon.port.emit('Y', '1');
-}
-</script>
-SIDEBAR TEST
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test-trusted-document.html
+++ /dev/null
@@ -1,20 +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 charset="UTF-8">
-    <title>Worker test</title>
-</head>
-<body>
-  <p id="paragraph">Lorem ipsum dolor sit amet.</p>
-  <script>
-    if ("addon" in window) {
-      addon.port.on('addon-to-document', function (arg) {
-        addon.port.emit('document-to-addon', arg);
-      });
-    }
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/test.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <title>foo</title>
-  </head>
-  <body>
-    <p>bar</p>
-    <script>
-    function getTestURL() {
-      return window.document.documentURI + "";
-    }
-    function changesInWindow() {
-      window.document.documentElement.setAttribute('test', 'changes in window');
-      return null;
-    }
-    function getAUQLUE() {
-      return "AUQLUE" in window;
-    }
-    </script>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/fixtures/testLocalXhr.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
deleted file mode 100644
--- a/addon-sdk/source/test/framescript-manager/frame-script.js
+++ /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/. */
-"use strict";
-
-const {onPing} = require("./pong");
-
-exports.onPing = onPing;
-
-exports.onInit = (context) => {
-  context.sendAsyncMessage("framescript-manager/ready", {state: "ready"});
-  context.addMessageListener("framescript-manager/ping", exports.onPing);
-};
deleted file mode 100644
--- a/addon-sdk/source/test/framescript-manager/pong.js
+++ /dev/null
@@ -1,7 +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.onPing = message =>
-  message.target.sendAsyncMessage("framescript-manager/pong", message.data);
deleted file mode 100644
--- a/addon-sdk/source/test/framescript-util/frame-script.js
+++ /dev/null
@@ -1,21 +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 { windowToMessageManager, nodeToMessageManager } = require("framescript/util");
-
-
-const onInit = (context) => {
-  context.addMessageListener("framescript-util/window/request", _ => {
-    windowToMessageManager(context.content.window).sendAsyncMessage(
-      "framescript-util/window/response", {window: true});
-  });
-
-  context.addMessageListener("framescript-util/node/request", message => {
-    const node = context.content.document.querySelector(message.data);
-    nodeToMessageManager(node).sendAsyncMessage(
-      "framescript-util/node/response", {node: true});
-  });
-};
-exports.onInit = onInit;
deleted file mode 100644
--- a/addon-sdk/source/test/jetpack-package.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-[DEFAULT]
-support-files =
-  fixtures/**
-  fixtures/native-addon-test.xpi
-  fixtures/native-overrides-test.xpi
-  loader/**
-generated-files =
-  fixtures/native-addon-test.xpi
-  fixtures/native-overrides-test.xpi
-
-[test-loader.js]
-[test-native-loader.js]
deleted file mode 100644
--- a/addon-sdk/source/test/leak/jetpack-package.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[DEFAULT]
-support-files =
-  leak-utils.js
-
-[test-leak-window-events.js]
-[test-leak-event-dom-closed-window.js]
-[test-leak-tab-events.js]
deleted file mode 100644
--- a/addon-sdk/source/test/leak/leak-utils.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu, Ci } = require("chrome");
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
-
-// Adapted from the SpecialPowers.exactGC() code.  We don't have a
-// window to operate on so we cannot use the exact same logic.  We
-// use 6 GC iterations here as that is what is needed to clean up
-// the windows we have tested with.
-function gc() {
-  return new Promise(resolve => {
-    Cu.forceGC();
-    Cu.forceCC();
-    let count = 0;
-    function genGCCallback() {
-      Cu.forceCC();
-      return function() {
-        if (++count < 5) {
-          Cu.schedulePreciseGC(genGCCallback());
-        } else {
-          resolve();
-        }
-      }
-    }
-
-    Cu.schedulePreciseGC(genGCCallback());
-  });
-}
-
-// Execute the given test function and verify that we did not leak windows
-// in the process.  The test function must return a promise or be a generator.
-// If the promise is resolved, or generator completes, with an sdk loader
-// object then it will be unloaded after the memory measurements.
-exports.asyncWindowLeakTest = function*(assert, asyncTestFunc) {
-
-  // Wait for the browser to finish loading.
-  yield Startup.onceInitialized;
-
-  // Track windows that are opened in an array of weak references.
-  let weakWindows = [];
-  function windowObserver(subject, topic) {
-    let supportsWeak = subject.QueryInterface(Ci.nsISupportsWeakReference);
-    if (supportsWeak) {
-      weakWindows.push(Cu.getWeakReference(supportsWeak));
-    }
-  }
-  Services.obs.addObserver(windowObserver, "domwindowopened");
-
-  // Execute the body of the test.
-  let testLoader = yield asyncTestFunc(assert);
-
-  // Stop tracking new windows and attempt to GC any resources allocated
-  // by the test body.
-  Services.obs.removeObserver(windowObserver, "domwindowopened");
-  yield gc();
-
-  // Check to see if any of the windows we saw survived the GC.  We consider
-  // these leaks.
-  assert.ok(weakWindows.length > 0, "should see at least one new window");
-  for (let i = 0; i < weakWindows.length; ++i) {
-    assert.equal(weakWindows[i].get(), null, "window " + i + " should be GC'd");
-  }
-
-  // Finally, unload the test body's loader if it provided one.  We do this
-  // after our leak detection to avoid free'ing things on unload.  Users
-  // don't tend to unload their addons very often, so we want to find leaks
-  // that happen while addons are in use.
-  if (testLoader) {
-    testLoader.unload();
-  }
-}
deleted file mode 100644
--- a/addon-sdk/source/test/leak/test-leak-event-dom-closed-window.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { asyncWindowLeakTest } = require("./leak-utils");
-const { Loader } = require('sdk/test/loader');
-const openWindow = require("sdk/window/utils").open;
-
-exports["test sdk/event/dom does not leak when attached to closed window"] = function*(assert) {
-  yield asyncWindowLeakTest(assert, _ => {
-    return new Promise(resolve => {
-      let loader = Loader(module);
-      let { open } = loader.require('sdk/event/dom');
-      let w = openWindow();
-      w.addEventListener("DOMWindowClose", function(evt) {
-        // The sdk/event/dom module tries to clean itself up when DOMWindowClose
-        // is fired.  Verify that it doesn't leak if its attached to an
-        // already closed window either. (See bug 1268898.)
-        open(w.document, "TestEvent1");
-        resolve(loader);
-      }, {once: true});
-      w.close();
-    });
-  });
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/leak/test-leak-tab-events.js
+++ /dev/null
@@ -1,42 +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 { asyncWindowLeakTest } = require("./leak-utils");
-const { Loader } = require('sdk/test/loader');
-const openWindow = require("sdk/window/utils").open;
-
-exports["test sdk/tab/events does not leak new window"] = function*(assert) {
-  yield asyncWindowLeakTest(assert, _ => {
-    return new Promise(resolve => {
-      let loader = Loader(module);
-      let { events } = loader.require('sdk/tab/events');
-      let w = openWindow();
-      w.addEventListener("load", function(evt) {
-        w.addEventListener("DOMWindowClose", function(evt) {
-          resolve(loader);
-        }, {once: true});
-        w.close();
-      }, {once: true});
-    });
-  });
-}
-
-exports["test sdk/tab/events does not leak when attached to existing window"] = function*(assert) {
-  yield asyncWindowLeakTest(assert, _ => {
-    return new Promise(resolve => {
-      let loader = Loader(module);
-      let w = openWindow();
-      w.addEventListener("load", function(evt) {
-        let { events } = loader.require('sdk/tab/events');
-        w.addEventListener("DOMWindowClose", function(evt) {
-          resolve(loader);
-        }, {once: true});
-        w.close();
-      }, {once: true});
-    });
-  });
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/leak/test-leak-window-events.js
+++ /dev/null
@@ -1,63 +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";
-
-// Opening new windows in Fennec causes issues
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { asyncWindowLeakTest } = require("./leak-utils.js");
-const { Loader } = require("sdk/test/loader");
-const { open } = require("sdk/window/utils");
-
-exports["test window/events for leaks"] = function*(assert) {
-  yield asyncWindowLeakTest(assert, _ => {
-    return new Promise((resolve, reject) => {
-      let loader = Loader(module);
-      let { events } = loader.require("sdk/window/events");
-      let { on, off } = loader.require("sdk/event/core");
-
-      on(events, "data", function handler(e) {
-        try {
-          if (e.type === "load") {
-            e.target.close();
-          }
-          else if (e.type === "close") {
-            off(events, "data", handler);
-
-            // Let asyncWindowLeakTest call loader.unload() after the
-            // leak check.
-            resolve(loader);
-          }
-        } catch (e) {
-          reject(e);
-        }
-      });
-
-      // Open a window.  This will trigger our data events.
-      open();
-    });
-  });
-};
-
-exports["test window/events for leaks with existing window"] = function*(assert) {
-  yield asyncWindowLeakTest(assert, _ => {
-    return new Promise((resolve, reject) => {
-      let loader = Loader(module);
-      let w = open();
-      w.addEventListener("load", function(evt) {
-        let { events } = loader.require("sdk/window/events");
-        w.addEventListener("DOMWindowClose", function(evt) {
-          resolve(loader);
-        }, {once: true});
-        w.close();
-      }, {once: true});
-    });
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/lib/httpd.js
+++ /dev/null
@@ -1,5206 +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/. */
-
-/*
-* An implementation of an HTTP server both as a loadable script and as an XPCOM
-* component. See the accompanying README file for user documentation on
-* httpd.js.
-*/
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { components, CC, Cc, Ci, Cr, Cu } = require("chrome");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-
-const PR_UINT32_MAX = Math.pow(2, 32) - 1;
-
-/** True if debugging output is enabled, false otherwise. */
-var DEBUG = false; // non-const *only* so tweakable in server tests
-
-/** True if debugging output should be timestamped. */
-var DEBUG_TIMESTAMP = false; // non-const so tweakable in server tests
-
-var gGlobalObject = Cc["@mozilla.org/systemprincipal;1"].createInstance();
-
-/**
-* Asserts that the given condition holds. If it doesn't, the given message is
-* dumped, a stack trace is printed, and an exception is thrown to attempt to
-* stop execution (which unfortunately must rely upon the exception not being
-* accidentally swallowed by the code that uses it).
-*/
-function NS_ASSERT(cond, msg)
-{
-  if (DEBUG && !cond)
-  {
-    dumpn("###!!!");
-    dumpn("###!!! ASSERTION" + (msg ? ": " + msg : "!"));
-    dumpn("###!!! Stack follows:");
-
-    var stack = new Error().stack.split(/\n/);
-    dumpn(stack.map(function(val) { return "###!!! " + val; }).join("\n"));
-
-    throw Cr.NS_ERROR_ABORT;
-  }
-}
-
-/** Constructs an HTTP error object. */
-function HttpError(code, description)
-{
-  this.code = code;
-  this.description = description;
-}
-HttpError.prototype =
-{
-  toString: function()
-  {
-    return this.code + " " + this.description;
-  }
-};
-
-/**
-* Errors thrown to trigger specific HTTP server responses.
-*/
-const HTTP_400 = new HttpError(400, "Bad Request");
-const HTTP_401 = new HttpError(401, "Unauthorized");
-const HTTP_402 = new HttpError(402, "Payment Required");
-const HTTP_403 = new HttpError(403, "Forbidden");
-const HTTP_404 = new HttpError(404, "Not Found");
-const HTTP_405 = new HttpError(405, "Method Not Allowed");
-const HTTP_406 = new HttpError(406, "Not Acceptable");
-const HTTP_407 = new HttpError(407, "Proxy Authentication Required");
-const HTTP_408 = new HttpError(408, "Request Timeout");
-const HTTP_409 = new HttpError(409, "Conflict");
-const HTTP_410 = new HttpError(410, "Gone");
-const HTTP_411 = new HttpError(411, "Length Required");
-const HTTP_412 = new HttpError(412, "Precondition Failed");
-const HTTP_413 = new HttpError(413, "Request Entity Too Large");
-const HTTP_414 = new HttpError(414, "Request-URI Too Long");
-const HTTP_415 = new HttpError(415, "Unsupported Media Type");
-const HTTP_417 = new HttpError(417, "Expectation Failed");
-
-const HTTP_500 = new HttpError(500, "Internal Server Error");
-const HTTP_501 = new HttpError(501, "Not Implemented");
-const HTTP_502 = new HttpError(502, "Bad Gateway");
-const HTTP_503 = new HttpError(503, "Service Unavailable");
-const HTTP_504 = new HttpError(504, "Gateway Timeout");
-const HTTP_505 = new HttpError(505, "HTTP Version Not Supported");
-
-/** Creates a hash with fields corresponding to the values in arr. */
-function array2obj(arr)
-{
-  var obj = {};
-  for (var i = 0; i < arr.length; i++)
-    obj[arr[i]] = arr[i];
-  return obj;
-}
-
-/** Returns an array of the integers x through y, inclusive. */
-function range(x, y)
-{
-  var arr = [];
-  for (var i = x; i <= y; i++)
-    arr.push(i);
-  return arr;
-}
-
-/** An object (hash) whose fields are the numbers of all HTTP error codes. */
-const HTTP_ERROR_CODES = array2obj(range(400, 417).concat(range(500, 505)));
-
-
-/**
-* The character used to distinguish hidden files from non-hidden files, a la
-* the leading dot in Apache. Since that mechanism also hides files from
-* easy display in LXR, ls output, etc. however, we choose instead to use a
-* suffix character. If a requested file ends with it, we append another
-* when getting the file on the server. If it doesn't, we just look up that
-* file. Therefore, any file whose name ends with exactly one of the character
-* is "hidden" and available for use by the server.
-*/
-const HIDDEN_CHAR = "^";
-
-/**
-* The file name suffix indicating the file containing overridden headers for
-* a requested file.
-*/
-const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
-
-/** Type used to denote SJS scripts for CGI-like functionality. */
-const SJS_TYPE = "sjs";
-
-/** Base for relative timestamps produced by dumpn(). */
-var firstStamp = 0;
-
-/** dump(str) with a trailing "\n" -- only outputs if DEBUG. */
-function dumpn(str)
-{
-  if (DEBUG)
-  {
-    var prefix = "HTTPD-INFO | ";
-    if (DEBUG_TIMESTAMP)
-    {
-      if (firstStamp === 0)
-        firstStamp = Date.now();
-
-      var elapsed = Date.now() - firstStamp; // milliseconds
-      var min = Math.floor(elapsed / 60000);
-      var sec = (elapsed % 60000) / 1000;
-
-      if (sec < 10)
-        prefix += min + ":0" + sec.toFixed(3) + " | ";
-      else
-        prefix += min + ":" + sec.toFixed(3) + " | ";
-    }
-
-    dump(prefix + str + "\n");
-  }
-}
-
-/** Dumps the current JS stack if DEBUG. */
-function dumpStack()
-{
-  // peel off the frames for dumpStack() and Error()
-  var stack = new Error().stack.split(/\n/).slice(2);
-  stack.forEach(dumpn);
-}
-
-
-/** The XPCOM thread manager. */
-var gThreadManager = null;
-
-/** The XPCOM prefs service. */
-var gRootPrefBranch = null;
-function getRootPrefBranch()
-{
-  if (!gRootPrefBranch)
-  {
-    gRootPrefBranch = Cc["@mozilla.org/preferences-service;1"]
-                        .getService(Ci.nsIPrefBranch);
-  }
-  return gRootPrefBranch;
-}
-
-/**
-* JavaScript constructors for commonly-used classes; precreating these is a
-* speedup over doing the same from base principles. See the docs at
-* http://developer.mozilla.org/en/docs/components.Constructor for details.
-*/
-const ServerSocket = CC("@mozilla.org/network/server-socket;1",
-                        "nsIServerSocket",
-                        "init");
-const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
-                                 "nsIScriptableInputStream",
-                                 "init");
-const Pipe = CC("@mozilla.org/pipe;1",
-                "nsIPipe",
-                "init");
-const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
-                           "nsIFileInputStream",
-                           "init");
-const ConverterInputStream = CC("@mozilla.org/intl/converter-input-stream;1",
-                                "nsIConverterInputStream",
-                                "init");
-const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
-                               "nsIWritablePropertyBag2");
-const SupportsString = CC("@mozilla.org/supports-string;1",
-                          "nsISupportsString");
-
-/* These two are non-const only so a test can overwrite them. */
-var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-var BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
-                            "nsIBinaryOutputStream",
-                            "setOutputStream");
-
-/**
-* Returns the RFC 822/1123 representation of a date.
-*
-* @param date : Number
-* the date, in milliseconds from midnight (00:00:00), January 1, 1970 GMT
-* @returns string
-* the representation of the given date
-*/
-function toDateString(date)
-{
-  //
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // date1 = 2DIGIT SP month SP 4DIGIT
-  // ; day month year (e.g., 02 Jun 1982)
-  // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  // ; 00:00:00 - 23:59:59
-  // wkday = "Mon" | "Tue" | "Wed"
-  // | "Thu" | "Fri" | "Sat" | "Sun"
-  // month = "Jan" | "Feb" | "Mar" | "Apr"
-  // | "May" | "Jun" | "Jul" | "Aug"
-  // | "Sep" | "Oct" | "Nov" | "Dec"
-  //
-
-  const wkdayStrings = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-  const monthStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-  /**
-* Processes a date and returns the encoded UTC time as a string according to
-* the format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toTime(date)
-  {
-    var hrs = date.getUTCHours();
-    var rv = (hrs < 10) ? "0" + hrs : hrs;
-
-    var mins = date.getUTCMinutes();
-    rv += ":";
-    rv += (mins < 10) ? "0" + mins : mins;
-
-    var secs = date.getUTCSeconds();
-    rv += ":";
-    rv += (secs < 10) ? "0" + secs : secs;
-
-    return rv;
-  }
-
-  /**
-* Processes a date and returns the encoded UTC date as a string according to
-* the date1 format specified in RFC 2616.
-*
-* @param date : Date
-* the date to process
-* @returns string
-* a string of the form "HH:MM:SS", ranging from "00:00:00" to "23:59:59"
-*/
-  function toDate1(date)
-  {
-    var day = date.getUTCDate();
-    var month = date.getUTCMonth();
-    var year = date.getUTCFullYear();
-
-    var rv = (day < 10) ? "0" + day : day;
-    rv += " " + monthStrings[month];
-    rv += " " + year;
-
-    return rv;
-  }
-
-  date = new Date(date);
-
-  const fmtString = "%wkday%, %date1% %time% GMT";
-  var rv = fmtString.replace("%wkday%", wkdayStrings[date.getUTCDay()]);
-  rv = rv.replace("%time%", toTime(date));
-  return rv.replace("%date1%", toDate1(date));
-}
-
-/**
-* Prints out a human-readable representation of the object o and its fields,
-* omitting those whose names begin with "_" if showMembers != true (to ignore
-* "private" properties exposed via getters/setters).
-*/
-function printObj(o, showMembers)
-{
-  var s = "******************************\n";
-  s += "o = {\n";
-  for (var i in o)
-  {
-    if (typeof(i) != "string" ||
-        (showMembers || (i.length > 0 && i[0] != "_")))
-      s+= " " + i + ": " + o[i] + ",\n";
-  }
-  s += " };\n";
-  s += "******************************";
-  dumpn(s);
-}
-
-/**
-* Instantiates a new HTTP server.
-*/
-function nsHttpServer()
-{
-  if (!gThreadManager)
-    gThreadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-
-  /** The port on which this server listens. */
-  this._port = undefined;
-
-  /** The socket associated with this. */
-  this._socket = null;
-
-  /** The handler used to process requests to this server. */
-  this._handler = new ServerHandler(this);
-
-  /** Naming information for this server. */
-  this._identity = new ServerIdentity();
-
-  /**
-* Indicates when the server is to be shut down at the end of the request.
-*/
-  this._doQuit = false;
-
-  /**
-* True if the socket in this is closed (and closure notifications have been
-* sent and processed if the socket was ever opened), false otherwise.
-*/
-  this._socketClosed = true;
-
-  /**
-* Used for tracking existing connections and ensuring that all connections
-* are properly cleaned up before server shutdown; increases by 1 for every
-* new incoming connection.
-*/
-  this._connectionGen = 0;
-
-  /**
-* Hash of all open connections, indexed by connection number at time of
-* creation.
-*/
-  this._connections = {};
-}
-nsHttpServer.prototype =
-{
-  classID: components.ID("{54ef6f81-30af-4b1d-ac55-8ba811293e41}"),
-
-  // NSISERVERSOCKETLISTENER
-
-  /**
-* Processes an incoming request coming in on the given socket and contained
-* in the given transport.
-*
-* @param socket : nsIServerSocket
-* the socket through which the request was served
-* @param trans : nsISocketTransport
-* the transport for the request/response
-* @see nsIServerSocketListener.onSocketAccepted
-*/
-  onSocketAccepted: function(socket, trans)
-  {
-    dumpn("*** onSocketAccepted(socket=" + socket + ", trans=" + trans + ")");
-
-    dumpn(">>> new connection on " + trans.host + ":" + trans.port);
-
-    const SEGMENT_SIZE = 8192;
-    const SEGMENT_COUNT = 1024;
-    try
-    {
-      var input = trans.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
-                       .QueryInterface(Ci.nsIAsyncInputStream);
-      var output = trans.openOutputStream(0, 0, 0);
-    }
-    catch (e)
-    {
-      dumpn("*** error opening transport streams: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    var connectionNumber = ++this._connectionGen;
-
-    try
-    {
-      var conn = new Connection(input, output, this, socket.port, trans.port,
-                                connectionNumber);
-      var reader = new RequestReader(conn);
-
-      // XXX add request timeout functionality here!
-
-      // Note: must use main thread here, or we might get a GC that will cause
-      // threadsafety assertions. We really need to fix XPConnect so that
-      // you can actually do things in multi-threaded JS. :-(
-      input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
-    }
-    catch (e)
-    {
-      // Assume this connection can't be salvaged and bail on it completely;
-      // don't attempt to close it so that we can assert that any connection
-      // being closed is in this._connections.
-      dumpn("*** error in initial request-processing stages: " + e);
-      trans.close(Cr.NS_BINDING_ABORTED);
-      return;
-    }
-
-    this._connections[connectionNumber] = conn;
-    dumpn("*** starting connection " + connectionNumber);
-  },
-
-  /**
-* Called when the socket associated with this is closed.
-*
-* @param socket : nsIServerSocket
-* the socket being closed
-* @param status : nsresult
-* the reason the socket stopped listening (NS_BINDING_ABORTED if the server
-* was stopped using nsIHttpServer.stop)
-* @see nsIServerSocketListener.onStopListening
-*/
-  onStopListening: function(socket, status)
-  {
-    dumpn(">>> shutting down server on port " + socket.port);
-    this._socketClosed = true;
-    if (!this._hasOpenConnections())
-    {
-      dumpn("*** no open connections, notifying async from onStopListening");
-
-      // Notify asynchronously so that any pending teardown in stop() has a
-      // chance to run first.
-      var self = this;
-      var stopEvent =
-        {
-          run: function()
-          {
-            dumpn("*** _notifyStopped async callback");
-            self._notifyStopped();
-          }
-        };
-      gThreadManager.dispatchToMainThread(stopEvent);
-    }
-  },
-
-  // NSIHTTPSERVER
-
-  //
-  // see nsIHttpServer.start
-  //
-  start: function(port)
-  {
-    this._start(port, "localhost")
-  },
-
-  _start: function(port, host)
-  {
-    if (this._socket)
-      throw Cr.NS_ERROR_ALREADY_INITIALIZED;
-
-    this._port = port;
-    this._doQuit = this._socketClosed = false;
-
-    this._host = host;
-
-    // The listen queue needs to be long enough to handle
-    // network.http.max-persistent-connections-per-server concurrent connections,
-    // plus a safety margin in case some other process is talking to
-    // the server as well.
-    var prefs = getRootPrefBranch();
-    var maxConnections;
-    try {
-      // Bug 776860: The original pref was removed in favor of this new one:
-      maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server") + 5;
-    }
-    catch(e) {
-      maxConnections = prefs.getIntPref("network.http.max-connections-per-server") + 5;
-    }
-
-    try
-    {
-      var loopback = true;
-      if (this._host != "127.0.0.1" && this._host != "localhost") {
-        var loopback = false;
-      }
-
-      var socket = new ServerSocket(this._port,
-                                    loopback, // true = localhost, false = everybody
-                                    maxConnections);
-      dumpn(">>> listening on port " + socket.port + ", " + maxConnections +
-            " pending connections");
-      socket.asyncListen(this);
-      this._identity._initialize(socket.port, host, true);
-      this._socket = socket;
-    }
-    catch (e)
-    {
-      dumpn("!!! could not start server on port " + port + ": " + e);
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    }
-  },
-
-  //
-  // see nsIHttpServer.stop
-  //
-  stop: function(callback)
-  {
-    if (!callback)
-      throw Cr.NS_ERROR_NULL_POINTER;
-    if (!this._socket)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    this._stopCallback = typeof callback === "function"
-                       ? callback
-                       : function() { callback.onStopped(); };
-
-    dumpn(">>> stopping listening on port " + this._socket.port);
-    this._socket.close();
-    this._socket = null;
-
-    // We can't have this identity any more, and the port on which we're running
-    // this server now could be meaningless the next time around.
-    this._identity._teardown();
-
-    this._doQuit = false;
-
-    // socket-close notification and pending request completion happen async
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (file && (!file.exists() || file.isDirectory()))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handler.registerFile(path, file);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/" ||
-        path.charAt(path.length - 1) != "/" ||
-        (directory &&
-         (!directory.exists() || !directory.isDirectory())))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX determine behavior of nonexistent /foo/bar when a /foo/bar/ mapping
-    // exists!
-
-    this._handler.registerDirectory(path, directory);
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    this._handler.registerPathHandler(path, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    this._handler.registerPrefixHandler(prefix, handler);
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(code, handler)
-  {
-    this._handler.registerErrorHandler(code, handler);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    this._handler.setIndexHandler(handler);
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    this._handler.registerContentType(ext, type);
-  },
-
-  //
-  // see nsIHttpServer.serverIdentity
-  //
-  get identity()
-  {
-    return this._identity;
-  },
-
-  //
-  // see nsIHttpServer.getState
-  //
-  getState: function(path, k)
-  {
-    return this._handler._getState(path, k);
-  },
-
-  //
-  // see nsIHttpServer.setState
-  //
-  setState: function(path, k, v)
-  {
-    return this._handler._setState(path, k, v);
-  },
-
-  //
-  // see nsIHttpServer.getSharedState
-  //
-  getSharedState: function(k)
-  {
-    return this._handler._getSharedState(k);
-  },
-
-  //
-  // see nsIHttpServer.setSharedState
-  //
-  setSharedState: function(k, v)
-  {
-    return this._handler._setSharedState(k, v);
-  },
-
-  //
-  // see nsIHttpServer.getObjectState
-  //
-  getObjectState: function(k)
-  {
-    return this._handler._getObjectState(k);
-  },
-
-  //
-  // see nsIHttpServer.setObjectState
-  //
-  setObjectState: function(k, v)
-  {
-    return this._handler._setObjectState(k, v);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIServerSocketListener) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NON-XPCOM PUBLIC API
-
-  /**
-* Returns true iff this server is not running (and is not in the process of
-* serving any requests still to be processed when the server was last
-* stopped after being run).
-*/
-  isStopped: function()
-  {
-    return this._socketClosed && !this._hasOpenConnections();
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /** True if this server has any open connections to it, false otherwise. */
-  _hasOpenConnections: function()
-  {
-    //
-    // If we have any open connections, they're tracked as numeric properties on
-    // |this._connections|. The non-standard __count__ property could be used
-    // to check whether there are any properties, but standard-wise, even
-    // looking forward to ES5, there's no less ugly yet still O(1) way to do
-    // this.
-    //
-    for (var n in this._connections)
-      return true;
-    return false;
-  },
-
-  /** Calls the server-stopped callback provided when stop() was called. */
-  _notifyStopped: function()
-  {
-    NS_ASSERT(this._stopCallback !== null, "double-notifying?");
-    NS_ASSERT(!this._hasOpenConnections(), "should be done serving by now");
-
-    //
-    // NB: We have to grab this now, null out the member, *then* call the
-    // callback here, or otherwise the callback could (indirectly) futz with
-    // this._stopCallback by starting and immediately stopping this, at
-    // which point we'd be nulling out a field we no longer have a right to
-    // modify.
-    //
-    var callback = this._stopCallback;
-    this._stopCallback = null;
-    try
-    {
-      callback();
-    }
-    catch (e)
-    {
-      // not throwing because this is specified as being usually (but not
-      // always) asynchronous
-      dump("!!! error running onStopped callback: " + e + "\n");
-    }
-  },
-
-  /**
-* Notifies this server that the given connection has been closed.
-*
-* @param connection : Connection
-* the connection that was closed
-*/
-  _connectionClosed: function(connection)
-  {
-    NS_ASSERT(connection.number in this._connections,
-              "closing a connection " + this + " that we never added to the " +
-              "set of open connections?");
-    NS_ASSERT(this._connections[connection.number] === connection,
-              "connection number mismatch? " +
-              this._connections[connection.number]);
-    delete this._connections[connection.number];
-
-    // Fire a pending server-stopped notification if it's our responsibility.
-    if (!this._hasOpenConnections() && this._socketClosed)
-      this._notifyStopped();
-  },
-
-  /**
-* Requests that the server be shut down when possible.
-*/
-  _requestQuit: function()
-  {
-    dumpn(">>> requesting a quit");
-    dumpStack();
-    this._doQuit = true;
-  }
-};
-
-
-//
-// RFC 2396 section 3.2.2:
-//
-// host = hostname | IPv4address
-// hostname = *( domainlabel "." ) toplabel [ "." ]
-// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-//
-
-const HOST_REGEX =
-  new RegExp("^(?:" +
-               // *( domainlabel "." )
-               "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
-               // toplabel
-               "[a-z](?:[a-z0-9-]*[a-z0-9])?" +
-             "|" +
-               // IPv4 address
-               "\\d+\\.\\d+\\.\\d+\\.\\d+" +
-             ")$",
-             "i");
-
-
-/**
-* Represents the identity of a server. An identity consists of a set of
-* (scheme, host, port) tuples denoted as locations (allowing a single server to
-* serve multiple sites or to be used behind both HTTP and HTTPS proxies for any
-* host/port). Any incoming request must be to one of these locations, or it
-* will be rejected with an HTTP 400 error. One location, denoted as the
-* primary location, is the location assigned in contexts where a location
-* cannot otherwise be endogenously derived, such as for HTTP/1.0 requests.
-*
-* A single identity may contain at most one location per unique host/port pair;
-* other than that, no restrictions are placed upon what locations may
-* constitute an identity.
-*/
-function ServerIdentity()
-{
-  /** The scheme of the primary location. */
-  this._primaryScheme = "http";
-
-  /** The hostname of the primary location. */
-  this._primaryHost = "127.0.0.1"
-
-  /** The port number of the primary location. */
-  this._primaryPort = -1;
-
-  /**
-* The current port number for the corresponding server, stored so that a new
-* primary location can always be set if the current one is removed.
-*/
-  this._defaultPort = -1;
-
-  /**
-* Maps hosts to maps of ports to schemes, e.g. the following would represent
-* https://example.com:789/ and http://example.org/:
-*
-* {
-* "xexample.com": { 789: "https" },
-* "xexample.org": { 80: "http" }
-* }
-*
-* Note the "x" prefix on hostnames, which prevents collisions with special
-* JS names like "prototype".
-*/
-  this._locations = { "xlocalhost": {} };
-}
-ServerIdentity.prototype =
-{
-  // NSIHTTPSERVERIDENTITY
-
-  //
-  // see nsIHttpServerIdentity.primaryScheme
-  //
-  get primaryScheme()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryScheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryHost
-  //
-  get primaryHost()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryHost;
-  },
-
-  //
-  // see nsIHttpServerIdentity.primaryPort
-  //
-  get primaryPort()
-  {
-    if (this._primaryPort === -1)
-      throw Cr.NS_ERROR_NOT_INITIALIZED;
-    return this._primaryPort;
-  },
-
-  //
-  // see nsIHttpServerIdentity.add
-  //
-  add: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      this._locations["x" + host] = entry = {};
-
-    entry[port] = scheme;
-  },
-
-  //
-  // see nsIHttpServerIdentity.remove
-  //
-  remove: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return false;
-
-    var present = port in entry;
-    delete entry[port];
-
-    if (this._primaryScheme == scheme &&
-        this._primaryHost == host &&
-        this._primaryPort == port &&
-        this._defaultPort !== -1)
-    {
-      // Always keep at least one identity in existence at any time, unless
-      // we're in the process of shutting down (the last condition above).
-      this._primaryPort = -1;
-      this._initialize(this._defaultPort, host, false);
-    }
-
-    return present;
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  has: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    return "x" + host in this._locations &&
-           scheme === this._locations["x" + host][port];
-  },
-
-  //
-  // see nsIHttpServerIdentity.has
-  //
-  getScheme: function(host, port)
-  {
-    this._validate("http", host, port);
-
-    var entry = this._locations["x" + host];
-    if (!entry)
-      return "";
-
-    return entry[port] || "";
-  },
-
-  //
-  // see nsIHttpServerIdentity.setPrimary
-  //
-  setPrimary: function(scheme, host, port)
-  {
-    this._validate(scheme, host, port);
-
-    this.add(scheme, host, port);
-
-    this._primaryScheme = scheme;
-    this._primaryHost = host;
-    this._primaryPort = port;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Initializes the primary name for the corresponding server, based on the
-* provided port number.
-*/
-  _initialize: function(port, host, addSecondaryDefault)
-  {
-    this._host = host;
-    if (this._primaryPort !== -1)
-      this.add("http", host, port);
-    else
-      this.setPrimary("http", "localhost", port);
-    this._defaultPort = port;
-
-    // Only add this if we're being called at server startup
-    if (addSecondaryDefault && host != "127.0.0.1")
-      this.add("http", "127.0.0.1", port);
-  },
-
-  /**
-* Called at server shutdown time, unsets the primary location only if it was
-* the default-assigned location and removes the default location from the
-* set of locations used.
-*/
-  _teardown: function()
-  {
-    if (this._host != "127.0.0.1") {
-      // Not the default primary location, nothing special to do here
-      this.remove("http", "127.0.0.1", this._defaultPort);
-    }
-
-    // This is a *very* tricky bit of reasoning here; make absolutely sure the
-    // tests for this code pass before you commit changes to it.
-    if (this._primaryScheme == "http" &&
-        this._primaryHost == this._host &&
-        this._primaryPort == this._defaultPort)
-    {
-      // Make sure we don't trigger the readding logic in .remove(), then remove
-      // the default location.
-      var port = this._defaultPort;
-      this._defaultPort = -1;
-      this.remove("http", this._host, port);
-
-      // Ensure a server start triggers the setPrimary() path in ._initialize()
-      this._primaryPort = -1;
-    }
-    else
-    {
-      // No reason not to remove directly as it's not our primary location
-      this.remove("http", this._host, this._defaultPort);
-    }
-  },
-
-  /**
-* Ensures scheme, host, and port are all valid with respect to RFC 2396.
-*
-* @throws NS_ERROR_ILLEGAL_VALUE
-* if any argument doesn't match the corresponding production
-*/
-  _validate: function(scheme, host, port)
-  {
-    if (scheme !== "http" && scheme !== "https")
-    {
-      dumpn("*** server only supports http/https schemes: '" + scheme + "'");
-      dumpStack();
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (!HOST_REGEX.test(host))
-    {
-      dumpn("*** unexpected host: '" + host + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-    if (port < 0 || port > 65535)
-    {
-      dumpn("*** unexpected port: '" + port + "'");
-      throw Cr.NS_ERROR_ILLEGAL_VALUE;
-    }
-  }
-};
-
-
-/**
-* Represents a connection to the server (and possibly in the future the thread
-* on which the connection is processed).
-*
-* @param input : nsIInputStream
-* stream from which incoming data on the connection is read
-* @param output : nsIOutputStream
-* stream to write data out the connection
-* @param server : nsHttpServer
-* the server handling the connection
-* @param port : int
-* the port on which the server is running
-* @param outgoingPort : int
-* the outgoing port used by this connection
-* @param number : uint
-* a serial number used to uniquely identify this connection
-*/
-function Connection(input, output, server, port, outgoingPort, number)
-{
-  dumpn("*** opening new connection " + number + " on port " + outgoingPort);
-
-  /** Stream of incoming data. */
-  this.input = input;
-
-  /** Stream for outgoing data. */
-  this.output = output;
-
-  /** The server associated with this request. */
-  this.server = server;
-
-  /** The port on which the server is running. */
-  this.port = port;
-
-  /** The outgoing poort used by this connection. */
-  this._outgoingPort = outgoingPort;
-
-  /** The serial number of this connection. */
-  this.number = number;
-
-  /**
-* The request for which a response is being generated, null if the
-* incoming request has not been fully received or if it had errors.
-*/
-  this.request = null;
-
-  /** State variables for debugging. */
-  this._closed = this._processed = false;
-}
-Connection.prototype =
-{
-  /** Closes this connection's input/output streams. */
-  close: function()
-  {
-    dumpn("*** closing connection " + this.number +
-          " on port " + this._outgoingPort);
-
-    this.input.close();
-    this.output.close();
-    this._closed = true;
-
-    var server = this.server;
-    server._connectionClosed(this);
-
-    // If an error triggered a server shutdown, act on it now
-    if (server._doQuit)
-      server.stop(function() { /* not like we can do anything better */ });
-  },
-
-  /**
-* Initiates processing of this connection, using the data in the given
-* request.
-*
-* @param request : Request
-* the request which should be processed
-*/
-  process: function(request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-
-    this.request = request;
-    this.server._handler.handleResponse(this);
-  },
-
-  /**
-* Initiates processing of this connection, generating a response with the
-* given HTTP error code.
-*
-* @param code : uint
-* an HTTP code, so in the range [0, 1000)
-* @param request : Request
-* incomplete data about the incoming request (since there were errors
-* during its processing
-*/
-  processError: function(code, request)
-  {
-    NS_ASSERT(!this._closed && !this._processed);
-
-    this._processed = true;
-    this.request = request;
-    this.server._handler.handleError(code, this);
-  },
-
-  /** Converts this to a string for debugging purposes. */
-  toString: function()
-  {
-    return "<Connection(" + this.number +
-           (this.request ? ", " + this.request.path : "") +"): " +
-           (this._closed ? "closed" : "open") + ">";
-  }
-};
-
-
-
-/** Returns an array of count bytes from the given input stream. */
-function readBytes(inputStream, count)
-{
-  return new BinaryInputStream(inputStream).readByteArray(count);
-}
-
-
-
-/** Request reader processing states; see RequestReader for details. */
-const READER_IN_REQUEST_LINE = 0;
-const READER_IN_HEADERS = 1;
-const READER_IN_BODY = 2;
-const READER_FINISHED = 3;
-
-
-/**
-* Reads incoming request data asynchronously, does any necessary preprocessing,
-* and forwards it to the request handler. Processing occurs in three states:
-*
-* READER_IN_REQUEST_LINE Reading the request's status line
-* READER_IN_HEADERS Reading headers in the request
-* READER_IN_BODY Reading the body of the request
-* READER_FINISHED Entire request has been read and processed
-*
-* During the first two stages, initial metadata about the request is gathered
-* into a Request object. Once the status line and headers have been processed,
-* we start processing the body of the request into the Request. Finally, when
-* the entire body has been read, we create a Response and hand it off to the
-* ServerHandler to be given to the appropriate request handler.
-*
-* @param connection : Connection
-* the connection for the request being read
-*/
-function RequestReader(connection)
-{
-  /** Connection metadata for this request. */
-  this._connection = connection;
-
-  /**
-* A container providing line-by-line access to the raw bytes that make up the
-* data which has been read from the connection but has not yet been acted
-* upon (by passing it to the request handler or by extracting request
-* metadata from it).
-*/
-  this._data = new LineData();
-
-  /**
-* The amount of data remaining to be read from the body of this request.
-* After all headers in the request have been read this is the value in the
-* Content-Length header, but as the body is read its value decreases to zero.
-*/
-  this._contentLength = 0;
-
-  /** The current state of parsing the incoming request. */
-  this._state = READER_IN_REQUEST_LINE;
-
-  /** Metadata constructed from the incoming request for the request handler. */
-  this._metadata = new Request(connection.port);
-
-  /**
-* Used to preserve state if we run out of line data midway through a
-* multi-line header. _lastHeaderName stores the name of the header, while
-* _lastHeaderValue stores the value we've seen so far for the header.
-*
-* These fields are always either both undefined or both strings.
-*/
-  this._lastHeaderName = this._lastHeaderValue = undefined;
-}
-RequestReader.prototype =
-{
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Called when more data from the incoming request is available. This method
-* then reads the available data from input and deals with that data as
-* necessary, depending upon the syntax of already-downloaded data.
-*
-* @param input : nsIAsyncInputStream
-* the stream of incoming data from the connection
-*/
-  onInputStreamReady: function(input)
-  {
-    dumpn("*** onInputStreamReady(input=" + input + ") on thread " +
-          gThreadManager.currentThread + " (main is " +
-          gThreadManager.mainThread + ")");
-    dumpn("*** this._state == " + this._state);
-
-    // Handle cases where we get more data after a request error has been
-    // discovered but *before* we can close the connection.
-    var data = this._data;
-    if (!data)
-      return;
-
-    try
-    {
-      data.appendBytes(readBytes(input, input.available()));
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** WARNING: unexpected error when reading from socket; will " +
-              "be treated as if the input stream had been closed");
-        dumpn("*** WARNING: actual error was: " + e);
-      }
-
-      // We've lost a race -- input has been closed, but we're still expecting
-      // to read more data. available() will throw in this case, and since
-      // we're dead in the water now, destroy the connection.
-      dumpn("*** onInputStreamReady called on a closed input, destroying " +
-            "connection");
-      this._connection.close();
-      return;
-    }
-
-    switch (this._state)
-    {
-      default:
-        NS_ASSERT(false, "invalid state: " + this._state);
-        break;
-
-      case READER_IN_REQUEST_LINE:
-        if (!this._processRequestLine())
-          break;
-        /* fall through */
-
-      case READER_IN_HEADERS:
-        if (!this._processHeaders())
-          break;
-        /* fall through */
-
-      case READER_IN_BODY:
-        this._processBody();
-    }
-
-    if (this._state != READER_FINISHED)
-      input.asyncWait(this, 0, 0, gThreadManager.currentThread);
-  },
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(aIID)
-  {
-    if (aIID.equals(Ci.nsIInputStreamCallback) ||
-        aIID.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE API
-
-  /**
-* Processes unprocessed, downloaded data as a request line.
-*
-* @returns boolean
-* true iff the request line has been fully processed
-*/
-  _processRequestLine: function()
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    // Servers SHOULD ignore any empty line(s) received where a Request-Line
-    // is expected (section 4.1).
-    var data = this._data;
-    var line = {};
-    var readSuccess;
-    while ((readSuccess = data.readLine(line)) && line.value == "")
-      dumpn("*** ignoring beginning blank line...");
-
-    // if we don't have a full line, wait until we do
-    if (!readSuccess)
-      return false;
-
-    // we have the first non-blank line
-    try
-    {
-      this._parseRequestLine(line.value);
-      this._state = READER_IN_HEADERS;
-      return true;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing request headers.
-*
-* @returns boolean
-* true iff header data in the request has been fully processed
-*/
-  _processHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    // XXX things to fix here:
-    //
-    // - need to support RFC 2047-encoded non-US-ASCII characters
-
-    try
-    {
-      var done = this._parseHeaders();
-      if (done)
-      {
-        var request = this._metadata;
-
-        // XXX this is wrong for requests with transfer-encodings applied to
-        // them, particularly chunked (which by its nature can have no
-        // meaningful Content-Length header)!
-        this._contentLength = request.hasHeader("Content-Length")
-                            ? parseInt(request.getHeader("Content-Length"), 10)
-                            : 0;
-        dumpn("_processHeaders, Content-length=" + this._contentLength);
-
-        this._state = READER_IN_BODY;
-      }
-      return done;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Processes stored data, assuming it is either at the beginning or in
-* the middle of processing the request body.
-*
-* @returns boolean
-* true iff the request body has been fully processed
-*/
-  _processBody: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    // XXX handle chunked transfer-coding request bodies!
-
-    try
-    {
-      if (this._contentLength > 0)
-      {
-        var data = this._data.purge();
-        var count = Math.min(data.length, this._contentLength);
-        dumpn("*** loading data=" + data + " len=" + data.length +
-              " excess=" + (data.length - count));
-
-        var bos = new BinaryOutputStream(this._metadata._bodyOutputStream);
-        bos.writeByteArray(data, count);
-        this._contentLength -= count;
-      }
-
-      dumpn("*** remaining body data len=" + this._contentLength);
-      if (this._contentLength == 0)
-      {
-        this._validateRequest();
-        this._state = READER_FINISHED;
-        this._handleResponse();
-        return true;
-      }
-
-      return false;
-    }
-    catch (e)
-    {
-      this._handleError(e);
-      return false;
-    }
-  },
-
-  /**
-* Does various post-header checks on the data in this request.
-*
-* @throws : HttpError
-* if the request was malformed in some way
-*/
-  _validateRequest: function()
-  {
-    NS_ASSERT(this._state == READER_IN_BODY);
-
-    dumpn("*** _validateRequest");
-
-    var metadata = this._metadata;
-    var headers = metadata._headers;
-
-    // 19.6.1.1 -- servers MUST report 400 to HTTP/1.1 requests w/o Host header
-    var identity = this._connection.server.identity;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-    {
-      if (!headers.hasHeader("Host"))
-      {
-        dumpn("*** malformed HTTP/1.1 or greater request with no Host header!");
-        throw HTTP_400;
-      }
-
-      // If the Request-URI wasn't absolute, then we need to determine our host.
-      // We have to determine what scheme was used to access us based on the
-      // server identity data at this point, because the request just doesn't
-      // contain enough data on its own to do this, sadly.
-      if (!metadata._host)
-      {
-        var host, port;
-        var hostPort = headers.getHeader("Host");
-        var colon = hostPort.indexOf(":");
-        if (colon < 0)
-        {
-          host = hostPort;
-          port = "";
-        }
-        else
-        {
-          host = hostPort.substring(0, colon);
-          port = hostPort.substring(colon + 1);
-        }
-
-        // NB: We allow an empty port here because, oddly, a colon may be
-        // present even without a port number, e.g. "example.com:"; in this
-        // case the default port applies.
-        if (!HOST_REGEX.test(host) || !/^\d*$/.test(port))
-        {
-          dumpn("*** malformed hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        // If we're not given a port, we're stuck, because we don't know what
-        // scheme to use to look up the correct port here, in general. Since
-        // the HTTPS case requires a tunnel/proxy and thus requires that the
-        // requested URI be absolute (and thus contain the necessary
-        // information), let's assume HTTP will prevail and use that.
-        port = +port || 80;
-
-        var scheme = identity.getScheme(host, port);
-        if (!scheme)
-        {
-          dumpn("*** unrecognized hostname (" + hostPort + ") in Host " +
-                "header, 400 time");
-          throw HTTP_400;
-        }
-
-        metadata._scheme = scheme;
-        metadata._host = host;
-        metadata._port = port;
-      }
-    }
-    else
-    {
-      NS_ASSERT(metadata._host === undefined,
-                "HTTP/1.0 doesn't allow absolute paths in the request line!");
-
-      metadata._scheme = identity.primaryScheme;
-      metadata._host = identity.primaryHost;
-      metadata._port = identity.primaryPort;
-    }
-
-    NS_ASSERT(identity.has(metadata._scheme, metadata._host, metadata._port),
-              "must have a location we recognize by now!");
-  },
-
-  /**
-* Handles responses in case of error, either in the server or in the request.
-*
-* @param e
-* the specific error encountered, which is an HttpError in the case where
-* the request is in some way invalid or cannot be fulfilled; if this isn't
-* an HttpError we're going to be paranoid and shut down, because that
-* shouldn't happen, ever
-*/
-  _handleError: function(e)
-  {
-    // Don't fall back into normal processing!
-    this._state = READER_FINISHED;
-
-    var server = this._connection.server;
-    if (e instanceof HttpError)
-    {
-      var code = e.code;
-    }
-    else
-    {
-      dumpn("!!! UNEXPECTED ERROR: " + e +
-            (e.lineNumber ? ", line " + e.lineNumber : ""));
-
-      // no idea what happened -- be paranoid and shut down
-      code = 500;
-      server._requestQuit();
-    }
-
-    // make attempted reuse of data an error
-    this._data = null;
-
-    this._connection.processError(code, this._metadata);
-  },
-
-  /**
-* Now that we've read the request line and headers, we can actually hand off
-* the request to be handled.
-*
-* This method is called once per request, after the request line and all
-* headers and the body, if any, have been received.
-*/
-  _handleResponse: function()
-  {
-    NS_ASSERT(this._state == READER_FINISHED);
-
-    // We don't need the line-based data any more, so make attempted reuse an
-    // error.
-    this._data = null;
-
-    this._connection.process(this._metadata);
-  },
-
-
-  // PARSING
-
-  /**
-* Parses the request line for the HTTP request associated with this.
-*
-* @param line : string
-* the request line
-*/
-  _parseRequestLine: function(line)
-  {
-    NS_ASSERT(this._state == READER_IN_REQUEST_LINE);
-
-    dumpn("*** _parseRequestLine('" + line + "')");
-
-    var metadata = this._metadata;
-
-    // clients and servers SHOULD accept any amount of SP or HT characters
-    // between fields, even though only a single SP is required (section 19.3)
-    var request = line.split(/[ \t]+/);
-    if (!request || request.length != 3)
-      throw HTTP_400;
-
-    metadata._method = request[0];
-
-    // get the HTTP version
-    var ver = request[2];
-    var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
-    if (!match)
-      throw HTTP_400;
-
-    // determine HTTP version
-    try
-    {
-      metadata._httpVersion = new nsHttpVersion(match[1]);
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
-        throw "unsupported HTTP version";
-    }
-    catch (e)
-    {
-      // we support HTTP/1.0 and HTTP/1.1 only
-      throw HTTP_501;
-    }
-
-
-    var fullPath = request[1];
-    var serverIdentity = this._connection.server.identity;
-
-    var scheme, host, port;
-
-    if (fullPath.charAt(0) != "/")
-    {
-      // No absolute paths in the request line in HTTP prior to 1.1
-      if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
-        throw HTTP_400;
-
-      try
-      {
-        var uri = Cc["@mozilla.org/network/io-service;1"]
-                    .getService(Ci.nsIIOService)
-                    .newURI(fullPath);
-        fullPath = uri.pathQueryRef;
-        scheme = uri.scheme;
-        host = metadata._host = uri.asciiHost;
-        port = uri.port;
-        if (port === -1)
-        {
-          if (scheme === "http")
-            port = 80;
-          else if (scheme === "https")
-            port = 443;
-          else
-            throw HTTP_400;
-        }
-      }
-      catch (e)
-      {
-        // If the host is not a valid host on the server, the response MUST be a
-        // 400 (Bad Request) error message (section 5.2). Alternately, the URI
-        // is malformed.
-        throw HTTP_400;
-      }
-
-      if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
-        throw HTTP_400;
-    }
-
-    var splitter = fullPath.indexOf("?");
-    if (splitter < 0)
-    {
-      // _queryString already set in ctor
-      metadata._path = fullPath;
-    }
-    else
-    {
-      metadata._path = fullPath.substring(0, splitter);
-      metadata._queryString = fullPath.substring(splitter + 1);
-    }
-
-    metadata._scheme = scheme;
-    metadata._host = host;
-    metadata._port = port;
-  },
-
-  /**
-* Parses all available HTTP headers in this until the header-ending CRLFCRLF,
-* adding them to the store of headers in the request.
-*
-* @throws
-* HTTP_400 if the headers are malformed
-* @returns boolean
-* true if all headers have now been processed, false otherwise
-*/
-  _parseHeaders: function()
-  {
-    NS_ASSERT(this._state == READER_IN_HEADERS);
-
-    dumpn("*** _parseHeaders");
-
-    var data = this._data;
-
-    var headers = this._metadata._headers;
-    var lastName = this._lastHeaderName;
-    var lastVal = this._lastHeaderValue;
-
-    var line = {};
-    while (true)
-    {
-      NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
-                lastName === undefined ?
-                  "lastVal without lastName? lastVal: '" + lastVal + "'" :
-                  "lastName without lastVal? lastName: '" + lastName + "'");
-
-      if (!data.readLine(line))
-      {
-        // save any data we have from the header we might still be processing
-        this._lastHeaderName = lastName;
-        this._lastHeaderValue = lastVal;
-        return false;
-      }
-
-      var lineText = line.value;
-      var firstChar = lineText.charAt(0);
-
-      // blank line means end of headers
-      if (lineText == "")
-      {
-        // we're finished with the previous header
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-        else
-        {
-          // no headers in request -- valid for HTTP/1.0 requests
-        }
-
-        // either way, we're done processing headers
-        this._state = READER_IN_BODY;
-        return true;
-      }
-      else if (firstChar == " " || firstChar == "\t")
-      {
-        // multi-line header if we've already seen a header line
-        if (!lastName)
-        {
-          // we don't have a header to continue!
-          throw HTTP_400;
-        }
-
-        // append this line's text to the value; starts with SP/HT, so no need
-        // for separating whitespace
-        lastVal += lineText;
-      }
-      else
-      {
-        // we have a new header, so set the old one (if one existed)
-        if (lastName)
-        {
-          try
-          {
-            headers.setHeader(lastName, lastVal, true);
-          }
-          catch (e)
-          {
-            dumpn("*** e == " + e);
-            throw HTTP_400;
-          }
-        }
-
-        var colon = lineText.indexOf(":"); // first colon must be splitter
-        if (colon < 1)
-        {
-          // no colon or missing header field-name
-          throw HTTP_400;
-        }
-
-        // set header name, value (to be set in the next loop, usually)
-        lastName = lineText.substring(0, colon);
-        lastVal = lineText.substring(colon + 1);
-      } // empty, continuation, start of header
-    } // while (true)
-  }
-};
-
-
-/** The character codes for CR and LF. */
-const CR = 0x0D, LF = 0x0A;
-
-/**
-* Calculates the number of characters before the first CRLF pair in array, or
-* -1 if the array contains no CRLF pair.
-*
-* @param array : Array
-* an array of numbers in the range [0, 256), each representing a single
-* character; the first CRLF is the lowest index i where
-* |array[i] == "\r".charCodeAt(0)| and |array[i+1] == "\n".charCodeAt(0)|,
-* if such an |i| exists, and -1 otherwise
-* @returns int
-* the index of the first CRLF if any were present, -1 otherwise
-*/
-function findCRLF(array)
-{
-  for (var i = array.indexOf(CR); i >= 0; i = array.indexOf(CR, i + 1))
-  {
-    if (array[i + 1] == LF)
-      return i;
-  }
-  return -1;
-}
-
-
-/**
-* A container which provides line-by-line access to the arrays of bytes with
-* which it is seeded.
-*/
-function LineData()
-{
-  /** An array of queued bytes from which to get line-based characters. */
-  this._data = [];
-}
-LineData.prototype =
-{
-  /**
-* Appends the bytes in the given array to the internal data cache maintained
-* by this.
-*/
-  appendBytes: function(bytes)
-  {
-    Array.prototype.push.apply(this._data, bytes);
-  },
-
-  /**
-* Removes and returns a line of data, delimited by CRLF, from this.
-*
-* @param out
-* an object whose "value" property will be set to the first line of text
-* present in this, sans CRLF, if this contains a full CRLF-delimited line
-* of text; if this doesn't contain enough data, the value of the property
-* is undefined
-* @returns boolean
-* true if a full line of data could be read from the data in this, false
-* otherwise
-*/
-  readLine: function(out)
-  {
-    var data = this._data;
-    var length = findCRLF(data);
-    if (length < 0)
-      return false;
-
-    //
-    // We have the index of the CR, so remove all the characters, including
-    // CRLF, from the array with splice, and convert the removed array into the
-    // corresponding string, from which we then strip the trailing CRLF.
-    //
-    // Getting the line in this matter acknowledges that substring is an O(1)
-    // operation in SpiderMonkey because strings are immutable, whereas two
-    // splices, both from the beginning of the data, are less likely to be as
-    // cheap as a single splice plus two extra character conversions.
-    //
-    var line = String.fromCharCode.apply(null, data.splice(0, length + 2));
-    out.value = line.substring(0, length);
-
-    return true;
-  },
-
-  /**
-* Removes the bytes currently within this and returns them in an array.
-*
-* @returns Array
-* the bytes within this when this method is called
-*/
-  purge: function()
-  {
-    var data = this._data;
-    this._data = [];
-    return data;
-  }
-};
-
-
-
-/**
-* Creates a request-handling function for an nsIHttpRequestHandler object.
-*/
-function createHandlerFunc(handler)
-{
-  return function(metadata, response) { handler.handle(metadata, response); };
-}
-
-
-/**
-* The default handler for directories; writes an HTML response containing a
-* slightly-formatted directory listing.
-*/
-function defaultIndexHandler(metadata, response)
-{
-  response.setHeader("Content-Type", "text/html", false);
-
-  var path = htmlEscape(decodeURI(metadata.path));
-
-  //
-  // Just do a very basic bit of directory listings -- no need for too much
-  // fanciness, especially since we don't have a style sheet in which we can
-  // stick rules (don't want to pollute the default path-space).
-  //
-
-  var body = '<html>\
-<head>\
-<title>' + path + '</title>\
-</head>\
-<body>\
-<h1>' + path + '</h1>\
-<ol style="list-style-type: none">';
-
-  var directory = metadata.getProperty("directory").QueryInterface(Ci.nsIFile);
-  NS_ASSERT(directory && directory.isDirectory());
-
-  var fileList = [];
-  var files = directory.directoryEntries;
-  while (files.hasMoreElements())
-  {
-    var f = files.getNext().QueryInterface(Ci.nsIFile);
-    var name = f.leafName;
-    if (!f.isHidden() &&
-        (name.charAt(name.length - 1) != HIDDEN_CHAR ||
-         name.charAt(name.length - 2) == HIDDEN_CHAR))
-      fileList.push(f);
-  }
-
-  fileList.sort(fileSort);
-
-  for (var i = 0; i < fileList.length; i++)
-  {
-    var file = fileList[i];
-    try
-    {
-      var name = file.leafName;
-      if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-        name = name.substring(0, name.length - 1);
-      var sep = file.isDirectory() ? "/" : "";
-
-      // Note: using " to delimit the attribute here because encodeURIComponent
-      // passes through '.
-      var item = '<li><a href="' + encodeURIComponent(name) + sep + '">' +
-                   htmlEscape(name) + sep +
-                 '</a></li>';
-
-      body += item;
-    }
-    catch (e) { /* some file system error, ignore the file */ }
-  }
-
-  body += ' </ol>\
-</body>\
-</html>';
-
-  response.bodyOutputStream.write(body, body.length);
-}
-
-/**
-* Sorts a and b (nsIFile objects) into an aesthetically pleasing order.
-*/
-function fileSort(a, b)
-{
-  var dira = a.isDirectory(), dirb = b.isDirectory();
-
-  if (dira && !dirb)
-    return -1;
-  if (dirb && !dira)
-    return 1;
-
-  var namea = a.leafName.toLowerCase(), nameb = b.leafName.toLowerCase();
-  return nameb > namea ? -1 : 1;
-}
-
-
-/**
-* Converts an externally-provided path into an internal path for use in
-* determining file mappings.
-*
-* @param path
-* the path to convert
-* @param encoded
-* true if the given path should be passed through decodeURI prior to
-* conversion
-* @throws URIError
-* if path is incorrectly encoded
-*/
-function toInternalPath(path, encoded)
-{
-  if (encoded)
-    path = decodeURI(path);
-
-  var comps = path.split("/");
-  for (var i = 0, sz = comps.length; i < sz; i++)
-  {
-    var comp = comps[i];
-    if (comp.charAt(comp.length - 1) == HIDDEN_CHAR)
-      comps[i] = comp + HIDDEN_CHAR;
-  }
-  return comps.join("/");
-}
-
-
-/**
-* Adds custom-specified headers for the given file to the given response, if
-* any such headers are specified.
-*
-* @param file
-* the file on the disk which is to be written
-* @param metadata
-* metadata about the incoming request
-* @param response
-* the Response to which any specified headers/data should be written
-* @throws HTTP_500
-* if an error occurred while processing custom-specified headers
-*/
-function maybeAddHeaders(file, metadata, response)
-{
-  var name = file.leafName;
-  if (name.charAt(name.length - 1) == HIDDEN_CHAR)
-    name = name.substring(0, name.length - 1);
-
-  var headerFile = file.parent;
-  headerFile.append(name + HEADERS_SUFFIX);
-
-  if (!headerFile.exists())
-    return;
-
-  const PR_RDONLY = 0x01;
-  var fis = new FileInputStream(headerFile, PR_RDONLY, 0o444,
-                                Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-  try
-  {
-    var lis = new ConverterInputStream(fis, "UTF-8", 1024, 0x0);
-    lis.QueryInterface(Ci.nsIUnicharLineInputStream);
-
-    var line = {value: ""};
-    var more = lis.readLine(line);
-
-    if (!more && line.value == "")
-      return;
-
-
-    // request line
-
-    var status = line.value;
-    if (status.indexOf("HTTP ") == 0)
-    {
-      status = status.substring(5);
-      var space = status.indexOf(" ");
-      var code, description;
-      if (space < 0)
-      {
-        code = status;
-        description = "";
-      }
-      else
-      {
-        code = status.substring(0, space);
-        description = status.substring(space + 1, status.length);
-      }
-
-      response.setStatusLine(metadata.httpVersion, parseInt(code, 10), description);
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-
-    // headers
-    while (more || line.value != "")
-    {
-      var header = line.value;
-      var colon = header.indexOf(":");
-
-      response.setHeader(header.substring(0, colon),
-                         header.substring(colon + 1, header.length),
-                         false); // allow overriding server-set headers
-
-      line.value = "";
-      more = lis.readLine(line);
-    }
-  }
-  catch (e)
-  {
-    dumpn("WARNING: error in headers for " + metadata.path + ": " + e);
-    throw HTTP_500;
-  }
-  finally
-  {
-    fis.close();
-  }
-}
-
-
-/**
-* An object which handles requests for a server, executing default and
-* overridden behaviors as instructed by the code which uses and manipulates it.
-* Default behavior includes the paths / and /trace (diagnostics), with some
-* support for HTTP error pages for various codes and fallback to HTTP 500 if
-* those codes fail for any reason.
-*
-* @param server : nsHttpServer
-* the server in which this handler is being used
-*/
-function ServerHandler(server)
-{
-  // FIELDS
-
-  /**
-* The nsHttpServer instance associated with this handler.
-*/
-  this._server = server;
-
-  /**
-* A FileMap object containing the set of path->nsIFile mappings for
-* all directory mappings set in the server (e.g., "/" for /var/www/html/,
-* "/foo/bar/" for /local/path/, and "/foo/bar/baz/" for /local/path2).
-*
-* Note carefully: the leading and trailing "/" in each path (not file) are
-* removed before insertion to simplify the code which uses this. You have
-* been warned!
-*/
-  this._pathDirectoryMap = new FileMap();
-
-  /**
-* Custom request handlers for the server in which this resides. Path-handler
-* pairs are stored as property-value pairs in this property.
-*
-* @see ServerHandler.prototype._defaultPaths
-*/
-  this._overridePaths = {};
-
-  /**
-* Custom request handlers for the server in which this resides. Prefix-handler
-* pairs are stored as property-value pairs in this property.
-*/
-  this._overridePrefixes = {};
-
-  /**
-* Custom request handlers for the error handlers in the server in which this
-* resides. Path-handler pairs are stored as property-value pairs in this
-* property.
-*
-* @see ServerHandler.prototype._defaultErrors
-*/
-  this._overrideErrors = {};
-
-  /**
-* Maps file extensions to their MIME types in the server, overriding any
-* mapping that might or might not exist in the MIME service.
-*/
-  this._mimeMappings = {};
-
-  /**
-* The default handler for requests for directories, used to serve directories
-* when no index file is present.
-*/
-  this._indexHandler = defaultIndexHandler;
-
-  /** Per-path state storage for the server. */
-  this._state = {};
-
-  /** Entire-server state storage. */
-  this._sharedState = {};
-
-  /** Entire-server state storage for nsISupports values. */
-  this._objectState = {};
-}
-ServerHandler.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Handles a request to this server, responding to the request appropriately
-* and initiating server shutdown if necessary.
-*
-* This method never throws an exception.
-*
-* @param connection : Connection
-* the connection for this request
-*/
-  handleResponse: function(connection)
-  {
-    var request = connection.request;
-    var response = new Response(connection);
-
-    var path = request.path;
-    dumpn("*** path == " + path);
-
-    try
-    {
-      try
-      {
-        if (path in this._overridePaths)
-        {
-          // explicit paths first, then files based on existing directory mappings,
-          // then (if the file doesn't exist) built-in server default paths
-          dumpn("calling override for " + path);
-          this._overridePaths[path](request, response);
-        }
-        else
-        {
-          let longestPrefix = "";
-          for (let prefix in this._overridePrefixes)
-          {
-            if (prefix.length > longestPrefix.length && path.startsWith(prefix))
-            {
-              longestPrefix = prefix;
-            }
-          }
-          if (longestPrefix.length > 0)
-          {
-            dumpn("calling prefix override for " + longestPrefix);
-            this._overridePrefixes[longestPrefix](request, response);
-          }
-          else
-          {
-            this._handleDefault(request, response);
-          }
-        }
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        if (!(e instanceof HttpError))
-        {
-          dumpn("*** unexpected error: e == " + e);
-          throw HTTP_500;
-        }
-        if (e.code !== 404)
-          throw e;
-
-        dumpn("*** default: " + (path in this._defaultPaths));
-
-        response = new Response(connection);
-        if (path in this._defaultPaths)
-          this._defaultPaths[path](request, response);
-        else
-          throw HTTP_404;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort(e);
-        return;
-      }
-
-      var errorCode = "internal";
-
-      try
-      {
-        if (!(e instanceof HttpError))
-          throw e;
-
-        errorCode = e.code;
-        dumpn("*** errorCode == " + errorCode);
-
-        response = new Response(connection);
-        if (e.customErrorHandling)
-          e.customErrorHandling(response);
-        this._handleError(errorCode, request, response);
-        return;
-      }
-      catch (e2)
-      {
-        dumpn("*** error handling " + errorCode + " error: " +
-              "e2 == " + e2 + ", shutting down server");
-
-        connection.server._requestQuit();
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  //
-  // see nsIHttpServer.registerFile
-  //
-  registerFile: function(path, file)
-  {
-    if (!file)
-    {
-      dumpn("*** unregistering '" + path + "' mapping");
-      delete this._overridePaths[path];
-      return;
-    }
-
-    dumpn("*** registering '" + path + "' as mapping to " + file.path);
-    file = file.clone();
-
-    var self = this;
-    this._overridePaths[path] =
-      function(request, response)
-      {
-        if (!file.exists())
-          throw HTTP_404;
-
-        response.setStatusLine(request.httpVersion, 200, "OK");
-        self._writeFileResponse(request, file, response, 0, file.fileSize);
-      };
-  },
-
-  //
-  // see nsIHttpServer.registerPathHandler
-  //
-  registerPathHandler: function(path, handler)
-  {
-    // XXX true path validation!
-    if (path.charAt(0) != "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePaths, path);
-  },
-
-  //
-  // see nsIHttpServer.registerPrefixHandler
-  //
-  registerPrefixHandler: function(prefix, handler)
-  {
-    // XXX true prefix validation!
-    if (!(prefix.startsWith("/") && prefix.endsWith("/")))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    this._handlerToField(handler, this._overridePrefixes, prefix);
-  },
-
-  //
-  // see nsIHttpServer.registerDirectory
-  //
-  registerDirectory: function(path, directory)
-  {
-    // strip off leading and trailing '/' so that we can use lastIndexOf when
-    // determining exactly how a path maps onto a mapped directory --
-    // conditional is required here to deal with "/".substring(1, 0) being
-    // converted to "/".substring(0, 1) per the JS specification
-    var key = path.length == 1 ? "" : path.substring(1, path.length - 1);
-
-    // the path-to-directory mapping code requires that the first character not
-    // be "/", or it will go into an infinite loop
-    if (key.charAt(0) == "/")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    key = toInternalPath(key, false);
-
-    if (directory)
-    {
-      dumpn("*** mapping '" + path + "' to the location " + directory.path);
-      this._pathDirectoryMap.put(key, directory);
-    }
-    else
-    {
-      dumpn("*** removing mapping for '" + path + "'");
-      this._pathDirectoryMap.put(key, null);
-    }
-  },
-
-  //
-  // see nsIHttpServer.registerErrorHandler
-  //
-  registerErrorHandler: function(err, handler)
-  {
-    if (!(err in HTTP_ERROR_CODES))
-      dumpn("*** WARNING: registering non-HTTP/1.1 error code " +
-            "(" + err + ") handler -- was this intentional?");
-
-    this._handlerToField(handler, this._overrideErrors, err);
-  },
-
-  //
-  // see nsIHttpServer.setIndexHandler
-  //
-  setIndexHandler: function(handler)
-  {
-    if (!handler)
-      handler = defaultIndexHandler;
-    else if (typeof(handler) != "function")
-      handler = createHandlerFunc(handler);
-
-    this._indexHandler = handler;
-  },
-
-  //
-  // see nsIHttpServer.registerContentType
-  //
-  registerContentType: function(ext, type)
-  {
-    if (!type)
-      delete this._mimeMappings[ext];
-    else
-      this._mimeMappings[ext] = headerUtils.normalizeFieldValue(type);
-  },
-
-  // PRIVATE API
-
-  /**
-* Sets or remove (if handler is null) a handler in an object with a key.
-*
-* @param handler
-* a handler, either function or an nsIHttpRequestHandler
-* @param dict
-* The object to attach the handler to.
-* @param key
-* The field name of the handler.
-*/
-  _handlerToField: function(handler, dict, key)
-  {
-    // for convenience, handler can be a function if this is run from xpcshell
-    if (typeof(handler) == "function")
-      dict[key] = handler;
-    else if (handler)
-      dict[key] = createHandlerFunc(handler);
-    else
-      delete dict[key];
-  },
-
-  /**
-* Handles a request which maps to a file in the local filesystem (if a base
-* path has already been set; otherwise the 404 error is thrown).
-*
-* @param metadata : Request
-* metadata for the incoming request
-* @param response : Response
-* an uninitialized Response to the given request, to be initialized by a
-* request handler
-* @throws HTTP_###
-* if an HTTP error occurred (usually HTTP_404); note that in this case the
-* calling code must handle post-processing of the response
-*/
-  _handleDefault: function(metadata, response)
-  {
-    dumpn("*** _handleDefault()");
-
-    response.setStatusLine(metadata.httpVersion, 200, "OK");
-
-    var path = metadata.path;
-    NS_ASSERT(path.charAt(0) == "/", "invalid path: <" + path + ">");
-
-    // determine the actual on-disk file; this requires finding the deepest
-    // path-to-directory mapping in the requested URL
-    var file = this._getFileForPath(path);
-
-    // the "file" might be a directory, in which case we either serve the
-    // contained index.html or make the index handler write the response
-    if (file.exists() && file.isDirectory())
-    {
-      file.append("index.html"); // make configurable?
-      if (!file.exists() || file.isDirectory())
-      {
-        metadata._ensurePropertyBag();
-        metadata._bag.setPropertyAsInterface("directory", file.parent);
-        this._indexHandler(metadata, response);
-        return;
-      }
-    }
-
-    // alternately, the file might not exist
-    if (!file.exists())
-      throw HTTP_404;
-
-    var start, end;
-    if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
-        metadata.hasHeader("Range") &&
-        this._getTypeFromFile(file) !== SJS_TYPE)
-    {
-      var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
-      if (!rangeMatch)
-        throw HTTP_400;
-
-      if (rangeMatch[1] !== undefined)
-        start = parseInt(rangeMatch[1], 10);
-
-      if (rangeMatch[2] !== undefined)
-        end = parseInt(rangeMatch[2], 10);
-
-      if (start === undefined && end === undefined)
-        throw HTTP_400;
-
-      // No start given, so the end is really the count of bytes from the
-      // end of the file.
-      if (start === undefined)
-      {
-        start = Math.max(0, file.fileSize - end);
-        end = file.fileSize - 1;
-      }
-
-      // start and end are inclusive
-      if (end === undefined || end >= file.fileSize)
-        end = file.fileSize - 1;
-
-      if (start !== undefined && start >= file.fileSize) {
-        var HTTP_416 = new HttpError(416, "Requested Range Not Satisfiable");
-        HTTP_416.customErrorHandling = function(errorResponse)
-        {
-          maybeAddHeaders(file, metadata, errorResponse);
-        };
-        throw HTTP_416;
-      }
-
-      if (end < start)
-      {
-        response.setStatusLine(metadata.httpVersion, 200, "OK");
-        start = 0;
-        end = file.fileSize - 1;
-      }
-      else
-      {
-        response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
-        var contentRange = "bytes " + start + "-" + end + "/" + file.fileSize;
-        response.setHeader("Content-Range", contentRange);
-      }
-    }
-    else
-    {
-      start = 0;
-      end = file.fileSize - 1;
-    }
-
-    // finally...
-    dumpn("*** handling '" + path + "' as mapping to " + file.path + " from " +
-          start + " to " + end + " inclusive");
-    this._writeFileResponse(metadata, file, response, start, end - start + 1);
-  },
-
-  /**
-* Writes an HTTP response for the given file, including setting headers for
-* file metadata.
-*
-* @param metadata : Request
-* the Request for which a response is being generated
-* @param file : nsIFile
-* the file which is to be sent in the response
-* @param response : Response
-* the response to which the file should be written
-* @param offset: uint
-* the byte offset to skip to when writing
-* @param count: uint
-* the number of bytes to write
-*/
-  _writeFileResponse: function(metadata, file, response, offset, count)
-  {
-    const PR_RDONLY = 0x01;
-
-    var type = this._getTypeFromFile(file);
-    if (type === SJS_TYPE)
-    {
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      try
-      {
-        var sis = new ScriptableInputStream(fis);
-        var s = Cu.Sandbox(gGlobalObject);
-        s.importFunction(dump, "dump");
-
-        // Define a basic key-value state-preservation API across requests, with
-        // keys initially corresponding to the empty string.
-        var self = this;
-        var path = metadata.path;
-        s.importFunction(function getState(k)
-        {
-          return self._getState(path, k);
-        });
-        s.importFunction(function setState(k, v)
-        {
-          self._setState(path, k, v);
-        });
-        s.importFunction(function getSharedState(k)
-        {
-          return self._getSharedState(k);
-        });
-        s.importFunction(function setSharedState(k, v)
-        {
-          self._setSharedState(k, v);
-        });
-        s.importFunction(function getObjectState(k, callback)
-        {
-          callback(self._getObjectState(k));
-        });
-        s.importFunction(function setObjectState(k, v)
-        {
-          self._setObjectState(k, v);
-        });
-        s.importFunction(function registerPathHandler(p, h)
-        {
-          self.registerPathHandler(p, h);
-        });
-
-        // Make it possible for sjs files to access their location
-        this._setState(path, "__LOCATION__", file.path);
-
-        try
-        {
-          // Alas, the line number in errors dumped to console when calling the
-          // request handler is simply an offset from where we load the SJS file.
-          // Work around this in a reasonably non-fragile way by dynamically
-          // getting the line number where we evaluate the SJS file. Don't
-          // separate these two lines!
-          var line = new Error().lineNumber;
-          Cu.evalInSandbox(sis.read(file.fileSize), s);
-        }
-        catch (e)
-        {
-          dumpn("*** syntax error in SJS at " + file.path + ": " + e);
-          throw HTTP_500;
-        }
-
-        try
-        {
-          s.handleRequest(metadata, response);
-        }
-        catch (e)
-        {
-          dump("*** error running SJS at " + file.path + ": " +
-               e + " on line " +
-               (e instanceof Error
-               ? e.lineNumber + " in httpd.js"
-               : (e.lineNumber - line)) + "\n");
-          throw HTTP_500;
-        }
-      }
-      finally
-      {
-        fis.close();
-      }
-    }
-    else
-    {
-      try
-      {
-        response.setHeader("Last-Modified",
-                           toDateString(file.lastModifiedTime),
-                           false);
-      }
-      catch (e) { /* lastModifiedTime threw, ignore */ }
-
-      response.setHeader("Content-Type", type, false);
-      maybeAddHeaders(file, metadata, response);
-      response.setHeader("Content-Length", "" + count, false);
-
-      var fis = new FileInputStream(file, PR_RDONLY, 0o444,
-                                    Ci.nsIFileInputStream.CLOSE_ON_EOF);
-
-      offset = offset || 0;
-      count = count || file.fileSize;
-      NS_ASSERT(offset === 0 || offset < file.fileSize, "bad offset");
-      NS_ASSERT(count >= 0, "bad count");
-      NS_ASSERT(offset + count <= file.fileSize, "bad total data size");
-
-      try
-      {
-        if (offset !== 0)
-        {
-          // Seek (or read, if seeking isn't supported) to the correct offset so
-          // the data sent to the client matches the requested range.
-          if (fis instanceof Ci.nsISeekableStream)
-            fis.seek(Ci.nsISeekableStream.NS_SEEK_SET, offset);
-          else
-            new ScriptableInputStream(fis).read(offset);
-        }
-      }
-      catch (e)
-      {
-        fis.close();
-        throw e;
-      }
-
-      let writeMore = function writeMore()
-      {
-        gThreadManager.dispatchToMainThread(writeData);
-      }
-
-      var input = new BinaryInputStream(fis);
-      var output = new BinaryOutputStream(response.bodyOutputStream);
-      var writeData =
-        {
-          run: function()
-          {
-            var chunkSize = Math.min(65536, count);
-            count -= chunkSize;
-            NS_ASSERT(count >= 0, "underflow");
-
-            try
-            {
-              var data = input.readByteArray(chunkSize);
-              NS_ASSERT(data.length === chunkSize,
-                        "incorrect data returned? got " + data.length +
-                        ", expected " + chunkSize);
-              output.writeByteArray(data, data.length);
-              if (count === 0)
-              {
-                fis.close();
-                response.finish();
-              }
-              else
-              {
-                writeMore();
-              }
-            }
-            catch (e)
-            {
-              try
-              {
-                fis.close();
-              }
-              finally
-              {
-                response.finish();
-              }
-              throw e;
-            }
-          }
-        };
-
-      writeMore();
-
-      // Now that we know copying will start, flag the response as async.
-      response.processAsync();
-    }
-  },
-
-  /**
-* Get the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getState: function(path, k)
-  {
-    var state = this._state;
-    if (path in state && k in state[path])
-      return state[path][k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for the given path for SJS state
-* preservation across requests.
-*
-* @param path : string
-* the path from which the given state is to be retrieved
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setState: function(path, k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    var state = this._state;
-    if (!(path in state))
-      state[path] = {};
-    state[path][k] = v;
-  },
-
-  /**
-* Get the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be returned
-* @returns string
-* the corresponding value, which is initially the empty string
-*/
-  _getSharedState: function(k)
-  {
-    var state = this._sharedState;
-    if (k in state)
-      return state[k];
-    return "";
-  },
-
-  /**
-* Set the value corresponding to a given key for SJS state preservation
-* across requests.
-*
-* @param k : string
-* the key whose corresponding value is to be set
-* @param v : string
-* the value to be set
-*/
-  _setSharedState: function(k, v)
-  {
-    if (typeof v !== "string")
-      throw new Error("non-string value passed");
-    this._sharedState[k] = v;
-  },
-
-  /**
-* Returns the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be returned
-* @returns nsISupports
-* the corresponding object, or null if none was present
-*/
-  _getObjectState: function(k)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    return this._objectState[k] || null;
-  },
-
-  /**
-* Sets the object associated with the given key in the server for SJS
-* state preservation across requests.
-*
-* @param k : string
-* the key whose corresponding object is to be set
-* @param v : nsISupports
-* the object to be associated with the given key; may be null
-*/
-  _setObjectState: function(k, v)
-  {
-    if (typeof k !== "string")
-      throw new Error("non-string key passed");
-    if (typeof v !== "object")
-      throw new Error("non-object value passed");
-    if (v && !("QueryInterface" in v))
-    {
-      throw new Error("must pass an nsISupports; use wrappedJSObject to ease " +
-                      "pain when using the server from JS");
-    }
-
-    this._objectState[k] = v;
-  },
-
-  /**
-* Gets a content-type for the given file, first by checking for any custom
-* MIME-types registered with this handler for the file's extension, second by
-* asking the global MIME service for a content-type, and finally by failing
-* over to application/octet-stream.
-*
-* @param file : nsIFile
-* the nsIFile for which to get a file type
-* @returns string
-* the best content-type which can be determined for the file
-*/
-  _getTypeFromFile: function(file)
-  {
-    try
-    {
-      var name = file.leafName;
-      var dot = name.lastIndexOf(".");
-      if (dot > 0)
-      {
-        var ext = name.slice(dot + 1);
-        if (ext in this._mimeMappings)
-          return this._mimeMappings[ext];
-      }
-      return Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
-               .getService(Ci.nsIMIMEService)
-               .getTypeFromFile(file);
-    }
-    catch (e)
-    {
-      return "application/octet-stream";
-    }
-  },
-
-  /**
-* Returns the nsIFile which corresponds to the path, as determined using
-* all registered path->directory mappings and any paths which are explicitly
-* overridden.
-*
-* @param path : string
-* the server path for which a file should be retrieved, e.g. "/foo/bar"
-* @throws HttpError
-* when the correct action is the corresponding HTTP error (i.e., because no
-* mapping was found for a directory in path, the referenced file doesn't
-* exist, etc.)
-* @returns nsIFile
-* the file to be sent as the response to a request for the path
-*/
-  _getFileForPath: function(path)
-  {
-    // decode and add underscores as necessary
-    try
-    {
-      path = toInternalPath(path, true);
-    }
-    catch (e)
-    {
-      throw HTTP_400; // malformed path
-    }
-
-    // next, get the directory which contains this path
-    var pathMap = this._pathDirectoryMap;
-
-    // An example progression of tmp for a path "/foo/bar/baz/" might be:
-    // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
-    var tmp = path.substring(1);
-    while (true)
-    {
-      // do we have a match for current head of the path?
-      var file = pathMap.get(tmp);
-      if (file)
-      {
-        // XXX hack; basically disable showing mapping for /foo/bar/ when the
-        // requested path was /foo/bar, because relative links on the page
-        // will all be incorrect -- we really need the ability to easily
-        // redirect here instead
-        if (tmp == path.substring(1) &&
-            tmp.length != 0 &&
-            tmp.charAt(tmp.length - 1) != "/")
-          file = null;
-        else
-          break;
-      }
-
-      // if we've finished trying all prefixes, exit
-      if (tmp == "")
-        break;
-
-      tmp = tmp.substring(0, tmp.lastIndexOf("/"));
-    }
-
-    // no mapping applies, so 404
-    if (!file)
-      throw HTTP_404;
-
-
-    // last, get the file for the path within the determined directory
-    var parentFolder = file.parent;
-    var dirIsRoot = (parentFolder == null);
-
-    // Strategy here is to append components individually, making sure we
-    // never move above the given directory; this allows paths such as
-    // "<file>/foo/../bar" but prevents paths such as "<file>/../base-sibling";
-    // this component-wise approach also means the code works even on platforms
-    // which don't use "/" as the directory separator, such as Windows
-    var leafPath = path.substring(tmp.length + 1);
-    var comps = leafPath.split("/");
-    for (var i = 0, sz = comps.length; i < sz; i++)
-    {
-      var comp = comps[i];
-
-      if (comp == "..")
-        file = file.parent;
-      else if (comp == "." || comp == "")
-        continue;
-      else
-        file.append(comp);
-
-      if (!dirIsRoot && file.equals(parentFolder))
-        throw HTTP_403;
-    }
-
-    return file;
-  },
-
-  /**
-* Writes the error page for the given HTTP error code over the given
-* connection.
-*
-* @param errorCode : uint
-* the HTTP error code to be used
-* @param connection : Connection
-* the connection on which the error occurred
-*/
-  handleError: function(errorCode, connection)
-  {
-    var response = new Response(connection);
-
-    dumpn("*** error in request: " + errorCode);
-
-    this._handleError(errorCode, new Request(connection.port), response);
-  },
-
-  /**
-* Handles a request which generates the given error code, using the
-* user-defined error handler if one has been set, gracefully falling back to
-* the x00 status code if the code has no handler, and failing to status code
-* 500 if all else fails.
-*
-* @param errorCode : uint
-* the HTTP error which is to be returned
-* @param metadata : Request
-* metadata for the request, which will often be incomplete since this is an
-* error
-* @param response : Response
-* an uninitialized Response should be initialized when this method
-* completes with information which represents the desired error code in the
-* ideal case or a fallback code in abnormal circumstances (i.e., 500 is a
-* fallback for 505, per HTTP specs)
-*/
-  _handleError: function(errorCode, metadata, response)
-  {
-    if (!metadata)
-      throw Cr.NS_ERROR_NULL_POINTER;
-
-    var errorX00 = errorCode - (errorCode % 100);
-
-    try
-    {
-      if (!(errorCode in HTTP_ERROR_CODES))
-        dumpn("*** WARNING: requested invalid error: " + errorCode);
-
-      // RFC 2616 says that we should try to handle an error by its class if we
-      // can't otherwise handle it -- if that fails, we revert to handling it as
-      // a 500 internal server error, and if that fails we throw and shut down
-      // the server
-
-      // actually handle the error
-      try
-      {
-        if (errorCode in this._overrideErrors)
-          this._overrideErrors[errorCode](metadata, response);
-        else
-          this._defaultErrors[errorCode](metadata, response);
-      }
-      catch (e)
-      {
-        if (response.partiallySent())
-        {
-          response.abort(e);
-          return;
-        }
-
-        // don't retry the handler that threw
-        if (errorX00 == errorCode)
-          throw HTTP_500;
-
-        dumpn("*** error in handling for error code " + errorCode + ", " +
-              "falling back to " + errorX00 + "...");
-        response = new Response(response._connection);
-        if (errorX00 in this._overrideErrors)
-          this._overrideErrors[errorX00](metadata, response);
-        else if (errorX00 in this._defaultErrors)
-          this._defaultErrors[errorX00](metadata, response);
-        else
-          throw HTTP_500;
-      }
-    }
-    catch (e)
-    {
-      if (response.partiallySent())
-      {
-        response.abort();
-        return;
-      }
-
-      // we've tried everything possible for a meaningful error -- now try 500
-      dumpn("*** error in handling for error code " + errorX00 + ", falling " +
-            "back to 500...");
-
-      try
-      {
-        response = new Response(response._connection);
-        if (500 in this._overrideErrors)
-          this._overrideErrors[500](metadata, response);
-        else
-          this._defaultErrors[500](metadata, response);
-      }
-      catch (e2)
-      {
-        dumpn("*** multiple errors in default error handlers!");
-        dumpn("*** e == " + e + ", e2 == " + e2);
-        response.abort(e2);
-        return;
-      }
-    }
-
-    response.complete();
-  },
-
-  // FIELDS
-
-  /**
-* This object contains the default handlers for the various HTTP error codes.
-*/
-  _defaultErrors:
-  {
-    400: function(metadata, response)
-    {
-      // none of the data in metadata is reliable, so hard-code everything here
-      response.setStatusLine("1.1", 400, "Bad Request");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Bad request\n";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    403: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 403, "Forbidden");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>403 Forbidden</title></head>\
-<body>\
-<h1>403 Forbidden</h1>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    404: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 404, "Not Found");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>404 Not Found</title></head>\
-<body>\
-<h1>404 Not Found</h1>\
-<p>\
-<span style='font-family: monospace;'>" +
-                          htmlEscape(metadata.path) +
-                       "</span> was not found.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    416: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                            416,
-                            "Requested Range Not Satisfiable");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head>\
-<title>416 Requested Range Not Satisfiable</title></head>\
-<body>\
-<h1>416 Requested Range Not Satisfiable</h1>\
-<p>The byte range was not valid for the\
-requested resource.\
-</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    500: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion,
-                             500,
-                             "Internal Server Error");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>500 Internal Server Error</title></head>\
-<body>\
-<h1>500 Internal Server Error</h1>\
-<p>Something's broken in this server and\
-needs to be fixed.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    501: function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 501, "Not Implemented");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>501 Not Implemented</title></head>\
-<body>\
-<h1>501 Not Implemented</h1>\
-<p>This server is not (yet) Apache.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    },
-    505: function(metadata, response)
-    {
-      response.setStatusLine("1.1", 505, "HTTP Version Not Supported");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>505 HTTP Version Not Supported</title></head>\
-<body>\
-<h1>505 HTTP Version Not Supported</h1>\
-<p>This server only supports HTTP/1.0 and HTTP/1.1\
-connections.</p>\
-</body>\
-</html>";
-      response.bodyOutputStream.write(body, body.length);
-    }
-  },
-
-  /**
-* Contains handlers for the default set of URIs contained in this server.
-*/
-  _defaultPaths:
-  {
-    "/": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/html", false);
-
-      var body = "<html>\
-<head><title>httpd.js</title></head>\
-<body>\
-<h1>httpd.js</h1>\
-<p>If you're seeing this page, httpd.js is up and\
-serving requests! Now set a base path and serve some\
-files!</p>\
-</body>\
-</html>";
-
-      response.bodyOutputStream.write(body, body.length);
-    },
-
-    "/trace": function(metadata, response)
-    {
-      response.setStatusLine(metadata.httpVersion, 200, "OK");
-      response.setHeader("Content-Type", "text/plain", false);
-
-      var body = "Request-URI: " +
-                 metadata.scheme + "://" + metadata.host + ":" + metadata.port +
-                 metadata.path + "\n\n";
-      body += "Request (semantically equivalent, slightly reformatted):\n\n";
-      body += metadata.method + " " + metadata.path;
-
-      if (metadata.queryString)
-        body += "?" + metadata.queryString;
-
-      body += " HTTP/" + metadata.httpVersion + "\r\n";
-
-      var headEnum = metadata.headers;
-      while (headEnum.hasMoreElements())
-      {
-        var fieldName = headEnum.getNext()
-                                .QueryInterface(Ci.nsISupportsString)
-                                .data;
-        body += fieldName + ": " + metadata.getHeader(fieldName) + "\r\n";
-      }
-
-      response.bodyOutputStream.write(body, body.length);
-    }
-  }
-};
-
-
-/**
-* Maps absolute paths to files on the local file system (as nsILocalFiles).
-*/
-function FileMap()
-{
-  /** Hash which will map paths to nsILocalFiles. */
-  this._map = {};
-}
-FileMap.prototype =
-{
-  // PUBLIC API
-
-  /**
-* Maps key to a clone of the nsIFile value if value is non-null;
-* otherwise, removes any extant mapping for key.
-*
-* @param key : string
-* string to which a clone of value is mapped
-* @param value : nsIFile
-* the file to map to key, or null to remove a mapping
-*/
-  put: function(key, value)
-  {
-    if (value)
-      this._map[key] = value.clone();
-    else
-      delete this._map[key];
-  },
-
-  /**
-* Returns a clone of the nsIFile mapped to key, or null if no such
-* mapping exists.
-*
-* @param key : string
-* key to which the returned file maps
-* @returns nsIFile
-* a clone of the mapped file, or null if no mapping exists
-*/
-  get: function(key)
-  {
-    var val = this._map[key];
-    return val ? val.clone() : null;
-  }
-};
-
-
-// Response CONSTANTS
-
-// token = *<any CHAR except CTLs or separators>
-// CHAR = <any US-ASCII character (0-127)>
-// CTL = <any US-ASCII control character (0-31) and DEL (127)>
-// separators = "(" | ")" | "<" | ">" | "@"
-// | "," | ";" | ":" | "\" | <">
-// | "/" | "[" | "]" | "?" | "="
-// | "{" | "}" | SP | HT
-const IS_TOKEN_ARRAY =
-  [0, 0, 0, 0, 0, 0, 0, 0, // 0
-   0, 0, 0, 0, 0, 0, 0, 0, // 8
-   0, 0, 0, 0, 0, 0, 0, 0, // 16
-   0, 0, 0, 0, 0, 0, 0, 0, // 24
-
-   0, 1, 0, 1, 1, 1, 1, 1, // 32
-   0, 0, 1, 1, 0, 1, 1, 0, // 40
-   1, 1, 1, 1, 1, 1, 1, 1, // 48
-   1, 1, 0, 0, 0, 0, 0, 0, // 56
-
-   0, 1, 1, 1, 1, 1, 1, 1, // 64
-   1, 1, 1, 1, 1, 1, 1, 1, // 72
-   1, 1, 1, 1, 1, 1, 1, 1, // 80
-   1, 1, 1, 0, 0, 0, 1, 1, // 88
-
-   1, 1, 1, 1, 1, 1, 1, 1, // 96
-   1, 1, 1, 1, 1, 1, 1, 1, // 104
-   1, 1, 1, 1, 1, 1, 1, 1, // 112
-   1, 1, 1, 0, 1, 0, 1]; // 120
-
-
-/**
-* Determines whether the given character code is a CTL.
-*
-* @param code : uint
-* the character code
-* @returns boolean
-* true if code is a CTL, false otherwise
-*/
-function isCTL(code)
-{
-  return (code >= 0 && code <= 31) || (code == 127);
-}
-
-/**
-* Represents a response to an HTTP request, encapsulating all details of that
-* response. This includes all headers, the HTTP version, status code and
-* explanation, and the entity itself.
-*
-* @param connection : Connection
-* the connection over which this response is to be written
-*/
-function Response(connection)
-{
-  /** The connection over which this response will be written. */
-  this._connection = connection;
-
-  /**
-* The HTTP version of this response; defaults to 1.1 if not set by the
-* handler.
-*/
-  this._httpVersion = nsHttpVersion.HTTP_1_1;
-
-  /**
-* The HTTP code of this response; defaults to 200.
-*/
-  this._httpCode = 200;
-
-  /**
-* The description of the HTTP code in this response; defaults to "OK".
-*/
-  this._httpDescription = "OK";
-
-  /**
-* An nsIHttpHeaders object in which the headers in this response should be
-* stored. This property is null after the status line and headers have been
-* written to the network, and it may be modified up until it is cleared,
-* except if this._finished is set first (in which case headers are written
-* asynchronously in response to a finish() call not preceded by
-* flushHeaders()).
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* Set to true when this response is ended (completely constructed if possible
-* and the connection closed); further actions on this will then fail.
-*/
-  this._ended = false;
-
-  /**
-* A stream used to hold data written to the body of this response.
-*/
-  this._bodyOutputStream = null;
-
-  /**
-* A stream containing all data that has been written to the body of this
-* response so far. (Async handlers make the data contained in this
-* unreliable as a way of determining content length in general, but auxiliary
-* saved information can sometimes be used to guarantee reliability.)
-*/
-  this._bodyInputStream = null;
-
-  /**
-* A stream copier which copies data to the network. It is initially null
-* until replaced with a copier for response headers; when headers have been
-* fully sent it is replaced with a copier for the response body, remaining
-* so for the duration of response processing.
-*/
-  this._asyncCopier = null;
-
-  /**
-* True if this response has been designated as being processed
-* asynchronously rather than for the duration of a single call to
-* nsIHttpRequestHandler.handle.
-*/
-  this._processAsync = false;
-
-  /**
-* True iff finish() has been called on this, signaling that no more changes
-* to this may be made.
-*/
-  this._finished = false;
-
-  /**
-* True iff powerSeized() has been called on this, signaling that this
-* response is to be handled manually by the response handler (which may then
-* send arbitrary data in response, even non-HTTP responses).
-*/
-  this._powerSeized = false;
-}
-Response.prototype =
-{
-  // PUBLIC CONSTRUCTION API
-
-  //
-  // see nsIHttpResponse.bodyOutputStream
-  //
-  get bodyOutputStream()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    if (!this._bodyOutputStream)
-    {
-      var pipe = new Pipe(true, false, Response.SEGMENT_SIZE, PR_UINT32_MAX,
-                          null);
-      this._bodyOutputStream = pipe.outputStream;
-      this._bodyInputStream = pipe.inputStream;
-      if (this._processAsync || this._powerSeized)
-        this._startAsyncProcessor();
-    }
-
-    return this._bodyOutputStream;
-  },
-
-  //
-  // see nsIHttpResponse.write
-  //
-  write: function(data)
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    var dataAsString = String(data);
-    this.bodyOutputStream.write(dataAsString, dataAsString.length);
-  },
-
-  //
-  // see nsIHttpResponse.setStatusLine
-  //
-  setStatusLine: function(httpVersion, code, description)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    if (!(code >= 0 && code < 1000))
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    try
-    {
-      var httpVer;
-      // avoid version construction for the most common cases
-      if (!httpVersion || httpVersion == "1.1")
-        httpVer = nsHttpVersion.HTTP_1_1;
-      else if (httpVersion == "1.0")
-        httpVer = nsHttpVersion.HTTP_1_0;
-      else
-        httpVer = new nsHttpVersion(httpVersion);
-    }
-    catch (e)
-    {
-      throw Cr.NS_ERROR_INVALID_ARG;
-    }
-
-    // Reason-Phrase = *<TEXT, excluding CR, LF>
-    // TEXT = <any OCTET except CTLs, but including LWS>
-    //
-    // XXX this ends up disallowing octets which aren't Unicode, I think -- not
-    // much to do if description is IDL'd as string
-    if (!description)
-      description = "";
-    for (var i = 0; i < description.length; i++)
-      if (isCTL(description.charCodeAt(i)) && description.charAt(i) != "\t")
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // set the values only after validation to preserve atomicity
-    this._httpDescription = description;
-    this._httpCode = code;
-    this._httpVersion = httpVer;
-  },
-
-  //
-  // see nsIHttpResponse.setHeader
-  //
-  setHeader: function(name, value, merge)
-  {
-    if (!this._headers || this._finished || this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    this._ensureAlive();
-
-    this._headers.setHeader(name, value, merge);
-  },
-
-  //
-  // see nsIHttpResponse.processAsync
-  //
-  processAsync: function()
-  {
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._processAsync)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** processing connection " + this._connection.number + " async");
-    this._processAsync = true;
-
-    /*
-* Either the bodyOutputStream getter or this method is responsible for
-* starting the asynchronous processor and catching writes of data to the
-* response body of async responses as they happen, for the purpose of
-* forwarding those writes to the actual connection's output stream.
-* If bodyOutputStream is accessed first, calling this method will create
-* the processor (when it first is clear that body data is to be written
-* immediately, not buffered). If this method is called first, accessing
-* bodyOutputStream will create the processor. If only this method is
-* called, we'll write nothing, neither headers nor the nonexistent body,
-* until finish() is called. Since that delay is easily avoided by simply
-* getting bodyOutputStream or calling write(""), we don't worry about it.
-*/
-    if (this._bodyOutputStream && !this._asyncCopier)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.seizePower
-  //
-  seizePower: function()
-  {
-    if (this._processAsync)
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-    if (this._finished)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._powerSeized)
-      return;
-    this._ensureAlive();
-
-    dumpn("*** forcefully seizing power over connection " +
-          this._connection.number + "...");
-
-    // Purge any already-written data without sending it. We could as easily
-    // swap out the streams entirely, but that makes it possible to acquire and
-    // unknowingly use a stale reference, so we require there only be one of
-    // each stream ever for any response to avoid this complication.
-    if (this._asyncCopier)
-      this._asyncCopier.cancel(Cr.NS_BINDING_ABORTED);
-    this._asyncCopier = null;
-    if (this._bodyOutputStream)
-    {
-      var input = new BinaryInputStream(this._bodyInputStream);
-      var avail;
-      while ((avail = input.available()) > 0)
-        input.readByteArray(avail);
-    }
-
-    this._powerSeized = true;
-    if (this._bodyOutputStream)
-      this._startAsyncProcessor();
-  },
-
-  //
-  // see nsIHttpResponse.finish
-  //
-  finish: function()
-  {
-    if (!this._processAsync && !this._powerSeized)
-      throw Cr.NS_ERROR_UNEXPECTED;
-    if (this._finished)
-      return;
-
-    dumpn("*** finishing connection " + this._connection.number);
-    this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-    this._finished = true;
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // POST-CONSTRUCTION API (not exposed externally)
-
-  /**
-* The HTTP version number of this, as a string (e.g. "1.1").
-*/
-  get httpVersion()
-  {
-    this._ensureAlive();
-    return this._httpVersion.toString();
-  },
-
-  /**
-* The HTTP status code of this response, as a string of three characters per
-* RFC 2616.
-*/
-  get httpCode()
-  {
-    this._ensureAlive();
-
-    var codeString = (this._httpCode < 10 ? "0" : "") +
-                     (this._httpCode < 100 ? "0" : "") +
-                     this._httpCode;
-    return codeString;
-  },
-
-  /**
-* The description of the HTTP status code of this response, or "" if none is
-* set.
-*/
-  get httpDescription()
-  {
-    this._ensureAlive();
-
-    return this._httpDescription;
-  },
-
-  /**
-* The headers in this response, as an nsHttpHeaders object.
-*/
-  get headers()
-  {
-    this._ensureAlive();
-
-    return this._headers;
-  },
-
-  //
-  // see nsHttpHeaders.getHeader
-  //
-  getHeader: function(name)
-  {
-    this._ensureAlive();
-
-    return this._headers.getHeader(name);
-  },
-
-  /**
-* Determines whether this response may be abandoned in favor of a newly
-* constructed response. A response may be abandoned only if it is not being
-* sent asynchronously and if raw control over it has not been taken from the
-* server.
-*
-* @returns boolean
-* true iff no data has been written to the network
-*/
-  partiallySent: function()
-  {
-    dumpn("*** partiallySent()");
-    return this._processAsync || this._powerSeized;
-  },
-
-  /**
-* If necessary, kicks off the remaining request processing needed to be done
-* after a request handler performs its initial work upon this response.
-*/
-  complete: function()
-  {
-    dumpn("*** complete()");
-    if (this._processAsync || this._powerSeized)
-    {
-      NS_ASSERT(this._processAsync ^ this._powerSeized,
-                "can't both send async and relinquish power");
-      return;
-    }
-
-    NS_ASSERT(!this.partiallySent(), "completing a partially-sent response?");
-
-    this._startAsyncProcessor();
-
-    // Now make sure we finish processing this request!
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-  },
-
-  /**
-* Abruptly ends processing of this response, usually due to an error in an
-* incoming request but potentially due to a bad error handler. Since we
-* cannot handle the error in the usual way (giving an HTTP error page in
-* response) because data may already have been sent (or because the response
-* might be expected to have been generated asynchronously or completely from
-* scratch by the handler), we stop processing this response and abruptly
-* close the connection.
-*
-* @param e : Error
-* the exception which precipitated this abort, or null if no such exception
-* was generated
-*/
-  abort: function(e)
-  {
-    dumpn("*** abort(<" + e + ">)");
-
-    // This response will be ended by the processor if one was created.
-    var copier = this._asyncCopier;
-    if (copier)
-    {
-      // We dispatch asynchronously here so that any pending writes of data to
-      // the connection will be deterministically written. This makes it easier
-      // to specify exact behavior, and it makes observable behavior more
-      // predictable for clients. Note that the correctness of this depends on
-      // callbacks in response to _waitToReadData in WriteThroughCopier
-      // happening asynchronously with respect to the actual writing of data to
-      // bodyOutputStream, as they currently do; if they happened synchronously,
-      // an event which ran before this one could write more data to the
-      // response body before we get around to canceling the copier. We have
-      // tests for this in test_seizepower.js, however, and I can't think of a
-      // way to handle both cases without removing bodyOutputStream access and
-      // moving its effective write(data, length) method onto Response, which
-      // would be slower and require more code than this anyway.
-      gThreadManager.dispatchToMainThread({
-        run: function()
-        {
-          dumpn("*** canceling copy asynchronously...");
-          copier.cancel(Cr.NS_ERROR_UNEXPECTED);
-        }
-      });
-    }
-    else
-    {
-      this.end();
-    }
-  },
-
-  /**
-* Closes this response's network connection, marks the response as finished,
-* and notifies the server handler that the request is done being processed.
-*/
-  end: function()
-  {
-    NS_ASSERT(!this._ended, "ending this response twice?!?!");
-
-    this._connection.close();
-    if (this._bodyOutputStream)
-      this._bodyOutputStream.close();
-
-    this._finished = true;
-    this._ended = true;
-  },
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Sends the status line and headers of this response if they haven't been
-* sent and initiates the process of copying data written to this response's
-* body to the network.
-*/
-  _startAsyncProcessor: function()
-  {
-    dumpn("*** _startAsyncProcessor()");
-
-    // Handle cases where we're being called a second time. The former case
-    // happens when this is triggered both by complete() and by processAsync(),
-    // while the latter happens when processAsync() in conjunction with sent
-    // data causes abort() to be called.
-    if (this._asyncCopier || this._ended)
-    {
-      dumpn("*** ignoring second call to _startAsyncProcessor");
-      return;
-    }
-
-    // Send headers if they haven't been sent already and should be sent, then
-    // asynchronously continue to send the body.
-    if (this._headers && !this._powerSeized)
-    {
-      this._sendHeaders();
-      return;
-    }
-
-    this._headers = null;
-    this._sendBody();
-  },
-
-  /**
-* Signals that all modifications to the response status line and headers are
-* complete and then sends that data over the network to the client. Once
-* this method completes, a different response to the request that resulted
-* in this response cannot be sent -- the only possible action in case of
-* error is to abort the response and close the connection.
-*/
-  _sendHeaders: function()
-  {
-    dumpn("*** _sendHeaders()");
-
-    NS_ASSERT(this._headers);
-    NS_ASSERT(!this._powerSeized);
-
-    // request-line
-    var statusLine = "HTTP/" + this.httpVersion + " " +
-                     this.httpCode + " " +
-                     this.httpDescription + "\r\n";
-
-    // header post-processing
-
-    var headers = this._headers;
-    headers.setHeader("Connection", "close", false);
-    headers.setHeader("Server", "httpd.js", false);
-    if (!headers.hasHeader("Date"))
-      headers.setHeader("Date", toDateString(Date.now()), false);
-
-    // Any response not being processed asynchronously must have an associated
-    // Content-Length header for reasons of backwards compatibility with the
-    // initial server, which fully buffered every response before sending it.
-    // Beyond that, however, it's good to do this anyway because otherwise it's
-    // impossible to test behaviors that depend on the presence or absence of a
-    // Content-Length header.
-    if (!this._processAsync)
-    {
-      dumpn("*** non-async response, set Content-Length");
-
-      var bodyStream = this._bodyInputStream;
-      var avail = bodyStream ? bodyStream.available() : 0;
-
-      // XXX assumes stream will always report the full amount of data available
-      headers.setHeader("Content-Length", "" + avail, false);
-    }
-
-
-    // construct and send response
-    dumpn("*** header post-processing completed, sending response head...");
-
-    // request-line
-    var preambleData = [statusLine];
-
-    // headers
-    var headEnum = headers.enumerator;
-    while (headEnum.hasMoreElements())
-    {
-      var fieldName = headEnum.getNext()
-                              .QueryInterface(Ci.nsISupportsString)
-                              .data;
-      var values = headers.getHeaderValues(fieldName);
-      for (var i = 0, sz = values.length; i < sz; i++)
-        preambleData.push(fieldName + ": " + values[i] + "\r\n");
-    }
-
-    // end request-line/headers
-    preambleData.push("\r\n");
-
-    var preamble = preambleData.join("");
-
-    var responseHeadPipe = new Pipe(true, false, 0, PR_UINT32_MAX, null);
-    responseHeadPipe.outputStream.write(preamble, preamble.length);
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, cx)
-        {
-          dumpn("*** preamble copying started");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** preamble copying complete " +
-                "[status=0x" + statusCode.toString(16) + "]");
-
-          if (!components.isSuccessCode(statusCode))
-          {
-            dumpn("!!! header copying problems: non-success statusCode, " +
-                  "ending response");
-
-            response.end();
-          }
-          else
-          {
-            response._sendBody();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    var headerCopier = this._asyncCopier =
-      new WriteThroughCopier(responseHeadPipe.inputStream,
-                             this._connection.output,
-                             copyObserver, null);
-
-    responseHeadPipe.outputStream.close();
-
-    // Forbid setting any more headers or modifying the request line.
-    this._headers = null;
-  },
-
-  /**
-* Asynchronously writes the body of the response (or the entire response, if
-* seizePower() has been called) to the network.
-*/
-  _sendBody: function()
-  {
-    dumpn("*** _sendBody");
-
-    NS_ASSERT(!this._headers, "still have headers around but sending body?");
-
-    // If no body data was written, we're done
-    if (!this._bodyInputStream)
-    {
-      dumpn("*** empty body, response finished");
-      this.end();
-      return;
-    }
-
-    var response = this;
-    var copyObserver =
-      {
-        onStartRequest: function(request, context)
-        {
-          dumpn("*** onStartRequest");
-        },
-
-        onStopRequest: function(request, cx, statusCode)
-        {
-          dumpn("*** onStopRequest [status=0x" + statusCode.toString(16) + "]");
-
-          if (statusCode === Cr.NS_BINDING_ABORTED)
-          {
-            dumpn("*** terminating copy observer without ending the response");
-          }
-          else
-          {
-            if (!components.isSuccessCode(statusCode))
-              dumpn("*** WARNING: non-success statusCode in onStopRequest");
-
-            response.end();
-          }
-        },
-
-        QueryInterface: function(aIID)
-        {
-          if (aIID.equals(Ci.nsIRequestObserver) || aIID.equals(Ci.nsISupports))
-            return this;
-
-          throw Cr.NS_ERROR_NO_INTERFACE;
-        }
-      };
-
-    dumpn("*** starting async copier of body data...");
-    this._asyncCopier =
-      new WriteThroughCopier(this._bodyInputStream, this._connection.output,
-                            copyObserver, null);
-  },
-
-  /** Ensures that this hasn't been ended. */
-  _ensureAlive: function()
-  {
-    NS_ASSERT(!this._ended, "not handling response lifetime correctly");
-  }
-};
-
-/**
-* Size of the segments in the buffer used in storing response data and writing
-* it to the socket.
-*/
-Response.SEGMENT_SIZE = 8192;
-
-/** Serves double duty in WriteThroughCopier implementation. */
-function notImplemented()
-{
-  throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/** Returns true iff the given exception represents stream closure. */
-function streamClosed(e)
-{
-  return e === Cr.NS_BASE_STREAM_CLOSED ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_CLOSED);
-}
-
-/** Returns true iff the given exception represents a blocked stream. */
-function wouldBlock(e)
-{
-  return e === Cr.NS_BASE_STREAM_WOULD_BLOCK ||
-         (typeof e === "object" && e.result === Cr.NS_BASE_STREAM_WOULD_BLOCK);
-}
-
-/**
-* Copies data from source to sink as it becomes available, when that data can
-* be written to sink without blocking.
-*
-* @param source : nsIAsyncInputStream
-* the stream from which data is to be read
-* @param sink : nsIAsyncOutputStream
-* the stream to which data is to be copied
-* @param observer : nsIRequestObserver
-* an observer which will be notified when the copy starts and finishes
-* @param context : nsISupports
-* context passed to observer when notified of start/stop
-* @throws NS_ERROR_NULL_POINTER
-* if source, sink, or observer are null
-*/
-function WriteThroughCopier(source, sink, observer, context)
-{
-  if (!source || !sink || !observer)
-    throw Cr.NS_ERROR_NULL_POINTER;
-
-  /** Stream from which data is being read. */
-  this._source = source;
-
-  /** Stream to which data is being written. */
-  this._sink = sink;
-
-  /** Observer watching this copy. */
-  this._observer = observer;
-
-  /** Context for the observer watching this. */
-  this._context = context;
-
-  /**
-* True iff this is currently being canceled (cancel has been called, the
-* callback may not yet have been made).
-*/
-  this._canceled = false;
-
-  /**
-* False until all data has been read from input and written to output, at
-* which point this copy is completed and cancel() is asynchronously called.
-*/
-  this._completed = false;
-
-  /** Required by nsIRequest, meaningless. */
-  this.loadFlags = 0;
-  /** Required by nsIRequest, meaningless. */
-  this.loadGroup = null;
-  /** Required by nsIRequest, meaningless. */
-  this.name = "response-body-copy";
-
-  /** Status of this request. */
-  this.status = Cr.NS_OK;
-
-  /** Arrays of byte strings waiting to be written to output. */
-  this._pendingData = [];
-
-  // start copying
-  try
-  {
-    observer.onStartRequest(this, context);
-    this._waitToReadData();
-    this._waitForSinkClosure();
-  }
-  catch (e)
-  {
-    dumpn("!!! error starting copy: " + e +
-          ("lineNumber" in e ? ", line " + e.lineNumber : ""));
-    dumpn(e.stack);
-    this.cancel(Cr.NS_ERROR_UNEXPECTED);
-  }
-}
-WriteThroughCopier.prototype =
-{
-  /* nsISupports implementation */
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIInputStreamCallback) ||
-        iid.equals(Ci.nsIOutputStreamCallback) ||
-        iid.equals(Ci.nsIRequest) ||
-        iid.equals(Ci.nsISupports))
-    {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // NSIINPUTSTREAMCALLBACK
-
-  /**
-* Receives a more-data-in-input notification and writes the corresponding
-* data to the output.
-*
-* @param input : nsIAsyncInputStream
-* the input stream on whose data we have been waiting
-*/
-  onInputStreamReady: function(input)
-  {
-    if (this._source === null)
-      return;
-
-    dumpn("*** onInputStreamReady");
-
-    //
-    // Ordinarily we'll read a non-zero amount of data from input, queue it up
-    // to be written and then wait for further callbacks. The complications in
-    // this method are the cases where we deviate from that behavior when errors
-    // occur or when copying is drawing to a finish.
-    //
-    // The edge cases when reading data are:
-    //
-    // Zero data is read
-    // If zero data was read, we're at the end of available data, so we can
-    // should stop reading and move on to writing out what we have (or, if
-    // we've already done that, onto notifying of completion).
-    // A stream-closed exception is thrown
-    // This is effectively a less kind version of zero data being read; the
-    // only difference is that we notify of completion with that result
-    // rather than with NS_OK.
-    // Some other exception is thrown
-    // This is the least kind result. We don't know what happened, so we
-    // act as though the stream closed except that we notify of completion
-    // with the result NS_ERROR_UNEXPECTED.
-    //
-
-    var bytesWanted = 0, bytesConsumed = -1;
-    try
-    {
-      input = new BinaryInputStream(input);
-
-      bytesWanted = Math.min(input.available(), Response.SEGMENT_SIZE);
-      dumpn("*** input wanted: " + bytesWanted);
-
-      if (bytesWanted > 0)
-      {
-        var data = input.readByteArray(bytesWanted);
-        bytesConsumed = data.length;
-        this._pendingData.push(String.fromCharCode.apply(String, data));
-      }
-
-      dumpn("*** " + bytesConsumed + " bytes read");
-
-      // Handle the zero-data edge case in the same place as all other edge
-      // cases are handled.
-      if (bytesWanted === 0)
-        throw Cr.NS_BASE_STREAM_CLOSED;
-    }
-    catch (e)
-    {
-      if (streamClosed(e))
-      {
-        dumpn("*** input stream closed");
-        e = bytesWanted === 0 ? Cr.NS_OK : Cr.NS_ERROR_UNEXPECTED;
-      }
-      else
-      {
-        dumpn("!!! unexpected error reading from input, canceling: " + e);
-        e = Cr.NS_ERROR_UNEXPECTED;
-      }
-
-      this._doneReadingSource(e);
-      return;
-    }
-
-    var pendingData = this._pendingData;
-
-    NS_ASSERT(bytesConsumed > 0);
-    NS_ASSERT(pendingData.length > 0, "no pending data somehow?");
-    NS_ASSERT(pendingData[pendingData.length - 1].length > 0,
-              "buffered zero bytes of data?");
-
-    NS_ASSERT(this._source !== null);
-
-    // Reading has gone great, and we've gotten data to write now. What if we
-    // don't have a place to write that data, because output went away just
-    // before this read? Drop everything on the floor, including new data, and
-    // cancel at this point.
-    if (this._sink === null)
-    {
-      pendingData.length = 0;
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we've read the data, and we know we have a place to write it. We
-    // need to queue up the data to be written, but *only* if none is queued
-    // already -- if data's already queued, the code that actually writes the
-    // data will make sure to wait on unconsumed pending data.
-    try
-    {
-      if (pendingData.length === 1)
-        this._waitToWriteData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to write data just read, swallowing and " +
-            "writing only what we already have: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Whee! We successfully read some data, and it's successfully queued up to
-    // be written. All that remains now is to wait for more data to read.
-    try
-    {
-      this._waitToReadData();
-    }
-    catch (e)
-    {
-      dumpn("!!! error waiting to read more data: " + e);
-      this._doneReadingSource(Cr.NS_ERROR_UNEXPECTED);
-    }
-  },
-
-
-  // NSIOUTPUTSTREAMCALLBACK
-
-  /**
-* Callback when data may be written to the output stream without blocking, or
-* when the output stream has been closed.
-*
-* @param output : nsIAsyncOutputStream
-* the output stream on whose writability we've been waiting, also known as
-* this._sink
-*/
-  onOutputStreamReady: function(output)
-  {
-    if (this._sink === null)
-      return;
-
-    dumpn("*** onOutputStreamReady");
-
-    var pendingData = this._pendingData;
-    if (pendingData.length === 0)
-    {
-      // There's no pending data to write. The only way this can happen is if
-      // we're waiting on the output stream's closure, so we can respond to a
-      // copying failure as quickly as possible (rather than waiting for data to
-      // be available to read and then fail to be copied). Therefore, we must
-      // be done now -- don't bother to attempt to write anything and wrap
-      // things up.
-      dumpn("!!! output stream closed prematurely, ending copy");
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-
-    NS_ASSERT(pendingData[0].length > 0, "queued up an empty quantum?");
-
-    //
-    // Write out the first pending quantum of data. The possible errors here
-    // are:
-    //
-    // The write might fail because we can't write that much data
-    // Okay, we've written what we can now, so re-queue what's left and
-    // finish writing it out later.
-    // The write failed because the stream was closed
-    // Discard pending data that we can no longer write, stop reading, and
-    // signal that copying finished.
-    // Some other error occurred.
-    // Same as if the stream were closed, but notify with the status
-    // NS_ERROR_UNEXPECTED so the observer knows something was wonky.
-    //
-
-    try
-    {
-      var quantum = pendingData[0];
-
-      // XXX |quantum| isn't guaranteed to be ASCII, so we're relying on
-      // undefined behavior! We're only using this because writeByteArray
-      // is unusably broken for asynchronous output streams; see bug 532834
-      // for details.
-      var bytesWritten = output.write(quantum, quantum.length);
-      if (bytesWritten === quantum.length)
-        pendingData.shift();
-      else
-        pendingData[0] = quantum.substring(bytesWritten);
-
-      dumpn("*** wrote " + bytesWritten + " bytes of data");
-    }
-    catch (e)
-    {
-      if (wouldBlock(e))
-      {
-        NS_ASSERT(pendingData.length > 0,
-                  "stream-blocking exception with no data to write?");
-        NS_ASSERT(pendingData[0].length > 0,
-                  "stream-blocking exception with empty quantum?");
-        this._waitToWriteData();
-        return;
-      }
-
-      if (streamClosed(e))
-        dumpn("!!! output stream prematurely closed, signaling error...");
-      else
-        dumpn("!!! unknown error: " + e + ", quantum=" + quantum);
-
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // The day is ours! Quantum written, now let's see if we have more data
-    // still to write.
-    try
-    {
-      if (pendingData.length > 0)
-      {
-        this._waitToWriteData();
-        return;
-      }
-    }
-    catch (e)
-    {
-      dumpn("!!! unexpected error waiting to write pending data: " + e);
-      this._doneWritingToSink(Cr.NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    // Okay, we have no more pending data to write -- but might we get more in
-    // the future?
-    if (this._source !== null)
-    {
-      /*
-* If we might, then wait for the output stream to be closed. (We wait
-* only for closure because we have no data to write -- and if we waited
-* for a specific amount of data, we would get repeatedly notified for no
-* reason if over time the output stream permitted more and more data to
-* be written to it without blocking.)
-*/
-       this._waitForSinkClosure();
-    }
-    else
-    {
-      /*
-* On the other hand, if we can't have more data because the input
-* stream's gone away, then it's time to notify of copy completion.
-* Victory!
-*/
-      this._sink = null;
-      this._cancelOrDispatchCancelCallback(Cr.NS_OK);
-    }
-  },
-
-
-  // NSIREQUEST
-
-  /** Returns true if the cancel observer hasn't been notified yet. */
-  isPending: function()
-  {
-    return !this._completed;
-  },
-
-  /** Not implemented, don't use! */
-  suspend: notImplemented,
-  /** Not implemented, don't use! */
-  resume: notImplemented,
-
-  /**
-* Cancels data reading from input, asynchronously writes out any pending
-* data, and causes the observer to be notified with the given error code when
-* all writing has finished.
-*
-* @param status : nsresult
-* the status to pass to the observer when data copying has been canceled
-*/
-  cancel: function(status)
-  {
-    dumpn("*** cancel(" + status.toString(16) + ")");
-
-    if (this._canceled)
-    {
-      dumpn("*** suppressing a late cancel");
-      return;
-    }
-
-    this._canceled = true;
-    this.status = status;
-
-    // We could be in the middle of absolutely anything at this point. Both
-    // input and output might still be around, we might have pending data to
-    // write, and in general we know nothing about the state of the world. We
-    // therefore must assume everything's in progress and take everything to its
-    // final steady state (or so far as it can go before we need to finish
-    // writing out remaining data).
-
-    this._doneReadingSource(status);
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /**
-* Stop reading input if we haven't already done so, passing e as the status
-* when closing the stream, and kick off a copy-completion notice if no more
-* data remains to be written.
-*
-* @param e : nsresult
-* the status to be used when closing the input stream
-*/
-  _doneReadingSource: function(e)
-  {
-    dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
-
-    this._finishSource(e);
-    if (this._pendingData.length === 0)
-      this._sink = null;
-    else
-      NS_ASSERT(this._sink !== null, "null output?");
-
-    // If we've written out all data read up to this point, then it's time to
-    // signal completion.
-    if (this._sink === null)
-    {
-      NS_ASSERT(this._pendingData.length === 0, "pending data still?");
-      this._cancelOrDispatchCancelCallback(e);
-    }
-  },
-
-  /**
-* Stop writing output if we haven't already done so, discard any data that
-* remained to be sent, close off input if it wasn't already closed, and kick
-* off a copy-completion notice.
-*
-* @param e : nsresult
-* the status to be used when closing input if it wasn't already closed
-*/
-  _doneWritingToSink: function(e)
-  {
-    dumpn("*** _doneWritingToSink(0x" + e.toString(16) + ")");
-
-    this._pendingData.length = 0;
-    this._sink = null;
-    this._doneReadingSource(e);
-  },
-
-  /**
-* Completes processing of this copy: either by canceling the copy if it
-* hasn't already been canceled using the provided status, or by dispatching
-* the cancel callback event (with the originally provided status, of course)
-* if it already has been canceled.
-*
-* @param status : nsresult
-* the status code to use to cancel this, if this hasn't already been
-* canceled
-*/
-  _cancelOrDispatchCancelCallback: function(status)
-  {
-    dumpn("*** _cancelOrDispatchCancelCallback(" + status + ")");
-
-    NS_ASSERT(this._source === null, "should have finished input");
-    NS_ASSERT(this._sink === null, "should have finished output");
-    NS_ASSERT(this._pendingData.length === 0, "should have no pending data");
-
-    if (!this._canceled)
-    {
-      this.cancel(status);
-      return;
-    }
-
-    var self = this;
-    var event =
-      {
-        run: function()
-        {
-          dumpn("*** onStopRequest async callback");
-
-          self._completed = true;
-          try
-          {
-            self._observer.onStopRequest(self, self._context, self.status);
-          }
-          catch (e)
-          {
-            NS_ASSERT(false,
-                      "how are we throwing an exception here? we control " +
-                      "all the callers! " + e);
-          }
-        }
-      };
-
-    gThreadManager.dispatchToMainThread(event);
-  },
-
-  /**
-* Kicks off another wait for more data to be available from the input stream.
-*/
-  _waitToReadData: function()
-  {
-    dumpn("*** _waitToReadData");
-    this._source.asyncWait(this, 0, Response.SEGMENT_SIZE,
-                           gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off another wait until data can be written to the output stream.
-*/
-  _waitToWriteData: function()
-  {
-    dumpn("*** _waitToWriteData");
-
-    var pendingData = this._pendingData;
-    NS_ASSERT(pendingData.length > 0, "no pending data to write?");
-    NS_ASSERT(pendingData[0].length > 0, "buffered an empty write?");
-
-    this._sink.asyncWait(this, 0, pendingData[0].length,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Kicks off a wait for the sink to which data is being copied to be closed.
-* We wait for stream closure when we don't have any data to be copied, rather
-* than waiting to write a specific amount of data. We can't wait to write
-* data because the sink might be infinitely writable, and if no data appears
-* in the source for a long time we might have to spin quite a bit waiting to
-* write, waiting to write again, &c. Waiting on stream closure instead means
-* we'll get just one notification if the sink dies. Note that when data
-* starts arriving from the sink we'll resume waiting for data to be written,
-* dropping this closure-only callback entirely.
-*/
-  _waitForSinkClosure: function()
-  {
-    dumpn("*** _waitForSinkClosure");
-
-    this._sink.asyncWait(this, Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY, 0,
-                         gThreadManager.mainThread);
-  },
-
-  /**
-* Closes input with the given status, if it hasn't already been closed;
-* otherwise a no-op.
-*
-* @param status : nsresult
-* status code use to close the source stream if necessary
-*/
-  _finishSource: function(status)
-  {
-    dumpn("*** _finishSource(" + status.toString(16) + ")");
-
-    if (this._source !== null)
-    {
-      this._source.closeWithStatus(status);
-      this._source = null;
-    }
-  }
-};
-
-
-/**
-* A container for utility functions used with HTTP headers.
-*/
-const headerUtils =
-{
-  /**
-* Normalizes fieldName (by converting it to lowercase) and ensures it is a
-* valid header field name (although not necessarily one specified in RFC
-* 2616).
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not match the field-name production in RFC 2616
-* @returns string
-* fieldName converted to lowercase if it is a valid header, for characters
-* where case conversion is possible
-*/
-  normalizeFieldName: function(fieldName)
-  {
-    if (fieldName == "")
-      throw Cr.NS_ERROR_INVALID_ARG;
-
-    for (var i = 0, sz = fieldName.length; i < sz; i++)
-    {
-      if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
-      {
-        dumpn(fieldName + " is not a valid header field name!");
-        throw Cr.NS_ERROR_INVALID_ARG;
-      }
-    }
-
-    return fieldName.toLowerCase();
-  },
-
-  /**
-* Ensures that fieldValue is a valid header field value (although not
-* necessarily as specified in RFC 2616 if the corresponding field name is
-* part of the HTTP protocol), normalizes the value if it is, and
-* returns the normalized value.
-*
-* @param fieldValue : string
-* a value to be normalized as an HTTP header field value
-* @throws NS_ERROR_INVALID_ARG
-* if fieldValue does not match the field-value production in RFC 2616
-* @returns string
-* fieldValue as a normalized HTTP header field value
-*/
-  normalizeFieldValue: function(fieldValue)
-  {
-    // field-value = *( field-content | LWS )
-    // field-content = <the OCTETs making up the field-value
-    // and consisting of either *TEXT or combinations
-    // of token, separators, and quoted-string>
-    // TEXT = <any OCTET except CTLs,
-    // but including LWS>
-    // LWS = [CRLF] 1*( SP | HT )
-    //
-    // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-    // qdtext = <any TEXT except <">>
-    // quoted-pair = "\" CHAR
-    // CHAR = <any US-ASCII character (octets 0 - 127)>
-
-    // Any LWS that occurs between field-content MAY be replaced with a single
-    // SP before interpreting the field value or forwarding the message
-    // downstream (section 4.2); we replace 1*LWS with a single SP
-    var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
-
-    // remove leading/trailing LWS (which has been converted to SP)
-    val = val.replace(/^ +/, "").replace(/ +$/, "");
-
-    // that should have taken care of all CTLs, so val should contain no CTLs
-    for (var i = 0, len = val.length; i < len; i++)
-      if (isCTL(val.charCodeAt(i)))
-        throw Cr.NS_ERROR_INVALID_ARG;
-
-    // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
-    // normalize, however, so this can be construed as a tightening of the
-    // spec and not entirely as a bug
-    return val;
-  }
-};
-
-
-
-/**
-* Converts the given string into a string which is safe for use in an HTML
-* context.
-*
-* @param str : string
-* the string to make HTML-safe
-* @returns string
-* an HTML-safe version of str
-*/
-function htmlEscape(str)
-{
-  // this is naive, but it'll work
-  var s = "";
-  for (var i = 0; i < str.length; i++)
-    s += "&#" + str.charCodeAt(i) + ";";
-  return s;
-}
-
-
-/**
-* Constructs an object representing an HTTP version (see section 3.1).
-*
-* @param versionString
-* a string of the form "#.#", where # is an non-negative decimal integer with
-* or without leading zeros
-* @throws
-* if versionString does not specify a valid HTTP version number
-*/
-function nsHttpVersion(versionString)
-{
-  var matches = /^(\d+)\.(\d+)$/.exec(versionString);
-  if (!matches)
-    throw "Not a valid HTTP version!";
-
-  /** The major version number of this, as a number. */
-  this.major = parseInt(matches[1], 10);
-
-  /** The minor version number of this, as a number. */
-  this.minor = parseInt(matches[2], 10);
-
-  if (isNaN(this.major) || isNaN(this.minor) ||
-      this.major < 0 || this.minor < 0)
-    throw "Not a valid HTTP version!";
-}
-nsHttpVersion.prototype =
-{
-  /**
-* Returns the standard string representation of the HTTP version represented
-* by this (e.g., "1.1").
-*/
-  toString: function ()
-  {
-    return this.major + "." + this.minor;
-  },
-
-  /**
-* Returns true if this represents the same HTTP version as otherVersion,
-* false otherwise.
-*
-* @param otherVersion : nsHttpVersion
-* the version to compare against this
-*/
-  equals: function (otherVersion)
-  {
-    return this.major == otherVersion.major &&
-           this.minor == otherVersion.minor;
-  },
-
-  /** True if this >= otherVersion, false otherwise. */
-  atLeast: function(otherVersion)
-  {
-    return this.major > otherVersion.major ||
-           (this.major == otherVersion.major &&
-            this.minor >= otherVersion.minor);
-  }
-};
-
-nsHttpVersion.HTTP_1_0 = new nsHttpVersion("1.0");
-nsHttpVersion.HTTP_1_1 = new nsHttpVersion("1.1");
-
-
-/**
-* An object which stores HTTP headers for a request or response.
-*
-* Note that since headers are case-insensitive, this object converts headers to
-* lowercase before storing them. This allows the getHeader and hasHeader
-* methods to work correctly for any case of a header, but it means that the
-* values returned by .enumerator may not be equal case-sensitively to the
-* values passed to setHeader when adding headers to this.
-*/
-function nsHttpHeaders()
-{
-  /**
-* A hash of headers, with header field names as the keys and header field
-* values as the values. Header field names are case-insensitive, but upon
-* insertion here they are converted to lowercase. Header field values are
-* normalized upon insertion to contain no leading or trailing whitespace.
-*
-* Note also that per RFC 2616, section 4.2, two headers with the same name in
-* a message may be treated as one header with the same field name and a field
-* value consisting of the separate field values joined together with a "," in
-* their original order. This hash stores multiple headers with the same name
-* in this manner.
-*/
-  this._headers = {};
-}
-nsHttpHeaders.prototype =
-{
-  /**
-* Sets the header represented by name and value in this.
-*
-* @param name : string
-* the header name
-* @param value : string
-* the header value
-* @throws NS_ERROR_INVALID_ARG
-* if name or value is not a valid header component
-*/
-  setHeader: function(fieldName, fieldValue, merge)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    var value = headerUtils.normalizeFieldValue(fieldValue);
-
-    // The following three headers are stored as arrays because their real-world
-    // syntax prevents joining individual headers into a single header using
-    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
-    if (merge && name in this._headers)
-    {
-      if (name === "www-authenticate" ||
-          name === "proxy-authenticate" ||
-          name === "set-cookie")
-      {
-        this._headers[name].push(value);
-      }
-      else
-      {
-        this._headers[name][0] += "," + value;
-        NS_ASSERT(this._headers[name].length === 1,
-            "how'd a non-special header have multiple values?")
-      }
-    }
-    else
-    {
-      this._headers[name] = [value];
-    }
-  },
-
-  /**
-* Returns the value for the header specified by this.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns string
-* the field value for the given header, possibly with non-semantic changes
-* (i.e., leading/trailing whitespace stripped, whitespace runs replaced
-* with spaces, etc.) at the option of the implementation; multiple
-* instances of the header will be combined with a comma, except for
-* the three headers noted in the description of getHeaderValues
-*/
-  getHeader: function(fieldName)
-  {
-    return this.getHeaderValues(fieldName).join("\n");
-  },
-
-  /**
-* Returns the value for the header specified by fieldName as an array.
-*
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @throws NS_ERROR_NOT_AVAILABLE
-* if the given header does not exist in this
-* @returns [string]
-* an array of all the header values in this for the given
-* header name. Header values will generally be collapsed
-* into a single header by joining all header values together
-* with commas, but certain headers (Proxy-Authenticate,
-* WWW-Authenticate, and Set-Cookie) violate the HTTP spec
-* and cannot be collapsed in this manner. For these headers
-* only, the returned array may contain multiple elements if
-* that header has been added more than once.
-*/
-  getHeaderValues: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-
-    if (name in this._headers)
-      return this._headers[name];
-    else
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-  },
-
-  /**
-* Returns true if a header with the given field name exists in this, false
-* otherwise.
-*
-* @param fieldName : string
-* the field name whose existence is to be determined in this
-* @throws NS_ERROR_INVALID_ARG
-* if fieldName does not constitute a valid header field name
-* @returns boolean
-* true if the header's present, false otherwise
-*/
-  hasHeader: function(fieldName)
-  {
-    var name = headerUtils.normalizeFieldName(fieldName);
-    return (name in this._headers);
-  },
-
-  /**
-* Returns a new enumerator over the field names of the headers in this, as
-* nsISupportsStrings. The names returned will be in lowercase, regardless of
-* how they were input using setHeader (header names are case-insensitive per
-* RFC 2616).
-*/
-  get enumerator()
-  {
-    var headers = [];
-    for (var i in this._headers)
-    {
-      var supports = new SupportsString();
-      supports.data = i;
-      headers.push(supports);
-    }
-
-    return new nsSimpleEnumerator(headers);
-  }
-};
-
-
-/**
-* Constructs an nsISimpleEnumerator for the given array of items.
-*
-* @param items : Array
-* the items, which must all implement nsISupports
-*/
-function nsSimpleEnumerator(items)
-{
-  this._items = items;
-  this._nextIndex = 0;
-}
-nsSimpleEnumerator.prototype =
-{
-  hasMoreElements: function()
-  {
-    return this._nextIndex < this._items.length;
-  },
-  getNext: function()
-  {
-    if (!this.hasMoreElements())
-      throw Cr.NS_ERROR_NOT_AVAILABLE;
-
-    return this._items[this._nextIndex++];
-  },
-  QueryInterface: function(aIID)
-  {
-    if (Ci.nsISimpleEnumerator.equals(aIID) ||
-        Ci.nsISupports.equals(aIID))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  }
-};
-
-
-/**
-* A representation of the data in an HTTP request.
-*
-* @param port : uint
-* the port on which the server receiving this request runs
-*/
-function Request(port)
-{
-  /** Method of this request, e.g. GET or POST. */
-  this._method = "";
-
-  /** Path of the requested resource; empty paths are converted to '/'. */
-  this._path = "";
-
-  /** Query string, if any, associated with this request (not including '?'). */
-  this._queryString = "";
-
-  /** Scheme of requested resource, usually http, always lowercase. */
-  this._scheme = "http";
-
-  /** Hostname on which the requested resource resides. */
-  this._host = undefined;
-
-  /** Port number over which the request was received. */
-  this._port = port;
-
-  var bodyPipe = new Pipe(false, false, 0, PR_UINT32_MAX, null);
-
-  /** Stream from which data in this request's body may be read. */
-  this._bodyInputStream = bodyPipe.inputStream;
-
-  /** Stream to which data in this request's body is written. */
-  this._bodyOutputStream = bodyPipe.outputStream;
-
-  /**
-* The headers in this request.
-*/
-  this._headers = new nsHttpHeaders();
-
-  /**
-* For the addition of ad-hoc properties and new functionality without having
-* to change nsIHttpRequest every time; currently lazily created, as its only
-* use is in directory listings.
-*/
-  this._bag = null;
-}
-Request.prototype =
-{
-  // SERVER METADATA
-
-  //
-  // see nsIHttpRequest.scheme
-  //
-  get scheme()
-  {
-    return this._scheme;
-  },
-
-  //
-  // see nsIHttpRequest.host
-  //
-  get host()
-  {
-    return this._host;
-  },
-
-  //
-  // see nsIHttpRequest.port
-  //
-  get port()
-  {
-    return this._port;
-  },
-
-  // REQUEST LINE
-
-  //
-  // see nsIHttpRequest.method
-  //
-  get method()
-  {
-    return this._method;
-  },
-
-  //
-  // see nsIHttpRequest.httpVersion
-  //
-  get httpVersion()
-  {
-    return this._httpVersion.toString();
-  },
-
-  //
-  // see nsIHttpRequest.path
-  //
-  get path()
-  {
-    return this._path;
-  },
-
-  //
-  // see nsIHttpRequest.queryString
-  //
-  get queryString()
-  {
-    return this._queryString;
-  },
-
-  // HEADERS
-
-  //
-  // see nsIHttpRequest.getHeader
-  //
-  getHeader: function(name)
-  {
-    return this._headers.getHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.hasHeader
-  //
-  hasHeader: function(name)
-  {
-    return this._headers.hasHeader(name);
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get headers()
-  {
-    return this._headers.enumerator;
-  },
-
-  //
-  // see nsIPropertyBag.enumerator
-  //
-  get enumerator()
-  {
-    this._ensurePropertyBag();
-    return this._bag.enumerator;
-  },
-
-  //
-  // see nsIHttpRequest.headers
-  //
-  get bodyInputStream()
-  {
-    return this._bodyInputStream;
-  },
-
-  //
-  // see nsIPropertyBag.getProperty
-  //
-  getProperty: function(name)
-  {
-    this._ensurePropertyBag();
-    return this._bag.getProperty(name);
-  },
-
-
-  // NSISUPPORTS
-
-  //
-  // see nsISupports.QueryInterface
-  //
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // PRIVATE IMPLEMENTATION
-
-  /** Ensures a property bag has been created for ad-hoc behaviors. */
-  _ensurePropertyBag: function()
-  {
-    if (!this._bag)
-      this._bag = new WritablePropertyBag();
-  }
-};
-
-
-// XPCOM trappings
-if ("XPCOMUtils" in this && // Firefox 3.6 doesn't load XPCOMUtils in this scope for some reason...
-    "generateNSGetFactory" in XPCOMUtils) {
-  var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsHttpServer]);
-}
-
-
-
-/**
-* Creates a new HTTP server listening for loopback traffic on the given port,
-* starts it, and runs the server until the server processes a shutdown request,
-* spinning an event loop so that events posted by the server's socket are
-* processed.
-*
-* This method is primarily intended for use in running this script from within
-* xpcshell and running a functional HTTP server without having to deal with
-* non-essential details.
-*
-* Note that running multiple servers using variants of this method probably
-* doesn't work, simply due to how the internal event loop is spun and stopped.
-*
-* @note
-* This method only works with Mozilla 1.9 (i.e., Firefox 3 or trunk code);
-* you should use this server as a component in Mozilla 1.8.
-* @param port
-* the port on which the server will run, or -1 if there exists no preference
-* for a specific port; note that attempting to use some values for this
-* parameter (particularly those below 1024) may cause this method to throw or
-* may result in the server being prematurely shut down
-* @param basePath
-* a local directory from which requests will be served (i.e., if this is
-* "/home/jwalden/" then a request to /index.html will load
-* /home/jwalden/index.html); if this is omitted, only the default URLs in
-* this server implementation will be functional
-*/
-function server(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  // if you're running this, you probably want to see debugging info
-  DEBUG = true;
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", SJS_TYPE);
-  srv.start(port);
-
-  gThreadManager.spinEventLoopUntil(() => srv.isStopped());
-
-  gThreadManager.spinEventLoopUntilEmpty();
-
-  DEBUG = false;
-}
-
-function startServerAsync(port, basePath)
-{
-  if (basePath)
-  {
-    var lp = Cc["@mozilla.org/file/local;1"]
-               .createInstance(Ci.nsIFile);
-    lp.initWithPath(basePath);
-  }
-
-  var srv = new nsHttpServer();
-  if (lp)
-    srv.registerDirectory("/", lp);
-  srv.registerContentType("sjs", "sjs");
-  srv.start(port);
-  return srv;
-}
-
-exports.nsHttpServer = nsHttpServer;
-exports.ScriptableInputStream = ScriptableInputStream;
-exports.server = server;
-exports.startServerAsync = startServerAsync;
deleted file mode 100644
--- a/addon-sdk/source/test/loader/b2g.js
+++ /dev/null
@@ -1,41 +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 {readURISync} = require("sdk/net/url");
-
-const systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].
-                        createInstance(Ci.nsIPrincipal);
-
-
-const FakeCu = function() {
-  const sandbox = Cu.Sandbox(systemPrincipal, {wantXrays: false});
-  sandbox.toString = function() {
-    return "[object BackstagePass]";
-  }
-  this.sandbox = sandbox;
-}
-FakeCu.prototype = {
-  ["import"](url, scope) {
-    const {sandbox} = this;
-    sandbox.__URI__ = url;
-    const target = Cu.createObjectIn(sandbox);
-    target.toString = sandbox.toString;
-    Cu.evalInSandbox(`(function(){` + readURISync(url) + `\n})`,
-                     sandbox, "1.8", url).call(target);
-    // Borrowed from mozJSComponentLoader.cpp to match errors closer.
-    // https://github.com/mozilla/gecko-dev/blob/f6ca65e8672433b2ce1a0e7c31f72717930b5e27/js/xpconnect/loader/mozJSComponentLoader.cpp#L1205-L1208
-    if (!Array.isArray(target.EXPORTED_SYMBOLS)) {
-      throw Error("EXPORTED_SYMBOLS is not an array.");
-    }
-
-    for (let key of target.EXPORTED_SYMBOLS) {
-      scope[key] = target[key];
-    }
-
-    return target;
-  }
-};
-exports.FakeCu = FakeCu;
deleted file mode 100644
--- a/addon-sdk/source/test/loader/fixture.js
+++ /dev/null
@@ -1,7 +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/. */
-
-exports.foo = foo;
-exports.bar = 2;
-print('testing');
deleted file mode 100644
--- a/addon-sdk/source/test/loader/user-global.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/. */
-"use strict";
-
-// Test module to check presense of user defined globals.
-// Related to bug 827792.
-
-exports.getCom = function() {
-  return com;
-};
deleted file mode 100644
--- a/addon-sdk/source/test/modules/add.js
+++ /dev/null
@@ -1,9 +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/. */
-
-define('modules/add', function () {
-  return function (a, b) {
-    return a + b;
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/async1.js
+++ /dev/null
@@ -1,14 +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/. */
-
-define(['./traditional2', './async2'], function () {
-  var traditional2 = require('./traditional2');
-  return {
-    name: 'async1',
-    traditional1Name: traditional2.traditional1Name,
-    traditional2Name: traditional2.name,
-    async2Name: require('./async2').name,
-    async2Traditional2Name: require('./async2').traditional2Name
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/async2.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-define(['./traditional2', 'exports'], function (traditional2, exports) {
-  exports.name = 'async2';
-  exports.traditional2Name = traditional2.name;
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/badExportAndReturn.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/. */
-
-// This is a bad module, it asks for exports but also returns a value from
-// the define defintion function.
-define(['exports'], function (exports) {    
-    return 'badExportAndReturn';
-});
-
deleted file mode 100644
--- a/addon-sdk/source/test/modules/badFirst.js
+++ /dev/null
@@ -1,9 +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/. */
-
-define(['./badSecond'], function (badSecond) {
-  return {
-    name: 'badFirst'
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/badSecond.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var first = require('./badFirst');
-
-exports.name = 'badSecond';
-exports.badFirstName = first.name;
deleted file mode 100644
--- a/addon-sdk/source/test/modules/blue.js
+++ /dev/null
@@ -1,9 +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/. */
-
-define(function () {
-  return {
-      name: 'blue'
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/castor.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/. */
-
-define(['exports', './pollux'], function(exports, pollux) {
-  exports.name = 'castor';
-  exports.getPolluxName = function () {
-    return pollux.name;
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/cheetah.js
+++ /dev/null
@@ -1,9 +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/. */
-
-define(function () {
-  return function () {
-    return 'cheetah';
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/color.js
+++ /dev/null
@@ -1,7 +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/. */
-
-define({
-  type: 'color'
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/dupe.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-define({
-  name: 'dupe'
-});
-
-// This is wrong and should not be allowed. Only one call to
-// define per file.
-define([], function () {
-  return {
-    name: 'dupe2'
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/dupeNested.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-define(function () {
-  // This is wrong and should not be allowed.
-  define('dupeNested2', {
-      name: 'dupeNested2'
-  });
-
-  return {
-    name: 'dupeNested'
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/dupeSetExports.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-define({name: "dupeSetExports"});
-
-// so this should cause a failure
-module.setExports("no no no");
deleted file mode 100644
--- a/addon-sdk/source/test/modules/exportsEquals.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.exports = 4;
deleted file mode 100644
--- a/addon-sdk/source/test/modules/green.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/. */
-
-define('modules/green', ['./color'], function (color) {
-  return {
-    name: 'green',
-    parentType: color.type
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/lion.js
+++ /dev/null
@@ -1,7 +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/. */
-
-define(function(require) {
-  return 'lion';
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/orange.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/. */
-
-define(['./color'], function (color) {
-  return {
-    name: 'orange',
-    parentType: color.type
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/pollux.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/. */
-
-define(['exports', './castor'], function(exports, castor) {
-  exports.name = 'pollux';
-  exports.getCastorName = function () {
-    return castor.name;
-  };
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/red.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-define(function (require) {
-  // comment fake-outs for require finding.
-  // require('bad1');
-  return {
-    name: 'red',
-    parentType: require('./color').type
-  };
-
-  /*
-   require('bad2');
-  */
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/setExports.js
+++ /dev/null
@@ -1,5 +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/. */
-
-module.setExports(5);
deleted file mode 100644
--- a/addon-sdk/source/test/modules/subtract.js
+++ /dev/null
@@ -1,9 +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/. */
-
-define(function () {
-    return function (a, b) {
-        return a - b;
-    }
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/tiger.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-define(function (require, exports) {
-  exports.name = 'tiger';
-  exports.type = require('./types/cat').type;
-});
deleted file mode 100644
--- a/addon-sdk/source/test/modules/traditional1.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.name = 'traditional1'
-
-var async1 = require('./async1');
-
-exports.traditional2Name = async1.traditional2Name;
-exports.traditional1Name = async1.traditional1Name;
-exports.async2Name = async1.async2Name;
-exports.async2Traditional2Name = async1.async2Traditional2Name;
deleted file mode 100644
--- a/addon-sdk/source/test/modules/traditional2.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-exports.name = 'traditional2';
-exports.traditional1Name = require('./traditional1').name;
deleted file mode 100644
--- a/addon-sdk/source/test/modules/types/cat.js
+++ /dev/null
@@ -1,5 +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/. */
-
-exports.type = 'cat';
deleted file mode 100644
--- a/addon-sdk/source/test/page-mod/helpers.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cc, Ci } = require("chrome");
-const { setTimeout } = require("sdk/timers");
-const { Loader } = require("sdk/test/loader");
-const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-const { merge } = require("sdk/util/object");
-const httpd = require("../lib/httpd");
-const { cleanUI } = require("sdk/test/utils");
-
-const PORT = 8099;
-const PATH = '/test-contentScriptWhen.html';
-
-function createLoader () {
-  let options = merge({}, require('@loader/options'),
-                      { id: "testloader", prefixURI: require('../fixtures').url() });
-  return Loader(module, null, options);
-}
-exports.createLoader = createLoader;
-
-function openNewTab(url) {
-  return openTab(getMostRecentBrowserWindow(), url, {
-    inBackground: false
-  });
-}
-exports.openNewTab = openNewTab;
-
-// an evil function enables the creation of tests
-// that depend on delicate event timing. do not use.
-function testPageMod(assert, done, testURL, pageModOptions,
-                     testCallback, timeout) {
-  let loader = createLoader();
-  let { PageMod } = loader.require("sdk/page-mod");
-  let pageMods = pageModOptions.map(opts => new PageMod(opts));
-  let newTab = openNewTab(testURL);
-  let b = getBrowserForTab(newTab);
-
-  function onPageLoad() {
-    b.removeEventListener("load", onPageLoad, true);
-    // Delay callback execute as page-mod content scripts may be executed on
-    // load event. So page-mod actions may not be already done.
-    // If we delay even more contentScriptWhen:'end', we may want to modify
-    // this code again.
-    setTimeout(testCallback, timeout,
-      b.contentWindow.wrappedJSObject,  // TODO: remove this CPOW
-      function () {
-        pageMods.forEach(mod => mod.destroy());
-        // XXX leaks reported if we don't close the tab?
-        closeTab(newTab);
-        loader.unload();
-        done();
-      }
-    );
-  }
-  b.addEventListener("load", onPageLoad, true);
-
-  return pageMods;
-}
-exports.testPageMod = testPageMod;
-
-/**
- * helper function that creates a PageMod and calls back the appropriate handler
- * based on the value of document.readyState at the time contentScript is attached
- */
-exports.handleReadyState = function(url, contentScriptWhen, callbacks) {
-  const loader = Loader(module);
-  const { PageMod } = loader.require('sdk/page-mod');
-
-  let pagemod = PageMod({
-    include: url,
-    attachTo: ['existing', 'top'],
-    contentScriptWhen: contentScriptWhen,
-    contentScript: "self.postMessage(document.readyState)",
-    onAttach: worker => {
-      let { tab } = worker;
-      worker.on('message', readyState => {
-        // generate event name from `readyState`, e.g. `"loading"` becomes `onLoading`.
-        let type = 'on' + readyState[0].toUpperCase() + readyState.substr(1);
-
-        if (type in callbacks)
-          callbacks[type](tab);
-
-        pagemod.destroy();
-        loader.unload();
-      })
-    }
-  });
-}
-
-// serves a slow page which takes 1.5 seconds to load,
-// 0.5 seconds in each readyState: uninitialized, loading, interactive.
-function contentScriptWhenServer() {
-  const URL = 'http://localhost:' + PORT + PATH;
-
-  const HTML = `/* polyglot js
-    <script src="${URL}"></script>
-    delay both the "DOMContentLoaded"
-    <script async src="${URL}"></script>
-    and "load" events */`;
-
-  let srv = httpd.startServerAsync(PORT);
-
-  srv.registerPathHandler(PATH, (_, response) => {
-    response.processAsync();
-    response.setHeader('Content-Type', 'text/html', false);
-    setTimeout(_ => response.finish(), 500);
-    response.write(HTML);
-  })
-
-  srv.URL = URL;
-  return srv;
-}
-exports.contentScriptWhenServer = contentScriptWhenServer;
deleted file mode 100644
--- a/addon-sdk/source/test/path/test-path.js
+++ /dev/null
@@ -1,430 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-// Adapted version of:
-// https://github.com/joyent/node/blob/v0.9.1/test/simple/test-path.js
-
-exports['test path'] = function(assert) {
-  var system = require('sdk/system');
-  var path = require('sdk/fs/path');
-
-  // Shim process global from node.
-  var process = Object.create(require('sdk/system'));
-  process.cwd = process.pathFor.bind(process, 'CurProcD');
-
-  var isWindows = require('sdk/system').platform.indexOf('win') === 0;
-
-  assert.equal(path.basename(''), '');
-  assert.equal(path.basename('/dir/basename.ext'), 'basename.ext');
-  assert.equal(path.basename('/basename.ext'), 'basename.ext');
-  assert.equal(path.basename('basename.ext'), 'basename.ext');
-  assert.equal(path.basename('basename.ext/'), 'basename.ext');
-  assert.equal(path.basename('basename.ext//'), 'basename.ext');
-
-  if (isWindows) {
-    // On Windows a backslash acts as a path separator.
-    assert.equal(path.basename('\\dir\\basename.ext'), 'basename.ext');
-    assert.equal(path.basename('\\basename.ext'), 'basename.ext');
-    assert.equal(path.basename('basename.ext'), 'basename.ext');
-    assert.equal(path.basename('basename.ext\\'), 'basename.ext');
-    assert.equal(path.basename('basename.ext\\\\'), 'basename.ext');
-
-  } else {
-    // On unix a backslash is just treated as any other character.
-    assert.equal(path.basename('\\dir\\basename.ext'), '\\dir\\basename.ext');
-    assert.equal(path.basename('\\basename.ext'), '\\basename.ext');
-    assert.equal(path.basename('basename.ext'), 'basename.ext');
-    assert.equal(path.basename('basename.ext\\'), 'basename.ext\\');
-    assert.equal(path.basename('basename.ext\\\\'), 'basename.ext\\\\');
-  }
-
-  // POSIX filenames may include control characters
-  // c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
-  if (!isWindows) {
-    var controlCharFilename = 'Icon' + String.fromCharCode(13);
-    assert.equal(path.basename('/a/b/' + controlCharFilename),
-                 controlCharFilename);
-  }
-
-  assert.equal(path.dirname('/a/b/'), '/a');
-  assert.equal(path.dirname('/a/b'), '/a');
-  assert.equal(path.dirname('/a'), '/');
-  assert.equal(path.dirname(''), '.');
-  assert.equal(path.dirname('/'), '/');
-  assert.equal(path.dirname('////'), '/');
-
-  if (isWindows) {
-    assert.equal(path.dirname('c:\\'), 'c:\\');
-    assert.equal(path.dirname('c:\\foo'), 'c:\\');
-    assert.equal(path.dirname('c:\\foo\\'), 'c:\\');
-    assert.equal(path.dirname('c:\\foo\\bar'), 'c:\\foo');
-    assert.equal(path.dirname('c:\\foo\\bar\\'), 'c:\\foo');
-    assert.equal(path.dirname('c:\\foo\\bar\\baz'), 'c:\\foo\\bar');
-    assert.equal(path.dirname('\\'), '\\');
-    assert.equal(path.dirname('\\foo'), '\\');
-    assert.equal(path.dirname('\\foo\\'), '\\');
-    assert.equal(path.dirname('\\foo\\bar'), '\\foo');
-    assert.equal(path.dirname('\\foo\\bar\\'), '\\foo');
-    assert.equal(path.dirname('\\foo\\bar\\baz'), '\\foo\\bar');
-    assert.equal(path.dirname('c:'), 'c:');
-    assert.equal(path.dirname('c:foo'), 'c:');
-    assert.equal(path.dirname('c:foo\\'), 'c:');
-    assert.equal(path.dirname('c:foo\\bar'), 'c:foo');
-    assert.equal(path.dirname('c:foo\\bar\\'), 'c:foo');
-    assert.equal(path.dirname('c:foo\\bar\\baz'), 'c:foo\\bar');
-    assert.equal(path.dirname('\\\\unc\\share'), '\\\\unc\\share');
-    assert.equal(path.dirname('\\\\unc\\share\\foo'), '\\\\unc\\share\\');
-    assert.equal(path.dirname('\\\\unc\\share\\foo\\'), '\\\\unc\\share\\');
-    assert.equal(path.dirname('\\\\unc\\share\\foo\\bar'),
-                 '\\\\unc\\share\\foo');
-    assert.equal(path.dirname('\\\\unc\\share\\foo\\bar\\'),
-                 '\\\\unc\\share\\foo');
-    assert.equal(path.dirname('\\\\unc\\share\\foo\\bar\\baz'),
-                 '\\\\unc\\share\\foo\\bar');
-  }
-
-
-  assert.equal(path.extname(''), '');
-  assert.equal(path.extname('/path/to/file'), '');
-  assert.equal(path.extname('/path/to/file.ext'), '.ext');
-  assert.equal(path.extname('/path.to/file.ext'), '.ext');
-  assert.equal(path.extname('/path.to/file'), '');
-  assert.equal(path.extname('/path.to/.file'), '');
-  assert.equal(path.extname('/path.to/.file.ext'), '.ext');
-  assert.equal(path.extname('/path/to/f.ext'), '.ext');
-  assert.equal(path.extname('/path/to/..ext'), '.ext');
-  assert.equal(path.extname('file'), '');
-  assert.equal(path.extname('file.ext'), '.ext');
-  assert.equal(path.extname('.file'), '');
-  assert.equal(path.extname('.file.ext'), '.ext');
-  assert.equal(path.extname('/file'), '');
-  assert.equal(path.extname('/file.ext'), '.ext');
-  assert.equal(path.extname('/.file'), '');
-  assert.equal(path.extname('/.file.ext'), '.ext');
-  assert.equal(path.extname('.path/file.ext'), '.ext');
-  assert.equal(path.extname('file.ext.ext'), '.ext');
-  assert.equal(path.extname('file.'), '.');
-  assert.equal(path.extname('.'), '');
-  assert.equal(path.extname('./'), '');
-  assert.equal(path.extname('.file.ext'), '.ext');
-  assert.equal(path.extname('.file'), '');
-  assert.equal(path.extname('.file.'), '.');
-  assert.equal(path.extname('.file..'), '.');
-  assert.equal(path.extname('..'), '');
-  assert.equal(path.extname('../'), '');
-  assert.equal(path.extname('..file.ext'), '.ext');
-  assert.equal(path.extname('..file'), '.file');
-  assert.equal(path.extname('..file.'), '.');
-  assert.equal(path.extname('..file..'), '.');
-  assert.equal(path.extname('...'), '.');
-  assert.equal(path.extname('...ext'), '.ext');
-  assert.equal(path.extname('....'), '.');
-  assert.equal(path.extname('file.ext/'), '.ext');
-  assert.equal(path.extname('file.ext//'), '.ext');
-  assert.equal(path.extname('file/'), '');
-  assert.equal(path.extname('file//'), '');
-  assert.equal(path.extname('file./'), '.');
-  assert.equal(path.extname('file.//'), '.');
-
-  if (isWindows) {
-    // On windows, backspace is a path separator.
-    assert.equal(path.extname('.\\'), '');
-    assert.equal(path.extname('..\\'), '');
-    assert.equal(path.extname('file.ext\\'), '.ext');
-    assert.equal(path.extname('file.ext\\\\'), '.ext');
-    assert.equal(path.extname('file\\'), '');
-    assert.equal(path.extname('file\\\\'), '');
-    assert.equal(path.extname('file.\\'), '.');
-    assert.equal(path.extname('file.\\\\'), '.');
-
-  } else {
-    // On unix, backspace is a valid name component like any other character.
-    assert.equal(path.extname('.\\'), '');
-    assert.equal(path.extname('..\\'), '.\\');
-    assert.equal(path.extname('file.ext\\'), '.ext\\');
-    assert.equal(path.extname('file.ext\\\\'), '.ext\\\\');
-    assert.equal(path.extname('file\\'), '');
-    assert.equal(path.extname('file\\\\'), '');
-    assert.equal(path.extname('file.\\'), '.\\');
-    assert.equal(path.extname('file.\\\\'), '.\\\\');
-  }
-
-  // path.join tests
-  var failures = [];
-  var joinTests =
-      // arguments result
-      [[['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'],
-       [['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'],
-       [['/foo', '../../../bar'], '/bar'],
-       [['foo', '../../../bar'], '../../bar'],
-       [['foo/', '../../../bar'], '../../bar'],
-       [['foo/x', '../../../bar'], '../bar'],
-       [['foo/x', './bar'], 'foo/x/bar'],
-       [['foo/x/', './bar'], 'foo/x/bar'],
-       [['foo/x/', '.', 'bar'], 'foo/x/bar'],
-       [['./'], './'],
-       [['.', './'], './'],
-       [['.', '.', '.'], '.'],
-       [['.', './', '.'], '.'],
-       [['.', '/./', '.'], '.'],
-       [['.', '/////./', '.'], '.'],
-       [['.'], '.'],
-       [['', '.'], '.'],
-       [['', 'foo'], 'foo'],
-       [['foo', '/bar'], 'foo/bar'],
-       [['', '/foo'], '/foo'],
-       [['', '', '/foo'], '/foo'],
-       [['', '', 'foo'], 'foo'],
-       [['foo', ''], 'foo'],
-       [['foo/', ''], 'foo/'],
-       [['foo', '', '/bar'], 'foo/bar'],
-       [['./', '..', '/foo'], '../foo'],
-       [['./', '..', '..', '/foo'], '../../foo'],
-       [['.', '..', '..', '/foo'], '../../foo'],
-       [['', '..', '..', '/foo'], '../../foo'],
-       [['/'], '/'],
-       [['/', '.'], '/'],
-       [['/', '..'], '/'],
-       [['/', '..', '..'], '/'],
-       [[''], '.'],
-       [['', ''], '.'],
-       [[' /foo'], ' /foo'],
-       [[' ', 'foo'], ' /foo'],
-       [[' ', '.'], ' '],
-       [[' ', '/'], ' /'],
-       [[' ', ''], ' '],
-       [['/', 'foo'], '/foo'],
-       [['/', '/foo'], '/foo'],
-       [['/', '//foo'], '/foo'],
-       [['/', '', '/foo'], '/foo'],
-       [['', '/', 'foo'], '/foo'],
-       [['', '/', '/foo'], '/foo']
-      ];
-
-  // Windows-specific join tests
-  if (isWindows) {
-    joinTests = joinTests.concat(
-      [// UNC path expected
-       [['//foo/bar'], '//foo/bar/'],
-       [['\\/foo/bar'], '//foo/bar/'],
-       [['\\\\foo/bar'], '//foo/bar/'],
-       // UNC path expected - server and share separate
-       [['//foo', 'bar'], '//foo/bar/'],
-       [['//foo/', 'bar'], '//foo/bar/'],
-       [['//foo', '/bar'], '//foo/bar/'],
-       // UNC path expected - questionable
-       [['//foo', '', 'bar'], '//foo/bar/'],
-       [['//foo/', '', 'bar'], '//foo/bar/'],
-       [['//foo/', '', '/bar'], '//foo/bar/'],
-       // UNC path expected - even more questionable
-       [['', '//foo', 'bar'], '//foo/bar/'],
-       [['', '//foo/', 'bar'], '//foo/bar/'],
-       [['', '//foo/', '/bar'], '//foo/bar/'],
-       // No UNC path expected (no double slash in first component)
-       [['\\', 'foo/bar'], '/foo/bar'],
-       [['\\', '/foo/bar'], '/foo/bar'],
-       [['', '/', '/foo/bar'], '/foo/bar'],
-       // No UNC path expected (no non-slashes in first component - questionable)
-       [['//', 'foo/bar'], '/foo/bar'],
-       [['//', '/foo/bar'], '/foo/bar'],
-       [['\\\\', '/', '/foo/bar'], '/foo/bar'],
-       [['//'], '/'],
-       // No UNC path expected (share name missing - questionable).
-       [['//foo'], '/foo'],
-       [['//foo/'], '/foo/'],
-       [['//foo', '/'], '/foo/'],
-       [['//foo', '', '/'], '/foo/'],
-       // No UNC path expected (too many leading slashes - questionable)
-       [['///foo/bar'], '/foo/bar'],
-       [['////foo', 'bar'], '/foo/bar'],
-       [['\\\\\\/foo/bar'], '/foo/bar'],
-       // Drive-relative vs drive-absolute paths. This merely describes the
-       // status quo, rather than being obviously right
-       [['c:'], 'c:.'],
-       [['c:.'], 'c:.'],
-       [['c:', ''], 'c:.'],
-       [['', 'c:'], 'c:.'],
-       [['c:.', '/'], 'c:./'],
-       [['c:.', 'file'], 'c:file'],
-       [['c:', '/'], 'c:/'],
-       [['c:', 'file'], 'c:/file']
-      ]);
-  }
-
-  // Run the join tests.
-  joinTests.forEach(function(test) {
-    var actual = path.join.apply(path, test[0]);
-    var expected = isWindows ? test[1].replace(/\//g, '\\') : test[1];
-    var message = 'path.join(' + test[0].map(JSON.stringify).join(',') + ')' +
-                  '\n expect=' + JSON.stringify(expected) +
-                  '\n actual=' + JSON.stringify(actual);
-    if (actual !== expected) failures.push('\n' + message);
-    // assert.equal(actual, expected, message);
-  });
-  assert.equal(failures.length, 0, failures.join(''));
-  var joinThrowTests = [true, false, 7, null, {}, undefined, [], NaN];
-  joinThrowTests.forEach(function(test) {
-    assert.throws(function() {
-      path.join(test);
-    }, TypeError);
-    assert.throws(function() {
-      path.resolve(test);
-    }, TypeError);
-  });
-
-
-  // path normalize tests
-  if (isWindows) {
-    assert.equal(path.normalize('./fixtures///b/../b/c.js'),
-                 'fixtures\\b\\c.js');
-    assert.equal(path.normalize('/foo/../../../bar'), '\\bar');
-    assert.equal(path.normalize('a//b//../b'), 'a\\b');
-    assert.equal(path.normalize('a//b//./c'), 'a\\b\\c');
-    assert.equal(path.normalize('a//b//.'), 'a\\b');
-    assert.equal(path.normalize('//server/share/dir/file.ext'),
-                 '\\\\server\\share\\dir\\file.ext');
-  } else {
-    assert.equal(path.normalize('./fixtures///b/../b/c.js'),
-                 'fixtures/b/c.js');
-    assert.equal(path.normalize('/foo/../../../bar'), '/bar');
-    assert.equal(path.normalize('a//b//../b'), 'a/b');
-    assert.equal(path.normalize('a//b//./c'), 'a/b/c');
-    assert.equal(path.normalize('a//b//.'), 'a/b');
-  }
-
-  // path.resolve tests
-  if (isWindows) {
-    // windows
-    var resolveTests =
-        // arguments result
-        [[['c:/blah\\blah', 'd:/games', 'c:../a'], 'c:\\blah\\a'],
-         [['c:/ignore', 'd:\\a/b\\c/d', '\\e.exe'], 'd:\\e.exe'],
-         [['c:/ignore', 'c:/some/file'], 'c:\\some\\file'],
-         [['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'],
-         [['.'], process.cwd()],
-         [['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative'],
-         [['c:/', '//'], 'c:\\'],
-         [['c:/', '//dir'], 'c:\\dir'],
-         [['c:/', '//server/share'], '\\\\server\\share\\'],
-         [['c:/', '//server//share'], '\\\\server\\share\\'],
-         [['c:/', '///some//dir'], 'c:\\some\\dir']
-        ];
-  } else {
-    // Posix
-    var resolveTests =
-        // arguments result
-        [[['/var/lib', '../', 'file/'], '/var/file'],
-         [['/var/lib', '/../', 'file/'], '/file'],
-         // For some mysterious reasons OSX debug builds resolve incorrectly
-         // https://tbpl.mozilla.org/php/getParsedLog.php?id=25105489&tree=Mozilla-Inbound
-         // Disable this tests until Bug 891698 is fixed.
-         // [['a/b/c/', '../../..'], process.cwd()],
-         // [['.'], process.cwd()],
-         [['/some/dir', '.', '/absolute/'], '/absolute']];
-  }
-  var failures = [];
-  resolveTests.forEach(function(test) {
-    var actual = path.resolve.apply(path, test[0]);
-    var expected = test[1];
-    var message = 'path.resolve(' + test[0].map(JSON.stringify).join(',') + ')' +
-                  '\n expect=' + JSON.stringify(expected) +
-                  '\n actual=' + JSON.stringify(actual);
-    if (actual !== expected) failures.push('\n' + message);
-    // assert.equal(actual, expected, message);
-  });
-  assert.equal(failures.length, 0, failures.join(''));
-
-  // path.isAbsolute tests
-  if (isWindows) {
-    assert.equal(path.isAbsolute('//server/file'), true);
-    assert.equal(path.isAbsolute('\\\\server\\file'), true);
-    assert.equal(path.isAbsolute('C:/Users/'), true);
-    assert.equal(path.isAbsolute('C:\\Users\\'), true);
-    assert.equal(path.isAbsolute('C:cwd/another'), false);
-    assert.equal(path.isAbsolute('C:cwd\\another'), false);
-    assert.equal(path.isAbsolute('directory/directory'), false);
-    assert.equal(path.isAbsolute('directory\\directory'), false);
-  } else {
-    assert.equal(path.isAbsolute('/home/foo'), true);
-    assert.equal(path.isAbsolute('/home/foo/..'), true);
-    assert.equal(path.isAbsolute('bar/'), false);
-    assert.equal(path.isAbsolute('./baz'), false);
-  }
-
-  // path.relative tests
-  if (isWindows) {
-    // windows
-    var relativeTests =
-        // arguments result
-        [['c:/blah\\blah', 'd:/games', 'd:\\games'],
-         ['c:/aaaa/bbbb', 'c:/aaaa', '..'],
-         ['c:/aaaa/bbbb', 'c:/cccc', '..\\..\\cccc'],
-         ['c:/aaaa/bbbb', 'c:/aaaa/bbbb', ''],
-         ['c:/aaaa/bbbb', 'c:/aaaa/cccc', '..\\cccc'],
-         ['c:/aaaa/', 'c:/aaaa/cccc', 'cccc'],
-         ['c:/', 'c:\\aaaa\\bbbb', 'aaaa\\bbbb'],
-         ['c:/aaaa/bbbb', 'd:\\', 'd:\\']];
-  } else {
-    // posix
-    var relativeTests =
-        // arguments result
-        [['/var/lib', '/var', '..'],
-         ['/var/lib', '/bin', '../../bin'],
-         ['/var/lib', '/var/lib', ''],
-         ['/var/lib', '/var/apache', '../apache'],
-         ['/var/', '/var/lib', 'lib'],
-         ['/', '/var/lib', 'var/lib']];
-  }
-  var failures = [];
-  relativeTests.forEach(function(test) {
-    var actual = path.relative(test[0], test[1]);
-    var expected = test[2];
-    var message = 'path.relative(' +
-                  test.slice(0, 2).map(JSON.stringify).join(',') +
-                  ')' +
-                  '\n expect=' + JSON.stringify(expected) +
-                  '\n actual=' + JSON.stringify(actual);
-    if (actual !== expected) failures.push('\n' + message);
-  });
-  assert.equal(failures.length, 0, failures.join(''));
-
-  // path.sep tests
-  if (isWindows) {
-    // windows
-    assert.equal(path.sep, '\\');
-  }
-  else {
-    // posix
-    assert.equal(path.sep, '/');
-  }
-
-  // path.delimiter tests
-  if (isWindows) {
-    // windows
-    assert.equal(path.delimiter, ';');
-  }
-  else {
-    // posix
-    assert.equal(path.delimiter, ':');
-  }
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/common.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "browser.dom.window.dump.enabled": true,
-  "javascript.options.showInConsole": true,
-  "devtools.debugger.remote-enabled": true,
-  "extensions.sdk.console.logLevel": "info",
-  "extensions.checkCompatibility.nightly": false,
-  "extensions.update.enabled": false,
-  "lightweightThemes.update.enabled": false,
-  "extensions.update.notifyUser": false,
-  "extensions.enabledScopes": 5,
-  "extensions.getAddons.cache.enabled": false,
-  "extensions.installDistroAddons": false,
-  "extensions.autoDisableScopes": 10,
-  "app.releaseNotesURL": "http://localhost/app-dummy/",
-  "app.vendorURL": "http://localhost/app-dummy/"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/e10s-off.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "browser.tabs.remote.autostart": false,
-  "browser.tabs.remote.autostart.1": false,
-  "browser.tabs.remote.autostart.2": false
-}
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/e10s-on.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "browser.tabs.remote.autostart": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/firefox.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "browser.startup.homepage": "about:blank",
-  "startup.homepage_welcome_url": "about:blank",
-  "devtools.browsertoolbox.panel": "jsdebugger",
-  "devtools.chrome.enabled": true,
-  "browser.safebrowsing.provider.google.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
-  "browser.safebrowsing.provider.google.updateURL": "http://localhost/safebrowsing-dummy/update",
-  "browser.safebrowsing.provider.google4.gethashURL": "http://localhost/safebrowsing4-dummy/gethash",
-  "browser.safebrowsing.provider.google4.updateURL": "http://localhost/safebrowsing4-dummy/update",
-  "browser.safebrowsing.provider.mozilla.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
-  "browser.safebrowsing.provider.mozilla.updateURL": "http://localhost/safebrowsing-dummy/update"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/no-connections.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "toolkit.telemetry.enabled": false,
-  "toolkit.telemetry.server": "https://localhost/telemetry-dummy/",
-  "app.update.auto": false,
-  "app.update.url": "http://localhost/app-dummy/update",
-  "app.update.enabled": false,
-  "app.update.staging.enabled": false,
-  "media.gmp-gmpopenh264.autoupdate": false,
-  "media.gmp-manager.cert.checkAttributes": false,
-  "media.gmp-manager.cert.requireBuiltIn": false,
-  "media.gmp-manager.url": "http://localhost/media-dummy/gmpmanager",
-  "media.gmp-manager.url.override": "http://localhost/dummy-gmp-manager.xml",
-  "media.gmp-manager.updateEnabled": false,
-  "browser.aboutHomeSnippets.updateUrl": "https://localhost/snippet-dummy",
-  "browser.newtab.url": "about:blank",
-  "browser.search.update": false,
-  "browser.search.suggest.enabled": false,
-  "browser.safebrowsing.downloads.remote.url": "http://localhost/safebrowsing-dummy/downloads",
-  "browser.safebrowsing.malware.enabled": false,
-  "browser.safebrowsing.phishing.enabled": false,
-  "browser.safebrowsing.blockedURIs.enabled": false,
-  "browser.safebrowsing.passwords.enabled": false,
-  "browser.safebrowsing.provider.google.updateURL": "http://localhost/safebrowsing-dummy/update",
-  "browser.safebrowsing.provider.google.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
-  "browser.safebrowsing.provider.google.reportURL": "http://localhost/safebrowsing-dummy/malwarereport",
-  "browser.safebrowsing.provider.google4.updateURL": "http://localhost/safebrowsing4-dummy/update",
-  "browser.safebrowsing.provider.google4.gethashURL": "http://localhost/safebrowsing4-dummy/gethash",
-  "browser.safebrowsing.provider.google4.reportURL": "http://localhost/safebrowsing4-dummy/malwarereport",
-  "browser.safebrowsing.provider.mozilla.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
-  "browser.safebrowsing.provider.mozilla.updateURL": "http://localhost/safebrowsing-dummy/update",
-  "plugins.flashBlock.enabled": false,
-  "privacy.trackingprotection.annotate_channels": false,
-  "privacy.trackingprotection.enabled": false,
-  "privacy.trackingprotection.pbmode.enabled": false,
-  "browser.newtabpage.directory.source": "data:application/json,{'jetpack':1}",
-  "extensions.update.url": "http://localhost/extensions-dummy/updateURL",
-  "extensions.update.background.url": "http://localhost/extensions-dummy/updateBackgroundURL",
-  "extensions.blocklist.url": "http://localhost/extensions-dummy/blocklistURL",
-  "extensions.webservice.discoverURL": "http://localhost/extensions-dummy/discoveryURL",
-  "extensions.getAddons.maxResults": 0,
-  "services.blocklist.base": "http://localhost/dummy-kinto/v1",
-  "geo.wifi.uri": "http://localhost/location-dummy/locationURL",
-  "browser.search.geoip.url": "http://localhost/location-dummy/locationURL",
-  "browser.search.isUS": true,
-  "browser.search.countryCode": "US",
-  "geo.wifi.uri": "http://localhost/extensions-dummy/geowifiURL",
-  "geo.wifi.scan": false,
-  "browser.webapps.checkForUpdates": 0,
-  "identity.fxaccounts.auth.uri": "http://localhost/fxa-dummy/"
-}
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/test-e10s-preferences.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var extend = require("lodash").extend
-
-var e10sOn = require("./e10s-on.json");
-var commonPrefs = require("./common.json");
-var testPrefs = require("./test.json");
-var fxPrefs = require("./firefox.json");
-var disconnectionPrefs = require("./no-connections.json");
-
-var prefs = extend({}, e10sOn, commonPrefs, testPrefs, disconnectionPrefs, fxPrefs);
-module.exports = prefs;
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/test-preferences.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var extend = require("lodash").extend
-
-var e10sOff = require("./e10s-off.json");
-var commonPrefs = require("./common.json");
-var testPrefs = require("./test.json");
-var fxPrefs = require("./firefox.json");
-var disconnectionPrefs = require("./no-connections.json");
-
-var prefs = extend({}, e10sOff, commonPrefs, testPrefs, disconnectionPrefs, fxPrefs);
-module.exports = prefs;
deleted file mode 100644
--- a/addon-sdk/source/test/preferences/test.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-  "browser.console.showInPanel": true,
-  "browser.startup.page": 0,
-  "browser.firstrun.show.localepicker": false,
-  "browser.firstrun.show.uidiscovery": false,
-  "browser.ui.layout.tablet": 0,
-  "dom.disable_open_during_load": false,
-  "dom.experimental_forms": true,
-  "dom.forms.number": true,
-  "dom.forms.color": true,
-  "dom.max_script_run_time": 0,
-  "hangmonitor.timeout": 0,
-  "dom.max_chrome_script_run_time": 0,
-  "dom.popup_maximum": -1,
-  "dom.send_after_paint_to_content": true,
-  "dom.successive_dialog_time_limit": 0,
-  "browser.shell.checkDefaultBrowser": false,
-  "shell.checkDefaultClient": false,
-  "browser.warnOnQuit": false,
-  "accessibility.typeaheadfind.autostart": false,
-  "browser.EULA.override": true,
-  "gfx.color_management.force_srgb": true,
-  "network.manage-offline-status": false,
-  "network.http.speculative-parallel-limit": 0,
-  "test.mousescroll": true,
-  "security.default_personal_cert": "Select Automatically",
-  "network.http.prompt-temp-redirect": false,
-  "security.warn_viewing_mixed": false,
-  "extensions.defaultProviders.enabled": true,
-  "datareporting.policy.dataSubmissionPolicyBypassNotification": true,
-  "layout.css.report_errors": true,
-  "layout.css.grid.enabled": true,
-  "layout.spammy_warnings.enabled": false,
-  "geo.provider.testing": true,
-  "browser.pagethumbnails.capturing_disabled": true,
-  "browser.download.panel.shown": true,
-  "general.useragent.updates.enabled": false,
-  "media.eme.enabled": true,
-  "dom.ipc.tabs.shutdownTimeoutSecs": 0,
-  "general.useragent.locale": "en-US",
-  "intl.locale.matchOS": "en-US",
-  "dom.indexedDB.experimental": true
-}
deleted file mode 100644
--- a/addon-sdk/source/test/private-browsing/helper.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const xulApp = require("sdk/system/xul-app");
-const { open: openWindow, getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { openTab, getTabContentWindow, getActiveTab, setTabURL, closeTab } = require('sdk/tabs/utils');
-const promise = require("sdk/core/promise");
-const windowHelpers = require('sdk/window/helpers');
-const events = require("sdk/system/events");
-
-exports.openWebpage = function openWebpage(url, enablePrivate) {
-  if (xulApp.is("Fennec")) {
-    let chromeWindow = getMostRecentBrowserWindow();
-    let rawTab = openTab(chromeWindow, url, {
-      isPrivate: enablePrivate
-    });
-
-    return {
-      ready: promise.resolve(getTabContentWindow(rawTab)),
-      close: function () {
-        closeTab(rawTab);
-        // Returns a resolved promise as there is no need to wait
-        return promise.resolve();
-      }
-    };
-  }
-  else {
-    let win = openWindow(null, {
-      features: {
-        private: enablePrivate
-      }
-    });
-    let deferred = promise.defer();
-
-    // Wait for delayed startup code to be executed, in order to ensure
-    // that the window is really ready
-    events.on("browser-delayed-startup-finished", function onReady({subject}) {
-      if (subject == win) {
-        events.off("browser-delayed-startup-finished", onReady);
-        deferred.resolve(win);
-
-        let rawTab = getActiveTab(win);
-        setTabURL(rawTab, url);
-        deferred.resolve(getTabContentWindow(rawTab));
-      }
-    }, true);
-
-    return {
-      ready: deferred.promise,
-      close: function () {
-        return windowHelpers.close(win);
-      }
-    };
-  }
-  return null;
-}
deleted file mode 100644
--- a/addon-sdk/source/test/private-browsing/tabs.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Ci } = require('chrome');
-const { openTab, closeTab } = require('sdk/tabs/utils');
-const { browserWindows } = require('sdk/windows');
-const { isPrivate } = require('sdk/private-browsing');
-
-exports.testIsPrivateOnTab = function(assert) {
-  let window = browserWindows.activeWindow;
-  assert.ok(!isPrivate(chromeWindow), 'the top level window is not private');
-
-  let rawTab = openTab(chromeWindow, 'data:text/html,<h1>Hi!</h1>', {
-    isPrivate: true
-  });
-
-  // test that the tab is private
-  assert.ok(rawTab.browser.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing);
-  assert.ok(isPrivate(rawTab.browser.contentWindow));
-  assert.ok(isPrivate(rawTab.browser));
-
-  closeTab(rawTab);
-};
deleted file mode 100644
--- a/addon-sdk/source/test/private-browsing/windows.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';
-
-const { onFocus, openDialog, open } = require('sdk/window/utils');
-const { open: openPromise, close, focus, promise } = require('sdk/window/helpers');
-const { isPrivate } = require('sdk/private-browsing');
-const { getMode } = require('sdk/private-browsing/utils');
-const { browserWindows: windows } = require('sdk/windows');
-const { defer } = require('sdk/core/promise');
-const tabs = require('sdk/tabs');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { cleanUI } = require("sdk/test/utils");
-
-// test openDialog() from window/utils with private option
-// test isActive state in pwpb case
-// test isPrivate on ChromeWindow
-exports.testPerWindowPrivateBrowsingGetter = function*(assert) {
-  let win = openDialog({ private: true });
-
-  yield promise(win, 'DOMContentLoaded');
-
-  assert.equal(getMode(win), true, 'Newly opened window is in PB mode');
-  assert.ok(isPrivate(win), 'isPrivate(window) is true');
-
-  yield close(win);
-}
-
-// test open() from window/utils with private feature
-// test isActive state in pwpb case
-// test isPrivate on ChromeWindow
-exports.testPerWindowPrivateBrowsingGetter = function*(assert) {
-  let win = open('chrome://browser/content/browser.xul', {
-    features: {
-      private: true
-    }
-  });
-
-  yield promise(win, 'DOMContentLoaded');
-  assert.equal(getMode(win), true, 'Newly opened window is in PB mode');
-  assert.ok(isPrivate(win), 'isPrivate(window) is true');
-  yield close(win)
-}
-
-exports.testIsPrivateOnWindowOpen = function*(assert) {
-  let window = yield new Promise(resolve => {
-    windows.open({
-      isPrivate: true,
-      onOpen: resolve
-    });
-  });
-
-  assert.equal(isPrivate(window), false, 'isPrivate for a window is true when it should be');
-  assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
-
-  yield cleanUI();
-}
-
-exports.testIsPrivateOnWindowOpenFromPrivate = function(assert, done) {
-    // open a private window
-    openPromise(null, {
-      features: {
-        private: true,
-        chrome: true,
-        titlebar: true,
-        toolbar: true
-      }
-    }).then(focus).then(function(window) {
-      let { promise, resolve } = defer();
-
-      assert.equal(isPrivate(window), true, 'the only open window is private');
-
-      windows.open({
-        url: 'about:blank',
-        onOpen: function(w) {
-          assert.equal(isPrivate(w), false, 'new test window is not private');
-          w.close(() => resolve(window));
-        }
-      });
-
-      return promise;
-    }).then(close).
-       then(done, assert.fail);
-};
-
-exports.testOpenTabWithPrivateWindow = function*(assert) {
-  let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
-
-  assert.pass("loading new private window");
-
-  yield promise(window, 'load').then(focus);
-
-  assert.equal(isPrivate(window), true, 'the focused window is private');
-
-  yield new Promise(resolve => tabs.open({
-    url: 'about:blank',
-    onOpen: (tab) => {
-      assert.equal(isPrivate(tab), false, 'the opened tab is not private');
-      tab.close(resolve);
-    }
-  }));
-
-  yield close(window);
-};
-
-exports.testIsPrivateOnWindowOff = function(assert, done) {
-  windows.open({
-    onOpen: function(window) {
-      assert.equal(isPrivate(window), false, 'isPrivate for a window is false when it should be');
-      assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
-      window.close(done);
-    }
-  })
-}
deleted file mode 100644
--- a/addon-sdk/source/test/querystring/test-querystring.js
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-"use strict";
-
-// test using assert
-var qs = require('sdk/querystring');
-
-// folding block, commented to pass gjslint
-// {{{
-// [ wonkyQS, canonicalQS, obj ]
-var qsTestCases = [
-  ['foo=918854443121279438895193',
-   'foo=918854443121279438895193',
-   {'foo': '918854443121279438895193'}],
-  ['foo=bar', 'foo=bar', {'foo': 'bar'}],
-  //['foo=bar&foo=quux', 'foo=bar&foo=quux', {'foo': ['bar', 'quux']}],
-  ['foo=1&bar=2', 'foo=1&bar=2', {'foo': '1', 'bar': '2'}],
-  // ['my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F',
-  // 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F',
-  // {'my weird field': 'q1!2"\'w$5&7/z8)?' }],
-  ['foo%3Dbaz=bar', 'foo%3Dbaz=bar', {'foo=baz': 'bar'}],
-  ['foo=baz=bar', 'foo=baz%3Dbar', {'foo': 'baz=bar'}],
-  /*
-  ['str=foo&arr=1&arr=2&arr=3&somenull=&undef=',
-   'str=foo&arr=1&arr=2&arr=3&somenull=&undef=',
-   { 'str': 'foo',
-     'arr': ['1', '2', '3'],
-     'somenull': '',
-     'undef': ''}],
-  */
-  //[' foo = bar ', '%20foo%20=%20bar%20', {' foo ': ' bar '}],
-  // disable test that fails ['foo=%zx', 'foo=%25zx', {'foo': '%zx'}],
-  ['foo=%EF%BF%BD', 'foo=%EF%BF%BD', {'foo': '\ufffd' }]
-];
-
-// [ wonkyQS, canonicalQS, obj ]
-var qsColonTestCases = [
-  ['foo:bar', 'foo:bar', {'foo': 'bar'}],
-  //['foo:bar;foo:quux', 'foo:bar;foo:quux', {'foo': ['bar', 'quux']}],
-  ['foo:1&bar:2;baz:quux',
-   'foo:1%26bar%3A2;baz:quux',
-   {'foo': '1&bar:2', 'baz': 'quux'}],
-  ['foo%3Abaz:bar', 'foo%3Abaz:bar', {'foo:baz': 'bar'}],
-  ['foo:baz:bar', 'foo:baz%3Abar', {'foo': 'baz:bar'}]
-];
-
-// [wonkyObj, qs, canonicalObj]
-var extendedFunction = function() {};
-extendedFunction.prototype = {a: 'b'};
-var qsWeirdObjects = [
-  //[{regexp: /./g}, 'regexp=', {'regexp': ''}],
-  //[{regexp: new RegExp('.', 'g')}, 'regexp=', {'regexp': ''}],
-  //[{fn: function() {}}, 'fn=', {'fn': ''}],
-  //[{fn: new Function('')}, 'fn=', {'fn': ''}],
-  //[{math: Math}, 'math=', {'math': ''}],
-  //[{e: extendedFunction}, 'e=', {'e': ''}],
-  //[{d: new Date()}, 'd=', {'d': ''}],
-  //[{d: Date}, 'd=', {'d': ''}],
-  //[{f: new Boolean(false), t: new Boolean(true)}, 'f=&t=', {'f': '', 't': ''}],
-  [{f: false, t: true}, 'f=false&t=true', {'f': 'false', 't': 'true'}],
-  //[{n: null}, 'n=', {'n': ''}],
-  //[{nan: NaN}, 'nan=', {'nan': ''}],
-  //[{inf: Infinity}, 'inf=', {'inf': ''}]
-];
-// }}}
-
-var qsNoMungeTestCases = [
-  ['', {}],
-  //['foo=bar&foo=baz', {'foo': ['bar', 'baz']}],
-  ['blah=burp', {'blah': 'burp'}],
-  //['gragh=1&gragh=3&goo=2', {'gragh': ['1', '3'], 'goo': '2'}],
-  ['frappucino=muffin&goat%5B%5D=scone&pond=moose',
-   {'frappucino': 'muffin', 'goat[]': 'scone', 'pond': 'moose'}],
-  ['trololol=yes&lololo=no', {'trololol': 'yes', 'lololo': 'no'}]
-];
-
-exports['test basic'] = function(assert) {
-  assert.strictEqual('918854443121279438895193',
-                   qs.parse('id=918854443121279438895193').id,
-                   'prase id=918854443121279438895193');
-};
-
-exports['test that the canonical qs is parsed properly'] = function(assert) {
-  qsTestCases.forEach(function(testCase) {
-    assert.deepEqual(testCase[2], qs.parse(testCase[0]),
-                     'parse ' + testCase[0]);
-  });
-};
-
-
-exports['test that the colon test cases can do the same'] = function(assert) {
-  qsColonTestCases.forEach(function(testCase) {
-    assert.deepEqual(testCase[2], qs.parse(testCase[0], ';', ':'),
-                     'parse ' + testCase[0] + ' -> ; :');
-  });
-};
-
-exports['test the weird objects, that they get parsed properly'] = function(assert) {
-  qsWeirdObjects.forEach(function(testCase) {
-    assert.deepEqual(testCase[2], qs.parse(testCase[1]),
-                     'parse ' + testCase[1]);
-  });
-};
-
-exports['test non munge test cases'] = function(assert) {
-  qsNoMungeTestCases.forEach(function(testCase) {
-    assert.deepEqual(testCase[0], qs.stringify(testCase[1], '&', '=', false),
-                     'stringify ' + JSON.stringify(testCase[1]) + ' -> & =');
-  });
-};
-
-exports['test the nested qs-in-qs case'] = function(assert) {
-  var f = qs.parse('a=b&q=x%3Dy%26y%3Dz');
-  f.q = qs.parse(f.q);
-  assert.deepEqual(f, { a: 'b', q: { x: 'y', y: 'z' } },
-                   'parse a=b&q=x%3Dy%26y%3Dz');
-};
-
-exports['test nested in colon'] = function(assert) {
-  var f = qs.parse('a:b;q:x%3Ay%3By%3Az', ';', ':');
-  f.q = qs.parse(f.q, ';', ':');
-  assert.deepEqual(f, { a: 'b', q: { x: 'y', y: 'z' } },
-                   'parse a:b;q:x%3Ay%3By%3Az -> ; :');
-};
-
-exports['test stringifying'] = function(assert) {
-  qsTestCases.forEach(function(testCase) {
-    assert.equal(testCase[1], qs.stringify(testCase[2]),
-                 'stringify ' + JSON.stringify(testCase[2]));
-  });
-
-  qsColonTestCases.forEach(function(testCase) {
-    assert.equal(testCase[1], qs.stringify(testCase[2], ';', ':'),
-                 'stringify ' + JSON.stringify(testCase[2]) + ' -> ; :');
-  });
-
-  qsWeirdObjects.forEach(function(testCase) {
-    assert.equal(testCase[1], qs.stringify(testCase[0]),
-                 'stringify ' + JSON.stringify(testCase[0]));
-  });
-};
-
-exports['test stringifying nested'] = function(assert) {
-  var f = qs.stringify({
-    a: 'b',
-    q: qs.stringify({
-      x: 'y',
-      y: 'z'
-    })
-  });
-  assert.equal(f, 'a=b&q=x%3Dy%26y%3Dz',
-               JSON.stringify({
-                  a: 'b',
-                  'qs.stringify -> q': {
-                    x: 'y',
-                    y: 'z'
-                  }
-                }));
-
-  var threw = false;
-  try { qs.parse(undefined); } catch(error) { threw = true; }
-  assert.ok(!threw, "does not throws on undefined");
-};
-
-exports['test nested in colon'] = function(assert) {
-  var f = qs.stringify({
-    a: 'b',
-    q: qs.stringify({
-      x: 'y',
-      y: 'z'
-    }, ';', ':')
-  }, ';', ':');
-  assert.equal(f, 'a:b;q:x%3Ay%3By%3Az',
-               'stringify ' + JSON.stringify({
-                  a: 'b',
-                  'qs.stringify -> q': {
-                    x: 'y',
-                    y: 'z'
-                  }
-                }) + ' -> ; : ');
-
-
-  assert.deepEqual({}, qs.parse(), 'parse undefined');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/sidebar/utils.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cu } = require('chrome');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { fromIterator } = require('sdk/util/array');
-
-const BUILTIN_SIDEBAR_MENUITEMS = exports.BUILTIN_SIDEBAR_MENUITEMS = [
-  'menu_socialSidebar',
-  'menu_historySidebar',
-  'menu_bookmarksSidebar',
-  'menu_tabsSidebar',
-];
-
-function isSidebarShowing(window) {
-  window = window || getMostRecentBrowserWindow();
-  let sidebar = window.document.getElementById('sidebar-box');
-  return !sidebar.hidden;
-}
-exports.isSidebarShowing = isSidebarShowing;
-
-function getSidebarMenuitems(window) {
-  window = window || getMostRecentBrowserWindow();
-  return fromIterator(window.document.querySelectorAll('#viewSidebarMenu menuitem'));
-}
-exports.getSidebarMenuitems = getSidebarMenuitems;
-
-function getExtraSidebarMenuitems() {
-  let menuitems = getSidebarMenuitems();
-  return menuitems.filter(function(mi) {
-    return BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) < 0;
-  });
-}
-exports.getExtraSidebarMenuitems = getExtraSidebarMenuitems;
-
-function makeID(id) {
-  return 'jetpack-sidebar-' + id;
-}
-exports.makeID = makeID;
-
-function simulateCommand(ele) {
-  let window = ele.ownerGlobal;
-  let { document } = window;
-  var evt = document.createEvent('XULCommandEvent');
-  evt.initCommandEvent('command', true, true, window,
-    0, false, false, false, false, null, 0);
-  ele.dispatchEvent(evt);
-}
-exports.simulateCommand = simulateCommand;
-
-function simulateClick(ele) {
-  let window = ele.ownerGlobal;
-  let { document } = window;
-  let evt = document.createEvent('MouseEvents');
-  evt.initMouseEvent('click', true, true, window,
-    0, 0, 0, 0, 0, false, false, false, false, 0, null);
-  ele.dispatchEvent(evt);
-}
-exports.simulateClick = simulateClick;
-
-// OSX and Windows exhibit different behaviors when 'checked' is false,
-// so compare against the consistent 'true'. See bug 894809.
-function isChecked(node) {
-  return node.getAttribute('checked') === 'true';
-};
-exports.isChecked = isChecked;
deleted file mode 100644
--- a/addon-sdk/source/test/tabs/test-fennec-tabs.js
+++ /dev/null
@@ -1,595 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { Loader, LoaderWithHookedConsole } = require('sdk/test/loader');
-const timer = require('sdk/timers');
-const tabs = require('sdk/tabs');
-const windows = require('sdk/windows');
-const { set: setPref } = require("sdk/preferences/service");
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-const tabsLen = tabs.length;
-const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
-
-// Fennec error message dispatched on all currently unimplement tab features,
-// that match LoaderWithHookedConsole messages object pattern
-const ERR_FENNEC_MSG = {
-  type: "error",
-  msg: "This method is not yet supported by Fennec"
-};
-
-// TEST: tab unloader
-exports.testAutomaticDestroy = function(assert, done) {
-  let called = false;
-
-  let loader2 = Loader(module);
-  let loader3 = Loader(module);
-  let tabs2 = loader2.require('sdk/tabs');
-  let tabs3 = loader3.require('sdk/tabs');
-  let tabs2Len = tabs2.length;
-
-  tabs2.on('open', function onOpen(tab) {
-    assert.fail("an onOpen listener was called that should not have been");
-    called = true;
-  });
-  tabs2.on('ready', function onReady(tab) {
-    assert.fail("an onReady listener was called that should not have been");
-    called = true;
-  });
-  tabs2.on('select', function onSelect(tab) {
-    assert.fail("an onSelect listener was called that should not have been");
-    called = true;
-  });
-  tabs2.on('close', function onClose(tab) {
-    assert.fail("an onClose listener was called that should not have been");
-    called = true;
-  });
-  loader2.unload();
-
-  tabs3.on('open', function onOpen(tab) {
-    assert.pass("an onOpen listener was called for tabs3");
-
-    tab.on('ready', function onReady(tab) {
-      assert.fail("an onReady listener was called that should not have been");
-      called = true;
-    });
-    tab.on('select', function onSelect(tab) {
-      assert.fail("an onSelect listener was called that should not have been");
-      called = true;
-    });
-    tab.on('close', function onClose(tab) {
-      assert.fail("an onClose listener was called that should not have been");
-      called = true;
-    });
-  });
-  tabs3.open(URL.replace(/#title#/, 'tabs3'));
-  loader3.unload();
-
-  // Fire a tab event and ensure that the destroyed tab is inactive
-  tabs.once('open', function(tab) {
-    assert.pass('tabs.once("open") works!');
-
-    assert.equal(tabs2Len, tabs2.length, "tabs2 length was not changed");
-    assert.equal(tabs.length, (tabs2.length+2), "tabs.length > tabs2.length");
-
-    tab.once('ready', function() {
-      assert.pass('tab.once("ready") works!');
-
-      tab.once('close', function() {
-        assert.pass('tab.once("close") works!');
-
-        timer.setTimeout(function () {
-          assert.ok(!called, "Unloaded tab module is destroyed and inactive");
-
-          // end test
-          done();
-        });
-      });
-
-      tab.close();
-    });
-  });
-
-  tabs.open('data:text/html;charset=utf-8,foo');
-};
-
-// TEST: tab properties
-exports.testTabProperties = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
-  let tabsLen = tabs.length;
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      assert.equal(tab.title, "foo", "title of the new tab matches");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.style, null, "style of the new tab matches");
-      assert.equal(tab.index, tabsLen, "index of the new tab matches");
-      assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
-      assert.notEqual(tab.id, null, "a tab object always has an id property");
-
-      tab.close(function() {
-        loader.unload();
-
-        // end test
-        done();
-      });
-    }
-  });
-};
-
-// TEST: tabs iterator and length property
-exports.testTabsIteratorAndLength = function(assert, done) {
-  let newTabs = [];
-  let startCount = 0;
-  for (let t of tabs) startCount++;
-
-  assert.equal(startCount, tabs.length, "length property is correct");
-
-  let url = "data:text/html;charset=utf-8,testTabsIteratorAndLength";
-  tabs.open({url: url, onOpen: tab => newTabs.push(tab)});
-  tabs.open({url: url, onOpen: tab => newTabs.push(tab)});
-  tabs.open({
-    url: url,
-    onOpen: function(tab) {
-      let count = 0;
-      for (let t of tabs) count++;
-      assert.equal(count, startCount + 3, "iterated tab count matches");
-      assert.equal(startCount + 3, tabs.length, "iterated tab count matches length property");
-
-      let newTabsLength = newTabs.length;
-      newTabs.forEach(t => t.close(function() {
-        if (--newTabsLength > 0) return;
-
-        tab.close(done);
-      }));
-    }
-  });
-};
-
-// TEST: tab.url setter
-exports.testTabLocation = function(assert, done) {
-  let url1 = "data:text/html;charset=utf-8,foo";
-  let url2 = "data:text/html;charset=utf-8,bar";
-
-  tabs.on('ready', function onReady(tab) {
-    if (tab.url != url2)
-      return;
-
-    tabs.removeListener('ready', onReady);
-    assert.pass("tab loaded the correct url");
-
-    tab.close(done);
-  });
-
-  tabs.open({
-    url: url1,
-    onOpen: function(tab) {
-      tab.url = url2;
-    }
-  });
-};
-
-// TEST: tab.move()
-exports.testTabMove = function(assert, done) {
-  let { loader, messages } = LoaderWithHookedConsole();
-  let tabs = loader.require('sdk/tabs');
-
-  let url = "data:text/html;charset=utf-8,testTabMove";
-
-  tabs.open({
-    url: url,
-    onOpen: function(tab1) {
-      assert.ok(tab1.index >= 0, "opening a tab returns a tab w/ valid index");
-
-      tabs.open({
-        url: url,
-        onOpen: function(tab) {
-          let i = tab.index;
-          assert.ok(tab.index > tab1.index, "2nd tab has valid index");
-          tab.index = 0;
-          assert.equal(tab.index, i, "tab index after move matches");
-          assert.equal(JSON.stringify(messages),
-                           JSON.stringify([ERR_FENNEC_MSG]),
-                           "setting tab.index logs error");
-          // end test
-          tab1.close(() => tab.close(function() {
-            loader.unload();
-            done();
-          }));
-        }
-      });
-    }
-  });
-};
-
-// TEST: open tab with default options
-exports.testTabsOpen_alt = function(assert, done) {
-  let { loader, messages } = LoaderWithHookedConsole();
-  let tabs = loader.require('sdk/tabs');
-  let url = "data:text/html;charset=utf-8,default";
-
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tabs.activeTab, tab, "URL of active tab in the current window matches");
-      assert.equal(tab.isPinned, false, "The new tab is not pinned");
-      assert.equal(messages.length, 1, "isPinned logs error");
-
-      // end test
-      tab.close(function() {
-        loader.unload();
-        done();
-      });
-    }
-  });
-};
-
-// TEST: open pinned tab
-exports.testOpenPinned_alt = function(assert, done) {
-    let { loader, messages } = LoaderWithHookedConsole();
-    let tabs = loader.require('sdk/tabs');
-    let url = "about:blank";
-
-    tabs.open({
-      url: url,
-      isPinned: true,
-      onOpen: function(tab) {
-        assert.equal(tab.isPinned, false, "The new tab is pinned");
-        // We get two error message: one for tabs.open's isPinned argument
-        // and another one for tab.isPinned
-        assert.equal(JSON.stringify(messages),
-                         JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
-                         "isPinned logs error");
-
-        // end test
-        tab.close(function() {
-          loader.unload();
-          done();
-        });
-      }
-    });
-};
-
-// TEST: pin/unpin opened tab
-exports.testPinUnpin_alt = function(assert, done) {
-    let { loader, messages } = LoaderWithHookedConsole();
-    let tabs = loader.require('sdk/tabs');
-    let url = "data:text/html;charset=utf-8,default";
-
-    tabs.open({
-      url: url,
-      onOpen: function(tab) {
-        tab.pin();
-        assert.equal(tab.isPinned, false, "The tab was pinned correctly");
-        assert.equal(JSON.stringify(messages),
-                         JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
-                         "tab.pin() logs error");
-
-        // Clear console messages for the following test
-        messages.length = 0;
-
-        tab.unpin();
-        assert.equal(tab.isPinned, false, "The tab was unpinned correctly");
-        assert.equal(JSON.stringify(messages),
-                         JSON.stringify([ERR_FENNEC_MSG, ERR_FENNEC_MSG]),
-                         "tab.unpin() logs error");
-
-        // end test
-        tab.close(function() {
-          loader.unload();
-          done();
-        });
-      }
-    });
-};
-
-// TEST: open tab in background
-exports.testInBackground = function(assert, done) {
-  let activeUrl = tabs.activeTab.url;
-  let url = "data:text/html;charset=utf-8,background";
-  let window = windows.browserWindows.activeWindow;
-  tabs.once('ready', function onReady(tab) {
-    assert.equal(tabs.activeTab.url, activeUrl, "URL of active tab has not changed");
-    assert.equal(tab.url, url, "URL of the new background tab matches");
-    assert.equal(windows.browserWindows.activeWindow, window, "a new window was not opened");
-    assert.notEqual(tabs.activeTab.url, url, "URL of active tab is not the new URL");
-
-    // end test
-    tab.close(done);
-  });
-
-  tabs.open({
-    url: url,
-    inBackground: true
-  });
-};
-
-// TEST: open tab in new window
-exports.testOpenInNewWindow = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,newwindow";
-  let window = windows.browserWindows.activeWindow;
-
-  tabs.open({
-    url: url,
-    inNewWindow: true,
-    onReady: function(tab) {
-      assert.equal(windows.browserWindows.length, 1, "a new window was not opened");
-      assert.equal(windows.browserWindows.activeWindow, window, "old window is active");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tabs.activeTab, tab, "tab is the activeTab");
-
-      tab.close(done);
-    }
-  });
-};
-
-// TEST: onOpen event handler
-exports.testTabsEvent_onOpen = function(assert, done) {
-  let url = URL.replace('#title#', 'testTabsEvent_onOpen');
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-  };
-  tabs.on('open', listener1);
-
-  // add listener via collection add
-  tabs.on('open', function listener2(tab) {
-    assert.equal(++eventCount, 2, "both listeners notified");
-    tabs.removeListener('open', listener1);
-    tabs.removeListener('open', listener2);
-
-    // ends test
-    tab.close(done);
-  });
-
-  tabs.open(url);
-};
-
-// TEST: onClose event handler
-exports.testTabsEvent_onClose = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,onclose";
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-  }
-  tabs.on('close', listener1);
-
-  // add listener via collection add
-  tabs.on('close', function listener2(tab) {
-    assert.equal(++eventCount, 2, "both listeners notified");
-    tabs.removeListener('close', listener1);
-    tabs.removeListener('close', listener2);
-
-    // end test
-    done();
-  });
-
-  tabs.on('ready', function onReady(tab) {
-    tabs.removeListener('ready', onReady);
-    tab.close();
-  });
-
-  tabs.open(url);
-};
-
-// TEST: onClose event handler when a window is closed
-exports.testTabsEvent_onCloseWindow = function(assert, done) {
-  let closeCount = 0, individualCloseCount = 0;
-  function listener() {
-    closeCount++;
-  }
-  tabs.on('close', listener);
-
-  // One tab is already open with the window
-  let openTabs = 0;
-  function testCasePossiblyLoaded(tab) {
-    tab.close(function() {
-      if (++openTabs == 3) {
-        tabs.removeListener("close", listener);
-
-        assert.equal(closeCount, 3, "Correct number of close events received");
-        assert.equal(individualCloseCount, 3,
-                         "Each tab with an attached onClose listener received a close " +
-                         "event when the window was closed");
-
-        done();
-      }
-    });
-  }
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,tab2",
-    onOpen: testCasePossiblyLoaded,
-    onClose: () => individualCloseCount++
-  });
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,tab3",
-    onOpen: testCasePossiblyLoaded,
-    onClose: () => individualCloseCount++
-  });
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,tab4",
-    onOpen: testCasePossiblyLoaded,
-    onClose: () => individualCloseCount++
-  });
-};
-
-// TEST: onReady event handler
-exports.testTabsEvent_onReady = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,onready";
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-  };
-  tabs.on('ready', listener1);
-
-  // add listener via collection add
-  tabs.on('ready', function listener2(tab) {
-    assert.equal(++eventCount, 2, "both listeners notified");
-    tabs.removeListener('ready', listener1);
-    tabs.removeListener('ready', listener2);
-
-    // end test
-    tab.close(done);
-  });
-
-  tabs.open(url);
-};
-
-// TEST: onActivate event handler
-exports.testTabsEvent_onActivate = function(assert, done) {
-    let url = "data:text/html;charset=utf-8,onactivate";
-    let eventCount = 0;
-
-    // add listener via property assignment
-    function listener1(tab) {
-      eventCount++;
-    };
-    tabs.on('activate', listener1);
-
-    // add listener via collection add
-    tabs.on('activate', function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      assert.equal(tab, tabs.activeTab, 'the active tab is correct');
-      tabs.removeListener('activate', listener1);
-      tabs.removeListener('activate', listener2);
-
-      // end test
-      tab.close(done);
-    });
-
-    tabs.open(url);
-};
-
-// TEST: onDeactivate event handler
-exports.testTabsEvent_onDeactivate = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,ondeactivate";
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-  };
-  tabs.on('deactivate', listener1);
-
-  // add listener via collection add
-  tabs.on('deactivate', function listener2(tab) {
-    assert.equal(++eventCount, 2, 'both listeners notified');
-    assert.notEqual(tab, tabs.activeTab, 'the active tab is not the deactivated tab');
-    tabs.removeListener('deactivate', listener1);
-    tabs.removeListener('deactivate', listener2);
-
-    // end test
-    tab.close(done);
-  });
-
-  tabs.on('activate', function onActivate(tab) {
-    tabs.removeListener('activate', onActivate);
-    tabs.open("data:text/html;charset=utf-8,foo");
-    tab.close();
-  });
-
-  tabs.open(url);
-};
-
-// TEST: per-tab event handlers
-exports.testPerTabEvents = function(assert, done) {
-  let eventCount = 0;
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,foo",
-    onOpen: function(tab) {
-      // add listener via property assignment
-      function listener1() {
-        eventCount++;
-      };
-      tab.on('ready', listener1);
-
-      // add listener via collection add
-      tab.on('ready', function listener2() {
-        assert.equal(eventCount, 1, "both listeners notified");
-        tab.removeListener('ready', listener1);
-        tab.removeListener('ready', listener2);
-
-        // end test
-        tab.close(done);
-      });
-    }
-  });
-};
-
-exports.testUniqueTabIds = function(assert, done) {
-  var tabs = require('sdk/tabs');
-  var tabIds = {};
-  var steps = [
-    function (index) {
-      tabs.open({
-        url: "data:text/html;charset=utf-8,foo",
-        onOpen: function(tab) {
-          tabIds['tab1'] = tab.id;
-          next(index);
-        }
-      });
-    },
-    function (index) {
-      tabs.open({
-        url: "data:text/html;charset=utf-8,bar",
-        onOpen: function(tab) {
-          tabIds['tab2'] = tab.id;
-          next(index);
-        }
-      });
-    },
-    function (index) {
-      assert.notEqual(tabIds.tab1, tabIds.tab2, "Tab ids should be unique.");
-      done();
-    }
-  ];
-
-  function next(index) {
-    if (index === steps.length) {
-      return;
-    }
-    let fn = steps[index];
-    index++;
-    fn(index);
-  }
-
-  next(0);
-}
-
-exports.testOnLoadEventWithDOM = function(assert, done) {
-  let count = 0;
-  let title = 'testOnLoadEventWithDOM';
-
-  tabs.open({
-    url: 'data:text/html;charset=utf-8,<title>' + title + '</title>',
-    inBackground: true,
-    onLoad: function(tab) {
-      assert.equal(tab.title, title, 'tab passed in as arg, load called');
-
-      if (++count > 1) {
-        assert.pass('onLoad event called on reload');
-        tab.close(done);
-      }
-      else {
-        assert.pass('first onLoad event occured');
-        tab.reload();
-      }
-    }
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/tabs/test-firefox-tabs.js
+++ /dev/null
@@ -1,1305 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const systemEvents = require("sdk/system/events");
-const { setTimeout, setImmediate } = require('sdk/timers');
-const { modelFor } = require('sdk/model/core');
-const { viewFor } = require('sdk/view/core');
-const { getOwnerWindow } = require('sdk/tabs/utils');
-const { windows, onFocus, getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { open, focus, close } = require('sdk/window/helpers');
-const { observer: windowObserver } = require("sdk/windows/observer");
-const tabs = require('sdk/tabs');
-const { browserWindows } = require('sdk/windows');
-const { set: setPref, get: getPref, reset: resetPref } = require("sdk/preferences/service");
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-const OPEN_IN_NEW_WINDOW_PREF = 'browser.link.open_newwindow';
-const DISABLE_POPUP_PREF = 'dom.disable_open_during_load';
-const fixtures = require("../fixtures");
-const { base64jpeg } = fixtures;
-const { cleanUI, before, after } = require("sdk/test/utils");
-const { wait } = require('../event/helpers');
-
-// Bug 682681 - tab.title should never be empty
-exports.testBug682681_aboutURI = function(assert, done) {
-  let url = 'chrome://browser/locale/tabbrowser.properties';
-  let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
-                        getService(Ci.nsIStringBundleService).
-                        createBundle(url);
-  let emptyTabTitle = stringBundle.GetStringFromName('tabs.emptyTabTitle');
-
-  tabs.on('ready', function onReady(tab) {
-    tabs.removeListener('ready', onReady);
-
-    assert.equal(tab.title,
-                     emptyTabTitle,
-                     "title of about: tab is not blank");
-
-    tab.close(done);
-  });
-
-  // open a about: url
-  tabs.open({
-    url: "about:blank",
-    inBackground: true
-  });
-};
-
-// related to Bug 682681
-exports.testTitleForDataURI = function(assert, done) {
-  tabs.open({
-    url: "data:text/html;charset=utf-8,<title>tab</title>",
-    inBackground: true,
-    onReady: function(tab) {
-      assert.equal(tab.title, "tab", "data: title is not Connecting...");
-      tab.close(done);
-    }
-  });
-};
-
-// TEST: 'BrowserWindow' instance creation on tab 'activate' event
-// See bug 648244: there was a infinite loop.
-exports.testBrowserWindowCreationOnActivate = function(assert, done) {
-  let windows = require("sdk/windows").browserWindows;
-  let gotActivate = false;
-
-  tabs.once('activate', function onActivate(eventTab) {
-    assert.ok(windows.activeWindow, "Is able to fetch activeWindow");
-    gotActivate = true;
-  });
-
-  open().then(function(window) {
-    assert.ok(gotActivate, "Received activate event");
-    return close(window);
-  }).then(done).catch(assert.fail);
-}
-
-// TEST: tab unloader
-exports.testAutomaticDestroyEventOpen = function(assert, done) {
-  let called = false;
-  let loader = Loader(module);
-  let tabs2 = loader.require("sdk/tabs");
-  tabs2.on('open', _ => called = true);
-
-  // Fire a tab event and ensure that the destroyed tab is inactive
-  tabs.once('open', tab => {
-    setTimeout(_ => {
-      assert.ok(!called, "Unloaded tab module is destroyed and inactive");
-      tab.close(done);
-    });
-  });
-
-  loader.unload();
-  tabs.open("data:text/html;charset=utf-8,testAutomaticDestroyEventOpen");
-};
-
-exports.testAutomaticDestroyEventActivate = function(assert, done) {
-  let called = false;
-  let loader = Loader(module);
-  let tabs2 = loader.require("sdk/tabs");
-  tabs2.on('activate', _ => called = true);
-
-  // Fire a tab event and ensure that the destroyed tab is inactive
-  tabs.once('activate', tab => {
-    setTimeout(_ => {
-      assert.ok(!called, "Unloaded tab module is destroyed and inactive");
-      tab.close(done);
-    });
-  });
-
-  loader.unload();
-  tabs.open("data:text/html;charset=utf-8,testAutomaticDestroyEventActivate");
-};
-
-exports.testAutomaticDestroyEventDeactivate = function(assert, done) {
-  let called = false;
-  let currentTab = tabs.activeTab;
-  let loader = Loader(module);
-  let tabs2 = loader.require("sdk/tabs");
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,testAutomaticDestroyEventDeactivate",
-    onActivate: _ => setTimeout(_ => {
-      tabs2.on('deactivate', _ => called = true);
-
-      // Fire a tab event and ensure that the destroyed tab is inactive
-      tabs.once('deactivate', tab => {
-        setTimeout(_ => {
-          assert.ok(!called, "Unloaded tab module is destroyed and inactive");
-          tab.close(done);
-        });
-      });
-
-      loader.unload();
-      currentTab.activate();
-    })
-  });
-};
-
-exports.testAutomaticDestroyEventClose = function(assert, done) {
-  let called = false;
-  let loader = Loader(module);
-  let tabs2 = loader.require("sdk/tabs");
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,testAutomaticDestroyEventClose",
-    onReady: tab => {
-      tabs2.on('close', _ => called = true);
-
-      // Fire a tab event and ensure that the destroyed tab is inactive
-      tabs.once('close', tab => {
-        setTimeout(_ => {
-          assert.ok(!called, "Unloaded tab module is destroyed and inactive");
-          done();
-        });
-      });
-
-      loader.unload();
-      tab.close();
-    }
-  });
-};
-
-exports.testTabPropertiesInNewWindow = function(assert, done) {
-  const { LoaderWithFilteredConsole } = require("sdk/test/loader");
-  let loader = LoaderWithFilteredConsole(module, function(type, message) {
-    return true;
-  });
-
-  let tabs = loader.require('sdk/tabs');
-  let { viewFor } = loader.require('sdk/view/core');
-
-  let count = 0;
-  function onReadyOrLoad (tab) {
-    if (count++) {
-      close(getOwnerWindow(viewFor(tab))).then(done).catch(assert.fail);
-    }
-  }
-
-  let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
-  tabs.open({
-    inNewWindow: true,
-    url: url,
-    onReady: function(tab) {
-      assert.equal(tab.title, "foo", "title of the new tab matches");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
-      assert.equal(tab.style, null, "style of the new tab matches");
-      assert.equal(tab.index, 0, "index of the new tab matches");
-      assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
-      assert.notEqual(tab.id, null, "a tab object always has an id property.");
-
-      onReadyOrLoad(tab);
-    },
-    onLoad: function(tab) {
-      assert.equal(tab.title, "foo", "title of the new tab matches");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
-      assert.equal(tab.style, null, "style of the new tab matches");
-      assert.equal(tab.index, 0, "index of the new tab matches");
-      assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
-      assert.notEqual(tab.id, null, "a tab object always has an id property.");
-
-      onReadyOrLoad(tab);
-    }
-  });
-};
-
-exports.testTabPropertiesInSameWindow = function(assert, done) {
-  const { LoaderWithFilteredConsole } = require("sdk/test/loader");
-  let loader = LoaderWithFilteredConsole(module, function(type, message) {
-    return true;
-  });
-
-  let tabs = loader.require('sdk/tabs');
-
-  // Get current count of tabs so we know the index of the
-  // new tab, bug 893846
-  let tabCount = tabs.length;
-  let count = 0;
-  function onReadyOrLoad (tab) {
-    if (count++) {
-      tab.close(done);
-    }
-  }
-
-  let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      assert.equal(tab.title, "foo", "title of the new tab matches");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
-      assert.equal(tab.style, null, "style of the new tab matches");
-      assert.equal(tab.index, tabCount, "index of the new tab matches");
-      assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
-      assert.notEqual(tab.id, null, "a tab object always has an id property.");
-
-      onReadyOrLoad(tab);
-    },
-    onLoad: function(tab) {
-      assert.equal(tab.title, "foo", "title of the new tab matches");
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
-      assert.equal(tab.style, null, "style of the new tab matches");
-      assert.equal(tab.index, tabCount, "index of the new tab matches");
-      assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
-      assert.notEqual(tab.id, null, "a tab object always has an id property.");
-
-      onReadyOrLoad(tab);
-    }
-  });
-};
-
-// TEST: tab properties
-exports.testTabContentTypeAndReload = function(assert, done) {
-  open().then(focus).then(function(window) {
-    let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
-    let urlXML = "data:text/xml;charset=utf-8,<foo>bar</foo>";
-    tabs.open({
-      url: url,
-      onReady: function(tab) {
-        if (tab.url === url) {
-          assert.equal(tab.contentType, "text/html");
-          tab.url = urlXML;
-        }
-        else {
-          assert.equal(tab.contentType, "text/xml");
-          close(window).then(done).catch(assert.fail);
-        }
-      }
-    });
-  });
-};
-
-// TEST: tabs iterator and length property
-exports.testTabsIteratorAndLength = function(assert, done) {
-  open(null, { features: { chrome: true, toolbar: true } }).then(focus).then(function(window) {
-    let startCount = 0;
-    for (let t of tabs) startCount++;
-    assert.equal(startCount, tabs.length, "length property is correct");
-    let url = "data:text/html;charset=utf-8,default";
-
-    tabs.open(url);
-    tabs.open(url);
-    tabs.open({
-      url: url,
-      onOpen: function(tab) {
-        let count = 0;
-        for (let t of tabs) count++;
-        assert.equal(count, startCount + 3, "iterated tab count matches");
-        assert.equal(startCount + 3, tabs.length, "iterated tab count matches length property");
-
-        close(window).then(done).catch(assert.fail);
-      }
-    });
-  });
-};
-
-// TEST: tab.url setter
-exports.testTabLocation = function(assert, done) {
-  open().then(focus).then(function(window) {
-    let url1 = "data:text/html;charset=utf-8,foo";
-    let url2 = "data:text/html;charset=utf-8,bar";
-
-    tabs.on('ready', function onReady(tab) {
-      if (tab.url != url2)
-        return;
-      tabs.removeListener('ready', onReady);
-      assert.pass("tab.load() loaded the correct url");
-      close(window).then(done).catch(assert.fail);
-    });
-
-    tabs.open({
-      url: url1,
-      onOpen: function(tab) {
-        tab.url = url2
-      }
-    });
-  });
-};
-
-// TEST: tab.close()
-exports.testTabClose = function(assert, done) {
-  let testName = "testTabClose";
-  let url = "data:text/html;charset=utf-8," + testName;
-
-  assert.notEqual(tabs.activeTab.url, url, "tab is not the active tab");
-  tabs.once('ready', function onReady(tab) {
-    assert.equal(tabs.activeTab.url, tab.url, "tab is now the active tab");
-    assert.equal(url, tab.url, "tab url is the test url");
-    let secondOnCloseCalled = false;
-
-    // Bug 699450: Multiple calls to tab.close should not throw
-    tab.close(() => secondOnCloseCalled = true);
-    try {
-      tab.close(function () {
-        assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
-        assert.ok(secondOnCloseCalled,
-          "The immediate second call to tab.close happened");
-        assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
-
-        done();
-      });
-    }
-    catch(e) {
-      assert.fail("second call to tab.close() thrown an exception: " + e);
-    }
-  });
-
-  tabs.open(url);
-};
-
-// TEST: tab.move()
-exports.testTabMove = function(assert, done) {
-  open().then(focus).then(function(window) {
-    let url = "data:text/html;charset=utf-8,foo";
-
-    tabs.open({
-      url: url,
-      onOpen: function(tab) {
-        assert.equal(tab.index, 1, "tab index before move matches");
-        tab.index = 0;
-        assert.equal(tab.index, 0, "tab index after move matches");
-        close(window).then(done).catch(assert.fail);
-      }
-    });
-  }).catch(assert.fail);
-};
-
-exports.testIgnoreClosing = function*(assert) {
-  let url = "data:text/html;charset=utf-8,foobar";
-  let originalWindow = getMostRecentBrowserWindow();
-
-  let window = yield open().then(focus);
-
-  assert.equal(tabs.length, 2, "should be two windows open each with one tab");
-
-  yield new Promise(resolve => {
-    tabs.once("ready", (tab) => {
-      let win = tab.window;
-      assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
-      assert.equal(tabs.length, 3, "should be three tabs in total");
-
-      tab.close(() => {
-        assert.equal(win.tabs.length, 1, "should be one tab in the new window");
-        assert.equal(tabs.length, 2, "should be two tabs in total");
-        resolve();
-      });
-    });
-
-    tabs.open(url);
-  });
-};
-
-// TEST: open tab with default options
-exports.testOpen = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,default";
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      assert.equal(tab.url, url, "URL of the new tab matches");
-      assert.equal(tab.isPinned, false, "The new tab is not pinned");
-
-      tab.close(done);
-    }
-  });
-};
-
-// TEST: opening a pinned tab
-exports.testOpenPinned = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,default";
-  tabs.open({
-    url: url,
-    isPinned: true,
-    onOpen: function(tab) {
-      assert.equal(tab.isPinned, true, "The new tab is pinned");
-      tab.close(done);
-    }
-  });
-};
-
-// TEST: pin/unpin opened tab
-exports.testPinUnpin = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,default";
-  tabs.open({
-    url: url,
-    inBackground: true,
-    onOpen: function(tab) {
-      tab.pin();
-      assert.equal(tab.isPinned, true, "The tab was pinned correctly");
-      tab.unpin();
-      assert.equal(tab.isPinned, false, "The tab was unpinned correctly");
-      tab.close(done);
-    }
-  });
-}
-
-// TEST: open tab in background
-exports.testInBackground = function(assert, done) {
-  assert.equal(tabs.length, 1, "Should be one tab");
-
-  let window = getMostRecentBrowserWindow();
-  let activeUrl = tabs.activeTab.url;
-  let url = "data:text/html;charset=utf-8,background";
-  assert.equal(getMostRecentBrowserWindow(), window, "getMostRecentBrowserWindow() matches this window");
-  tabs.on('ready', function onReady(tab) {
-    tabs.removeListener('ready', onReady);
-    assert.equal(tabs.activeTab.url, activeUrl, "URL of active tab has not changed");
-    assert.equal(tab.url, url, "URL of the new background tab matches");
-    assert.equal(getMostRecentBrowserWindow(), window, "a new window was not opened");
-    assert.notEqual(tabs.activeTab.url, url, "URL of active tab is not the new URL");
-    tab.close(done);
-  });
-
-  tabs.open({
-    url: url,
-    inBackground: true
-  });
-}
-
-// TEST: open tab in new window
-exports.testOpenInNewWindow = function(assert, done) {
-  let startWindowCount = windows().length;
-
-  let url = "data:text/html;charset=utf-8,testOpenInNewWindow";
-  tabs.open({
-    url: url,
-    inNewWindow: true,
-    onReady: function(tab) {
-      let newWindow = getOwnerWindow(viewFor(tab));
-      assert.equal(windows().length, startWindowCount + 1, "a new window was opened");
-
-      onFocus(newWindow).then(function() {
-        assert.equal(getMostRecentBrowserWindow(), newWindow, "new window is active");
-        assert.equal(tab.url, url, "URL of the new tab matches");
-        assert.equal(newWindow.content.location, url, "URL of new tab in new window matches");
-        assert.equal(tabs.activeTab.url, url, "URL of activeTab matches");
-
-        return close(newWindow).then(done);
-      }).catch(assert.fail);
-    }
-  });
-
-}
-
-// Test tab.open inNewWindow + onOpen combination
-exports.testOpenInNewWindowOnOpen = function(assert, done) {
-  let startWindowCount = windows().length;
-
-  let url = "data:text/html;charset=utf-8,newwindow";
-  tabs.open({
-    url: url,
-    inNewWindow: true,
-    onOpen: function(tab) {
-      let newWindow = getOwnerWindow(viewFor(tab));
-
-      onFocus(newWindow).then(function() {
-        assert.equal(windows().length, startWindowCount + 1, "a new window was opened");
-        assert.equal(getMostRecentBrowserWindow(), newWindow, "new window is active");
-
-        close(newWindow).then(done).catch(assert.fail);
-      });
-    }
-  });
-};
-
-// TEST: onOpen event handler
-exports.testTabsEvent_onOpen = function(assert, done) {
-  open().then(focus).then(window => {
-    let url = "data:text/html;charset=utf-8,1";
-    let eventCount = 0;
-
-    // add listener via property assignment
-    function listener1(tab) {
-      eventCount++;
-    };
-    tabs.on('open', listener1);
-
-    // add listener via collection add
-    tabs.on('open', function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      tabs.removeListener('open', listener1);
-      tabs.removeListener('open', listener2);
-      close(window).then(done).catch(assert.fail);
-    });
-
-    tabs.open(url);
-  }).catch(assert.fail);
-};
-
-// TEST: onClose event handler
-exports.testTabsEvent_onClose = function*(assert) {
-  let window = yield open().then(focus);
-  let url = "data:text/html;charset=utf-8,onclose";
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-  }
-  tabs.on("close", listener1);
-
-  yield new Promise(resolve => {
-    // add listener via collection add
-    tabs.on("close", function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      tabs.removeListener("close", listener2);
-      resolve();
-    });
-
-    tabs.on('ready', function onReady(tab) {
-      tabs.removeListener('ready', onReady);
-      tab.close();
-    });
-
-    tabs.open(url);
-  });
-
-  tabs.removeListener("close", listener1);
-  assert.pass("done test!");
-
-  yield close(window);
-  assert.pass("window was closed!");
-};
-
-// TEST: onClose event handler when a window is closed
-exports.testTabsEvent_onCloseWindow = function(assert, done) {
-  let closeCount = 0;
-  let individualCloseCount = 0;
-
-  open().then(focus).then(window => {
-    assert.pass('opened a new window');
-
-    tabs.on("close", function listener() {
-      if (++closeCount == 4) {
-        tabs.removeListener("close", listener);
-      }
-    });
-
-    function endTest() {
-      if (++individualCloseCount < 3) {
-        assert.pass('tab closed ' + individualCloseCount);
-        return;
-      }
-
-      assert.equal(closeCount, 4, "Correct number of close events received");
-      assert.equal(individualCloseCount, 3,
-                   "Each tab with an attached onClose listener received a close " +
-                   "event when the window was closed");
-
-      done();
-    }
-
-    // One tab is already open with the window
-    let openTabs = 1;
-    function testCasePossiblyLoaded() {
-      if (++openTabs == 4) {
-        window.close();
-      }
-      assert.pass('tab opened ' + openTabs);
-    }
-
-    tabs.open({
-      url: "data:text/html;charset=utf-8,tab2",
-      onOpen: testCasePossiblyLoaded,
-      onClose: endTest
-    });
-
-    tabs.open({
-      url: "data:text/html;charset=utf-8,tab3",
-      onOpen: testCasePossiblyLoaded,
-      onClose: endTest
-    });
-
-    tabs.open({
-      url: "data:text/html;charset=utf-8,tab4",
-      onOpen: testCasePossiblyLoaded,
-      onClose: endTest
-    });
-  }).catch(assert.fail);
-}
-
-// TEST: onReady event handler
-exports.testTabsEvent_onReady = function(assert, done) {
-  open().then(focus).then(window => {
-    let url = "data:text/html;charset=utf-8,onready";
-    let eventCount = 0;
-
-    // add listener via property assignment
-    function listener1(tab) {
-      eventCount++;
-    };
-    tabs.on('ready', listener1);
-
-    // add listener via collection add
-    tabs.on('ready', function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      tabs.removeListener('ready', listener1);
-      tabs.removeListener('ready', listener2);
-      close(window).then(done);
-    });
-
-    tabs.open(url);
-  }).catch(assert.fail);
-};
-
-// TEST: onActivate event handler
-exports.testTabsEvent_onActivate = function(assert, done) {
-  open().then(focus).then(window => {
-    let url = "data:text/html;charset=utf-8,onactivate";
-    let eventCount = 0;
-
-    // add listener via property assignment
-    function listener1(tab) {
-      eventCount++;
-    };
-    tabs.on('activate', listener1);
-
-    // add listener via collection add
-    tabs.on('activate', function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      tabs.removeListener('activate', listener1);
-      tabs.removeListener('activate', listener2);
-      close(window).then(done).catch(assert.fail);
-    });
-
-    tabs.open(url);
-  }).catch(assert.fail);
-};
-
-// onDeactivate event handler
-exports.testTabsEvent_onDeactivate = function*(assert) {
-  let window = yield open().then(focus);
-
-  let url = "data:text/html;charset=utf-8,ondeactivate";
-  let eventCount = 0;
-
-  // add listener via property assignment
-  function listener1(tab) {
-    eventCount++;
-    assert.pass("listener1 was called " + eventCount);
-  };
-  tabs.on('deactivate', listener1);
-
-  yield new Promise(resolve => {
-    // add listener via collection add
-    tabs.on('deactivate', function listener2(tab) {
-      assert.equal(++eventCount, 2, "both listeners notified");
-      tabs.removeListener('deactivate', listener2);
-      resolve();
-    });
-
-    tabs.on('open', function onOpen(tab) {
-      assert.pass("tab opened");
-      tabs.removeListener('open', onOpen);
-      tabs.open("data:text/html;charset=utf-8,foo");
-    });
-
-    tabs.open(url);
-  });
-
-  tabs.removeListener('deactivate', listener1);
-  assert.pass("listeners were removed");
-};
-
-// pinning
-exports.testTabsEvent_pinning = function(assert, done) {
-  open().then(focus).then(window => {
-    let url = "data:text/html;charset=utf-8,1";
-
-    tabs.on('open', function onOpen(tab) {
-      tabs.removeListener('open', onOpen);
-      tab.pin();
-    });
-
-    tabs.on('pinned', function onPinned(tab) {
-      tabs.removeListener('pinned', onPinned);
-      assert.ok(tab.isPinned, "notified tab is pinned");
-      tab.unpin();
-    });
-
-    tabs.on('unpinned', function onUnpinned(tab) {
-      tabs.removeListener('unpinned', onUnpinned);
-      assert.ok(!tab.isPinned, "notified tab is not pinned");
-      close(window).then(done).catch(assert.fail);
-    });
-
-    tabs.open(url);
-  }).catch(assert.fail);
-};
-
-// TEST: per-tab event handlers
-exports.testPerTabEvents = function*(assert) {
-  let window = yield open().then(focus);
-  let eventCount = 0;
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: "data:text/html;charset=utf-8,foo",
-      onOpen: (tab) => {
-        assert.pass("the tab was opened");
-
-        // add listener via property assignment
-        function listener1() {
-          eventCount++;
-        };
-        tab.on('ready', listener1);
-
-        // add listener via collection add
-        tab.on('ready', function listener2() {
-          assert.equal(eventCount, 1, "listener1 called before listener2");
-          tab.removeListener('ready', listener1);
-          tab.removeListener('ready', listener2);
-          assert.pass("removed listeners");
-          eventCount++;
-          resolve();
-        });
-      }
-    });
-  });
-
-  assert.equal(eventCount, 2, "both listeners were notified.");
-};
-
-exports.testAttachOnMultipleDocuments = function (assert, done) {
-  // Example of attach that process multiple tab documents
-  open().then(focus).then(window => {
-    let firstLocation = "data:text/html;charset=utf-8,foobar";
-    let secondLocation = "data:text/html;charset=utf-8,bar";
-    let thirdLocation = "data:text/html;charset=utf-8,fox";
-    let onReadyCount = 0;
-    let worker1 = null;
-    let worker2 = null;
-    let detachEventCount = 0;
-
-    tabs.open({
-      url: firstLocation,
-      onReady: function (tab) {
-        onReadyCount++;
-        if (onReadyCount == 1) {
-          worker1 = tab.attach({
-            contentScript: 'self.on("message", ' +
-                           '  function () { return self.postMessage(document.location.href); }' +
-                           ');',
-            onMessage: function (msg) {
-              assert.equal(msg, firstLocation,
-                               "Worker url is equal to the 1st document");
-              tab.url = secondLocation;
-            },
-            onDetach: function () {
-              detachEventCount++;
-              assert.pass("Got worker1 detach event");
-              assert.throws(function () {
-                  worker1.postMessage("ex-1");
-                },
-                /Couldn't find the worker/,
-                "postMessage throw because worker1 is destroyed");
-              checkEnd();
-            }
-          });
-          worker1.postMessage("new-doc-1");
-        }
-        else if (onReadyCount == 2) {
-
-          worker2 = tab.attach({
-            contentScript: 'self.on("message", ' +
-                           '  function () { return self.postMessage(document.location.href); }' +
-                           ');',
-            onMessage: function (msg) {
-              assert.equal(msg, secondLocation,
-                               "Worker url is equal to the 2nd document");
-              tab.url = thirdLocation;
-            },
-            onDetach: function () {
-              detachEventCount++;
-              assert.pass("Got worker2 detach event");
-              assert.throws(function () {
-                  worker2.postMessage("ex-2");
-                },
-                /Couldn't find the worker/,
-                "postMessage throw because worker2 is destroyed");
-              checkEnd();
-            }
-          });
-          worker2.postMessage("new-doc-2");
-        }
-        else if (onReadyCount == 3) {
-          tab.close();
-        }
-      }
-    });
-
-    function checkEnd() {
-      if (detachEventCount != 2)
-        return;
-
-      assert.pass("Got all detach events");
-
-      close(window).then(done).catch(assert.fail);
-    }
-  }).catch(assert.fail);
-}
-
-
-exports.testAttachWrappers = function (assert, done) {
-  // Check that content script has access to wrapped values by default
-  open().then(focus).then(window => {
-    let document = "data:text/html;charset=utf-8,<script>var globalJSVar = true; " +
-                   "                       document.getElementById = 3;</script>";
-    let count = 0;
-
-    tabs.open({
-      url: document,
-      onReady: function (tab) {
-        let worker = tab.attach({
-          contentScript: 'try {' +
-                         '  self.postMessage(!("globalJSVar" in window));' +
-                         '  self.postMessage(typeof window.globalJSVar == "undefined");' +
-                         '} catch(e) {' +
-                         '  self.postMessage(e.message);' +
-                         '}',
-          onMessage: function (msg) {
-            assert.equal(msg, true, "Worker has wrapped objects ("+count+")");
-            if (count++ == 1)
-              close(window).then(done).catch(assert.fail);
-          }
-        });
-      }
-    });
-  }).catch(assert.fail);
-}
-
-/*
-// We do not offer unwrapped access to DOM since bug 601295 landed
-// See 660780 to track progress of unwrap feature
-exports.testAttachUnwrapped = function (assert, done) {
-  // Check that content script has access to unwrapped values through unsafeWindow
-  openBrowserWindow(function(window, browser) {
-    let document = "data:text/html;charset=utf-8,<script>var globalJSVar=true;</script>";
-    let count = 0;
-
-    tabs.open({
-      url: document,
-      onReady: function (tab) {
-        let worker = tab.attach({
-          contentScript: 'try {' +
-                         '  self.postMessage(unsafeWindow.globalJSVar);' +
-                         '} catch(e) {' +
-                         '  self.postMessage(e.message);' +
-                         '}',
-          onMessage: function (msg) {
-            assert.equal(msg, true, "Worker has access to javascript content globals ("+count+")");
-            close(window).then(done);
-          }
-        });
-      }
-    });
-
-  });
-}
-*/
-
-exports['test window focus changes active tab'] = function(assert, done) {
-  let url1 = "data:text/html;charset=utf-8," + encodeURIComponent("test window focus changes active tab</br><h1>Window #1");
-
-  let win1 = openBrowserWindow(function() {
-    assert.pass("window 1 is open");
-
-    let win2 = openBrowserWindow(function() {
-      assert.pass("window 2 is open");
-
-      focus(win2).then(function() {
-        tabs.on("activate", function onActivate(tab) {
-          tabs.removeListener("activate", onActivate);
-
-          if (tab.readyState === 'uninitialized') {
-            tab.once('ready', whenReady);
-          }
-          else {
-            whenReady(tab);
-          }
-
-          function whenReady(tab) {
-            assert.pass("activate was called on windows focus change.");
-            assert.equal(tab.url, url1, 'the activated tab url is correct');
-
-            return close(win2).then(function() {
-              assert.pass('window 2 was closed');
-              return close(win1);
-            }).then(done).catch(assert.fail);
-          }
-        });
-
-        win1.focus();
-      });
-    }, "data:text/html;charset=utf-8,test window focus changes active tab</br><h1>Window #2");
-  }, url1);
-};
-
-exports['test ready event on new window tab'] = function(assert, done) {
-  let uri = encodeURI("data:text/html;charset=utf-8,Waiting for ready event!");
-
-  require("sdk/tabs").on("ready", function onReady(tab) {
-    if (tab.url === uri) {
-      require("sdk/tabs").removeListener("ready", onReady);
-      assert.pass("ready event was emitted");
-      close(window).then(done).catch(assert.fail);
-    }
-  });
-
-  let window = openBrowserWindow(function(){}, uri);
-};
-
-exports['test unique tab ids'] = function(assert, done) {
-  var windows = require('sdk/windows').browserWindows;
-  var { all, defer } = require('sdk/core/promise');
-
-  function openWindow() {
-    let deferred = defer();
-    let win = windows.open({
-      url: "data:text/html;charset=utf-8,<html>foo</html>",
-    });
-
-    win.on('open', function(window) {
-      assert.ok(window.tabs.length);
-      assert.ok(window.tabs.activeTab);
-      assert.ok(window.tabs.activeTab.id);
-      deferred.resolve({
-        id: window.tabs.activeTab.id,
-        win: win
-      });
-    });
-
-    return deferred.promise;
-  }
-
-  var one = openWindow(), two = openWindow();
-  all([one, two]).then(function(results) {
-    assert.notEqual(results[0].id, results[1].id, "tab Ids should not be equal.");
-    results[0].win.close(function() {
-      results[1].win.close(function () {
-        done();
-      });
-    });
-  });
-}
-
-// related to Bug 671305
-exports.testOnLoadEventWithDOM = function(assert, done) {
-  let count = 0;
-  let title = 'testOnLoadEventWithDOM';
-
-  // open a about: url
-  tabs.open({
-    url: 'data:text/html;charset=utf-8,<title>' + title + '</title>',
-    inBackground: true,
-    onLoad: function(tab) {
-      assert.equal(tab.title, title, 'tab passed in as arg, load called');
-
-      if (++count > 1) {
-        assert.pass('onLoad event called on reload');
-        tab.close(done);
-      }
-      else {
-        assert.pass('first onLoad event occured');
-        tab.reload();
-      }
-    }
-  });
-};
-
-// related to Bug 671305
-exports.testOnLoadEventWithImage = function(assert, done) {
-  let count = 0;
-
-  tabs.open({
-    url: base64jpeg,
-    inBackground: true,
-    onLoad: function(tab) {
-      if (++count > 1) {
-        assert.pass('onLoad event called on reload with image');
-        tab.close(done);
-      }
-      else {
-        assert.pass('first onLoad event occured');
-        tab.reload();
-      }
-    }
-  });
-};
-
-exports.testNoDeadObjects = function(assert, done) {
-  let loader = Loader(module);
-  let myTabs = loader.require("sdk/tabs");
-
-  // Load a tab, unload our modules, and navigate the tab to trigger an event
-  // on it.  This would throw a dead object exception if our modules didn't
-  // clean up their event handlers on unload.
-  tabs.open({
-    url: "data:text/html;charset=utf-8,one",
-    onLoad: function(tab) {
-      // 2. Arrange to nuke the sandboxes and then trigger the load event
-      //    on the tab once the loader is kaput.
-      systemEvents.on("sdk:loader:destroy", function onUnload() {
-        systemEvents.off("sdk:loader:destroy", onUnload, true);
-        // Defer this carnage till the end of the event queue, to avoid nuking
-        // the sandboxes from under the modules as they're being cleaned up.
-        setTimeout(function() {
-          // 3. Arrange to close the tab once the second page loads.
-          tab.on("load", function() {
-            tab.close(function() {
-              let { viewFor } = loader.require("sdk/view/core");
-              assert.equal(viewFor(tab), undefined, "didn't retain the closed tab");
-              done();
-            });
-          });
-
-          // Trigger a load event on the tab, to give the now-unloaded
-          // myTabs a chance to choke on it.
-          tab.url = "data:text/html;charset=utf-8,two";
-        }, 0);
-      }, true);
-
-      // 1. Start unloading the modules.  Defer till the end of the event
-      //    queue, in case myTabs is attaching its own handlers here too.
-      //    We want it to latch on before we pull the rug from under it.
-      setTimeout(function() {
-        loader.unload();
-      }, 0);
-    }
-  });
-};
-
-exports.testTabDestroy = function(assert, done) {
-  let loader = Loader(module);
-  let myTabs = loader.require("sdk/tabs");
-  let { modelFor: myModelFor } = loader.require("sdk/model/core");
-  let { viewFor: myViewFor } = loader.require("sdk/view/core");
-  let myFirstTab = myTabs.activeTab;
-
-  myTabs.open({
-    url: "data:text/html;charset=utf-8,destroy",
-    onReady: (myTab) => setImmediate(() => {
-      let tab = modelFor(myViewFor(myTab));
-
-      function badListener(event, tab) {
-        // Ignore events for the other tabs
-        if (tab != myTab)
-          return;
-        assert.fail("Should not have seen the " + event + " listener called");
-      }
-
-      assert.ok(myTab, "Should have a tab in the test loader.");
-      assert.equal(myViewFor(myTab), viewFor(tab), "Should have the right view.");
-      assert.equal(myTabs.length, 2, "Should have the right number of global tabs.");
-      assert.equal(myTab.window.tabs.length, 2, "Should have the right number of window tabs.");
-      assert.equal(myTabs.activeTab, myTab, "Globally active tab is correct.");
-      assert.equal(myTab.window.tabs.activeTab, myTab, "Window active tab is correct.");
-
-      assert.equal(myTabs[1], myTab, "Global tabs list contains tab.");
-      assert.equal(myTab.window.tabs[1], myTab, "Window tabs list contains tab.");
-
-      myTab.once("ready", badListener.bind(null, "tab ready"));
-      myTab.once("deactivate", badListener.bind(null, "tab deactivate"));
-      myTab.once("activate", badListener.bind(null, "tab activate"));
-      myTab.once("close", badListener.bind(null, "tab close"));
-
-      myTab.destroy();
-
-      myTab.once("ready", badListener.bind(null, "new tab ready"));
-      myTab.once("deactivate", badListener.bind(null, "new tab deactivate"));
-      myTab.once("activate", badListener.bind(null, "new tab activate"));
-      myTab.once("close", badListener.bind(null, "new tab close"));
-
-      myTabs.once("ready", badListener.bind(null, "tabs ready"));
-      myTabs.once("deactivate", badListener.bind(null, "tabs deactivate"));
-      myTabs.once("activate", badListener.bind(null, "tabs activate"));
-      myTabs.once("close", badListener.bind(null, "tabs close"));
-
-      assert.equal(myViewFor(myTab), viewFor(tab), "Should have the right view.");
-      assert.equal(myModelFor(viewFor(tab)), myTab, "Can still reach the tab object.");
-      assert.equal(myTabs.length, 2, "Should have the right number of global tabs.");
-      assert.equal(myTab.window.tabs.length, 2, "Should have the right number of window tabs.");
-      assert.equal(myTabs.activeTab, myTab, "Globally active tab is correct.");
-      assert.equal(myTab.window.tabs.activeTab, myTab, "Window active tab is correct.");
-
-      assert.equal(myTabs[1], myTab, "Global tabs list still contains tab.");
-      assert.equal(myTab.window.tabs[1], myTab, "Window tabs list still contains tab.");
-
-      assert.equal(myTab.url, undefined, "url property is not usable");
-      assert.equal(myTab.contentType, undefined, "contentType property is not usable");
-      assert.equal(myTab.title, undefined, "title property is not usable");
-      assert.equal(myTab.id, undefined, "id property is not usable");
-      assert.equal(myTab.index, undefined, "index property is not usable");
-
-      myTab.pin();
-      assert.ok(!tab.isPinned, "pin method shouldn't work");
-
-      tabs.once("activate", () => setImmediate(() => {
-        assert.equal(myTabs.activeTab, myFirstTab, "Globally active tab is correct.");
-        assert.equal(myTab.window.tabs.activeTab, myFirstTab, "Window active tab is correct.");
-
-        let sawActivate = false;
-        tabs.once("activate", () => setImmediate(() => {
-          sawActivate = true;
-
-          assert.equal(myTabs.activeTab, myTab, "Globally active tab is correct.");
-          assert.equal(myTab.window.tabs.activeTab, myTab, "Window active tab is correct.");
-
-          // This shouldn't have any effect
-          myTab.close();
-
-          tab.once("ready", () => setImmediate(() => {
-            tab.close(() => {
-              loader.unload();
-              done();
-            });
-          }));
-          tab.url = "data:text/html;charset=utf-8,destroy2";
-        }));
-
-        myTab.activate();
-        setImmediate(() => {
-          assert.ok(!sawActivate, "activate method shouldn't have done anything");
-
-          tab.activate();
-        });
-      }));
-      myFirstTab.activate();
-    })
-  })
-};
-
-// related to bug 942511
-// https://bugzilla.mozilla.org/show_bug.cgi?id=942511
-exports['test active tab properties defined on popup closed'] = function (assert, done) {
-  setPref(OPEN_IN_NEW_WINDOW_PREF, 2);
-  setPref(DISABLE_POPUP_PREF, false);
-
-  let tabID = "";
-  let popupClosed = false;
-
-  tabs.open({
-    url: 'about:blank',
-    onReady: function (tab) {
-      tabID = tab.id;
-      tab.attach({
-        contentScript: 'var popup = window.open("about:blank");' +
-                       'popup.close();'
-      });
-      
-      windowObserver.once('close', () => {
-        popupClosed = true;
-      });
-
-      windowObserver.on('activate', () => {
-        // Only when the 'activate' event is fired after the popup was closed.
-        if (popupClosed) {
-          popupClosed = false;
-          let activeTabID = tabs.activeTab.id;
-          if (activeTabID) {
-              assert.equal(tabID, activeTabID, 'ActiveTab properties are correct');
-          }
-          else {
-            assert.fail('ActiveTab properties undefined on popup closed');
-          }
-          tab.close(done);
-        }
-      });
-    }
-  });
-};
-
-// related to bugs 922956 and 989288
-// https://bugzilla.mozilla.org/show_bug.cgi?id=922956
-// https://bugzilla.mozilla.org/show_bug.cgi?id=989288
-if (0) exports["test tabs ready and close after window.open"] = function*(assert, done) {
-  // ensure popups open in a new window and disable popup blocker
-  setPref(OPEN_IN_NEW_WINDOW_PREF, 2);
-  setPref(DISABLE_POPUP_PREF, false);
-
-  // open windows to trigger observers
-  tabs.activeTab.attach({
-    contentScript: "window.open('about:blank');" +
-                   "window.open('about:blank', '', " +
-                   "'width=800,height=600,resizable=no,status=no,location=no');"
-  });
-
-  let tab1 = yield wait(tabs, "ready");
-  assert.pass("first tab ready has occured");
-
-  let tab2 = yield wait(tabs, "ready");
-  assert.pass("second tab ready has occured");
-
-  tab1.close();
-  yield wait(tabs, "close");
-  assert.pass("first tab close has occured");
-
-  tab2.close();
-  yield wait(tabs, "close");
-  assert.pass("second tab close has occured");
-};
-
-// related to bug #939496
-exports["test tab open event for new window"] = function(assert, done) {
-  // ensure popups open in a new window and disable popup blocker
-  setPref(OPEN_IN_NEW_WINDOW_PREF, 2);
-  setPref(DISABLE_POPUP_PREF, false);
-
-  tabs.once('open', function onOpen(window) {
-    assert.pass("tab open has occured");
-    window.close(done);
-  });
-
-  // open window to trigger observers
-  browserWindows.open("about:logo");
-};
-
-after(exports, function*(name, assert) {
-  resetPopupPrefs();
-  yield cleanUI();
-});
-
-const resetPopupPrefs = () => {
-  resetPref(OPEN_IN_NEW_WINDOW_PREF);
-  resetPref(DISABLE_POPUP_PREF);
-};
-
-/******************* helpers *********************/
-
-// Utility function to open a new browser window.
-function openBrowserWindow(callback, url) {
-  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-           getService(Ci.nsIWindowWatcher);
-  let urlString = Cc["@mozilla.org/supports-string;1"].
-                  createInstance(Ci.nsISupportsString);
-  urlString.data = url;
-  let window = ww.openWindow(null, "chrome://browser/content/browser.xul",
-                             "_blank", "chrome,all,dialog=no", urlString);
-
-  if (callback) {
-    window.addEventListener("load", function onLoad(event) {
-      if (event.target && event.target.defaultView == window) {
-        window.removeEventListener("load", onLoad, true);
-        let browsers = window.document.getElementsByTagName("tabbrowser");
-        try {
-          setTimeout(function () {
-            callback(window, browsers[0]);
-          }, 10);
-        }
-        catch (e) {
-          console.exception(e);
-        }
-      }
-    }, true);
-  }
-
-  return window;
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/tabs/utils.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/. */
-"use strict";
-
-const { openTab: makeTab, getTabContentWindow } = require("sdk/tabs/utils");
-
-function openTab(rawWindow, url) {
-  return new Promise(resolve => {
-    let tab = makeTab(rawWindow, url);
-    let window = getTabContentWindow(tab);
-    if (window.document.readyState == "complete") {
-      return resolve();
-    }
-
-    window.addEventListener("load", function() {
-      resolve();
-    }, {capture: true, once: true});
-
-    return null;
-  })
-}
-exports.openTab = openTab;
deleted file mode 100644
--- a/addon-sdk/source/test/test-addon-bootstrap.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu, Cc, Ci } = require("chrome");
-const { create, evaluate } = require("./fixtures/bootstrap/utils");
-
-const ROOT = require.resolve("sdk/base64").replace("/sdk/base64.js", "");
-
-// Note: much of this test code is from
-// http://dxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm
-const BOOTSTRAP_REASONS = {
-  APP_STARTUP     : 1,
-  APP_SHUTDOWN    : 2,
-  ADDON_ENABLE    : 3,
-  ADDON_DISABLE   : 4,
-  ADDON_INSTALL   : 5,
-  ADDON_UNINSTALL : 6,
-  ADDON_UPGRADE   : 7,
-  ADDON_DOWNGRADE : 8
-};
-
-exports["test install/startup/shutdown/uninstall all return a promise"] = function*(assert) {
-  let uri = require.resolve("./fixtures/addon/bootstrap.js");
-  let id = "test-min-boot@jetpack";
-  let bootstrapScope = create({
-    id: id,
-    uri: uri
-  });
-
-  // As we don't want our caller to control the JS version used for the
-  // bootstrap file, we run loadSubScript within the context of the
-  // sandbox with the latest JS version set explicitly.
-  bootstrapScope.ROOT = ROOT;
-
-  evaluate({
-    uri: uri,
-    scope: bootstrapScope
-  });
-
-  let addon = {
-    id: id,
-    version: "0.0.1",
-    resourceURI: {
-      spec: uri.replace("bootstrap.js", "")
-    }
-  };
-
-  let install = bootstrapScope.install(addon, BOOTSTRAP_REASONS.ADDON_INSTALL);
-  yield install.then(() => assert.pass("install returns a promise"));
-
-  let startup = bootstrapScope.startup(addon, BOOTSTRAP_REASONS.ADDON_INSTALL);
-  yield startup.then(() => assert.pass("startup returns a promise"));
-
-  let shutdown = bootstrapScope.shutdown(addon, BOOTSTRAP_REASONS.ADDON_DISABLE);
-  yield shutdown.then(() => assert.pass("shutdown returns a promise"));
-
-  // calling shutdown multiple times is fine
-  shutdown = bootstrapScope.shutdown(addon, BOOTSTRAP_REASONS.ADDON_DISABLE);
-  yield shutdown.then(() => assert.pass("shutdown returns working promise on multiple calls"));
-
-  let uninstall = bootstrapScope.uninstall(addon, BOOTSTRAP_REASONS.ADDON_UNINSTALL);
-  yield uninstall.then(() => assert.pass("uninstall returns a promise"));
-}
-
-exports["test minimal bootstrap.js"] = function*(assert) {
-  let uri = require.resolve("./fixtures/addon/bootstrap.js");
-  let bootstrapScope = create({
-    id: "test-min-boot@jetpack",
-    uri: uri
-  });
-
-  // As we don't want our caller to control the JS version used for the
-  // bootstrap file, we run loadSubScript within the context of the
-  // sandbox with the latest JS version set explicitly.
-  bootstrapScope.ROOT = ROOT;
-
-  assert.equal(typeof bootstrapScope.install, "undefined", "install DNE");
-  assert.equal(typeof bootstrapScope.startup, "undefined", "startup DNE");
-  assert.equal(typeof bootstrapScope.shutdown, "undefined", "shutdown DNE");
-  assert.equal(typeof bootstrapScope.uninstall, "undefined", "uninstall DNE");
-
-  evaluate({
-    uri: uri,
-    scope: bootstrapScope
-  });
-
-  assert.equal(typeof bootstrapScope.install, "function", "install exists");
-  assert.equal(typeof bootstrapScope.startup, "function", "startup exists");
-  assert.equal(typeof bootstrapScope.shutdown, "function", "shutdown exists");
-  assert.equal(typeof bootstrapScope.uninstall, "function", "uninstall exists");
-
-  bootstrapScope.shutdown(null, BOOTSTRAP_REASONS.ADDON_DISABLE);
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-addon-extras.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Ci, Cu, Cc, components } = require("chrome");
-const self = require("sdk/self");
-const { before, after } = require("sdk/test/utils");
-const fixtures = require("./fixtures");
-const { Loader } = require("sdk/test/loader");
-const { merge } = require("sdk/util/object");
-
-exports["test changing result from addon extras in panel"] = function(assert, done) {
-  let loader = Loader(module, null, null, {
-    modules: {
-      "sdk/self": merge({}, self, {
-        data: merge({}, self.data, {url: fixtures.url})
-      })
-    }
-  });
-
-  const { Panel } = loader.require("sdk/panel");
-  const { getActiveView } = loader.require("sdk/view/core");
-  const { events } = loader.require("sdk/content/sandbox/events");
-  const { on } = loader.require("sdk/event/core");
-  const { isAddonContent } = loader.require("sdk/content/utils");
-
-  var result = 1;
-  var extrasVal = {
-    test: function() {
-      return result;
-    }
-  };
-
-  on(events, "content-script-before-inserted", ({ window, worker }) => {
-    assert.pass("content-script-before-inserted");
-
-    if (isAddonContent({ contentURL: window.location.href })) {
-      let extraStuff = Cu.cloneInto(extrasVal, window, {
-        cloneFunctions: true
-      });
-      getUnsafeWindow(window).extras = extraStuff;
-
-      assert.pass("content-script-before-inserted done!");
-    }
-  });
-
-  let panel = Panel({
-    contentURL: "./test-addon-extras.html"
-  });
-
-  // Force the panel view to actually load.
-  getActiveView(panel);
-
-  panel.port.once("result1", (result) => {
-    assert.equal(result, 1, "result is a number");
-    result = true;
-    panel.port.emit("get-result");
-  });
-
-  panel.port.once("result2", (result) => {
-    assert.equal(result, true, "result is a boolean");
-    loader.unload();
-    done();
-  });
-
-  panel.port.emit("get-result");
-}
-
-function getUnsafeWindow (win) {
-  return win.wrappedJSObject || win;
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-addon-installer.js
+++ /dev/null
@@ -1,230 +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 { pathFor } = require("sdk/system");
-const AddonInstaller = require("sdk/addon/installer");
-const { on, off } = require("sdk/system/events");
-const { setTimeout } = require("sdk/timers");
-const fs = require("sdk/io/fs");
-const path = require("sdk/fs/path");
-const { OS } = require("resource://gre/modules/osfile.jsm");
-const { toFilename } = require("sdk/url");
-
-// Retrieve the path to the OS temporary directory:
-const tmpDir = pathFor("TmpD");
-
-const profilePath = pathFor("ProfD");
-const corruptXPIPath = path.join(profilePath, "sdk-corrupt.xpi");
-const testFolderURL = module.uri.split('test-addon-installer.js')[0];
-const ADDON_URL = toFilename(testFolderURL + "fixtures/addon-install-unit-test@mozilla.com.xpi");
-
-exports["test Install"] = function*(assert) {
-  var ADDON_PATH = OS.Path.join(OS.Constants.Path.tmpDir, "install-test.xpi");
-
-  assert.pass("Copying test add-on " + ADDON_URL + " to " + ADDON_PATH);
-
-  yield OS.File.copy(ADDON_URL, ADDON_PATH);
-
-  assert.pass("Copied test add-on to " + ADDON_PATH);
-
-  // Save all events distpatched by bootstrap.js of the installed addon
-  let events = [];
-  function eventsObserver({ data }) {
-    events.push(data);
-  }
-  on("addon-install-unit-test", eventsObserver);
-
-  // Install the test addon
-  yield AddonInstaller.install(ADDON_PATH).then((id) => {
-    assert.equal(id, "addon-install-unit-test@mozilla.com", "`id` is valid");
-
-    // Now uninstall it
-    return AddonInstaller.uninstall(id).then(function () {
-      // Ensure that bootstrap.js methods of the addon have been called
-      // successfully and in the right order
-      let expectedEvents = ["install", "startup", "shutdown", "uninstall"];
-      assert.equal(JSON.stringify(events),
-                   JSON.stringify(expectedEvents),
-                   "addon's bootstrap.js functions have been called");
-
-      off("addon-install-unit-test", eventsObserver);
-    });
-  }, (code) => {
-    assert.fail("Install failed: "+code);
-    off("addon-install-unit-test", eventsObserver);
-  });
-
-  assert.pass("Add-on was uninstalled.");
-
-  yield OS.File.remove(ADDON_PATH);
-
-  assert.pass("Removed the temp file");
-};
-
-exports["test Failing Install With Invalid Path"] = function (assert, done) {
-  AddonInstaller.install("invalid-path").then(
-    function onInstalled(id) {
-      assert.fail("Unexpected success");
-      done();
-    },
-    function onFailure(code) {
-      assert.equal(code, AddonInstaller.ERROR_FILE_ACCESS,
-                       "Got expected error code");
-      done();
-    }
-  );
-};
-
-exports["test Failing Install With Invalid File"] = function (assert, done) {
-  const content = "bad xpi";
-  const path = corruptXPIPath;
-
-  fs.writeFile(path, content, (error) => {
-    assert.equal(fs.readFileSync(path).toString(),
-                 content,
-                 "contet was written");
-
-    AddonInstaller.install(path).then(
-      () => {
-        assert.fail("Unexpected success");
-        fs.unlink(path, done);
-      },
-      (code) => {
-        assert.equal(code, AddonInstaller.ERROR_CORRUPT_FILE,
-                         "Got expected error code");
-        fs.unlink(path, done);
-      }
-    );
-  });
-}
-
-exports["test Update"] = function*(assert) {
-  var ADDON_PATH = OS.Path.join(OS.Constants.Path.tmpDir, "update-test.xpi");
-
-  assert.pass("Copying test add-on " + ADDON_URL + " to " + ADDON_PATH);
-
-  yield OS.File.copy(ADDON_URL, ADDON_PATH);
-
-  assert.pass("Copied test add-on to " + ADDON_PATH);
-
-  // Save all events distpatched by bootstrap.js of the installed addon
-  let events = [];
-  let iteration = 1;
-  let eventsObserver = ({data}) => events.push(data);
-  on("addon-install-unit-test", eventsObserver);
-
-  yield new Promise(resolve => {
-    function onInstalled(id) {
-      let prefix = "[" + iteration + "] ";
-      assert.equal(id, "addon-install-unit-test@mozilla.com",
-                       prefix + "`id` is valid");
-
-      // On 2nd and 3rd iteration, we receive uninstall events from the last
-      // previously installed addon
-      let expectedEvents =
-        iteration == 1
-        ? ["install", "startup"]
-        : ["shutdown", "uninstall", "install", "startup"];
-      assert.equal(JSON.stringify(events),
-                       JSON.stringify(expectedEvents),
-                       prefix + "addon's bootstrap.js functions have been called");
-
-      if (iteration++ < 3) {
-        next();
-      }
-      else {
-        events = [];
-        AddonInstaller.uninstall(id).then(function() {
-          let expectedEvents = ["shutdown", "uninstall"];
-          assert.equal(JSON.stringify(events),
-                       JSON.stringify(expectedEvents),
-                       prefix + "addon's bootstrap.js functions have been called");
-
-          off("addon-install-unit-test", eventsObserver);
-          resolve();
-        });
-      }
-    }
-    function onFailure(code) {
-      assert.fail("Install failed: "+code);
-      off("addon-install-unit-test", eventsObserver);
-      resolve();
-    }
-
-    function next() {
-      events = [];
-      AddonInstaller.install(ADDON_PATH).then(onInstalled, onFailure);
-    }
-
-    next();
-  });
-
-  assert.pass("Add-on was uninstalled.");
-
-  yield OS.File.remove(ADDON_PATH);
-
-  assert.pass("Removed the temp file");
-};
-
-exports['test Uninstall failure'] = function (assert, done) {
-  AddonInstaller.uninstall('invalid-addon-path').then(
-    () => assert.fail('Addon uninstall should not resolve successfully'),
-    () => assert.pass('Addon correctly rejected invalid uninstall')
-  ).then(done, assert.fail);
-};
-
-exports['test Addon Disable and Enable'] = function*(assert) {
-  var ADDON_PATH = OS.Path.join(OS.Constants.Path.tmpDir, "disable-enable-test.xpi");
-
-  assert.pass("Copying test add-on " + ADDON_URL + " to " + ADDON_PATH);
-
-  yield OS.File.copy(ADDON_URL, ADDON_PATH);
-
-  assert.pass("Copied test add-on to " + ADDON_PATH);
-
-  let ensureActive = (addonId) => AddonInstaller.isActive(addonId).then(state => {
-    assert.equal(state, true, 'Addon should be enabled by default');
-    return addonId;
-  });
-  let ensureInactive = (addonId) => AddonInstaller.isActive(addonId).then(state => {
-    assert.equal(state, false, 'Addon should be disabled after disabling');
-    return addonId;
-  });
-
-  yield AddonInstaller.install(ADDON_PATH)
-    .then(ensureActive)
-    .then(AddonInstaller.enable) // should do nothing, yet not fail
-    .then(ensureActive)
-    .then(AddonInstaller.disable)
-    .then(ensureInactive)
-    .then(AddonInstaller.disable) // should do nothing, yet not fail
-    .then(ensureInactive)
-    .then(AddonInstaller.enable)
-    .then(ensureActive)
-    .then(AddonInstaller.uninstall);
-
-  assert.pass("Add-on was uninstalled.");
-
-  yield OS.File.remove(ADDON_PATH);
-
-  assert.pass("Removed the temp file");
-};
-
-exports['test Disable failure'] = function (assert, done) {
-  AddonInstaller.disable('not-an-id').then(
-    () => assert.fail('Addon disable should not resolve successfully'),
-    () => assert.pass('Addon correctly rejected invalid disable')
-  ).then(done, assert.fail);
-};
-
-exports['test Enable failure'] = function (assert, done) {
-  AddonInstaller.enable('not-an-id').then(
-    () => assert.fail('Addon enable should not resolve successfully'),
-    () => assert.pass('Addon correctly rejected invalid enable')
-  ).then(done, assert.fail);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-addon-window.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-var { Loader } = require('sdk/test/loader');
-
-exports.testReady = function(assert, done) {
-  let loader = Loader(module);
-  let { ready, window } = loader.require('sdk/addon/window');
-  let windowIsReady = false;
-
-  ready.then(function() {
-    assert.equal(windowIsReady, false, 'ready promise was resolved only once');
-    windowIsReady = true;
-
-    loader.unload();
-    done();
-  }).catch(assert.fail);
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-api-utils.js
+++ /dev/null
@@ -1,328 +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 apiUtils = require("sdk/deprecated/api-utils");
-
-exports.testValidateOptionsEmpty = function (assert) {
-  let val = apiUtils.validateOptions(null, {});
-
-  assert.deepEqual(val, {});
-
-  val = apiUtils.validateOptions(null, { foo: {} });
-  assert.deepEqual(val, {});
-
-  val = apiUtils.validateOptions({}, {});
-  assert.deepEqual(val, {});
-
-  val = apiUtils.validateOptions({}, { foo: {} });
-  assert.deepEqual(val, {});
-};
-
-exports.testValidateOptionsNonempty = function (assert) {
-  let val = apiUtils.validateOptions({ foo: 123 }, {});
-  assert.deepEqual(val, {});
-
-  val = apiUtils.validateOptions({ foo: 123, bar: 456 },
-                                 { foo: {}, bar: {}, baz: {} });
-
-  assert.deepEqual(val, { foo: 123, bar: 456 });
-};
-
-exports.testValidateOptionsMap = function (assert) {
-  let val = apiUtils.validateOptions({ foo: 3, bar: 2 }, {
-    foo: { map: v => v * v },
-    bar: { map: v => undefined }
-  });
-  assert.deepEqual(val, { foo: 9, bar: undefined });
-};
-
-exports.testValidateOptionsMapException = function (assert) {
-  let val = apiUtils.validateOptions({ foo: 3 }, {
-    foo: { map: function () { throw new Error(); }}
-  });
-  assert.deepEqual(val, { foo: 3 });
-};
-
-exports.testValidateOptionsOk = function (assert) {
-  let val = apiUtils.validateOptions({ foo: 3, bar: 2, baz: 1 }, {
-    foo: { ok: v => v },
-    bar: { ok: v => v }
-  });
-  assert.deepEqual(val, { foo: 3, bar: 2 });
-
-  assert.throws(
-    () => apiUtils.validateOptions({ foo: 2, bar: 2 }, {
-      bar: { ok: v => v > 2 }
-    }),
-    /^The option "bar" is invalid/,
-    "ok should raise exception on invalid option"
-  );
-
-  assert.throws(
-    () => apiUtils.validateOptions(null, { foo: { ok: v => v }}),
-    /^The option "foo" is invalid/,
-    "ok should raise exception on invalid option"
-  );
-};
-
-exports.testValidateOptionsIs = function (assert) {
-  let opts = {
-    array: [],
-    boolean: true,
-    func: function () {},
-    nul: null,
-    number: 1337,
-    object: {},
-    string: "foo",
-    undef1: undefined
-  };
-  let requirements = {
-    array: { is: ["array"] },
-    boolean: { is: ["boolean"] },
-    func: { is: ["function"] },
-    nul: { is: ["null"] },
-    number: { is: ["number"] },
-    object: { is: ["object"] },
-    string: { is: ["string"] },
-    undef1: { is: ["undefined"] },
-    undef2: { is: ["undefined"] }
-  };
-  let val = apiUtils.validateOptions(opts, requirements);
-  assert.deepEqual(val, opts);
-
-  assert.throws(
-    () => apiUtils.validateOptions(null, {
-      foo: { is: ["object", "number"] }
-    }),
-    /^The option "foo" must be one of the following types: object, number/,
-    "Invalid type should raise exception"
-  );
-};
-
-exports.testValidateOptionsIsWithExportedValue = function (assert) {
-  let { string, number, boolean, object } = apiUtils;
-
-  let opts = {
-    boolean: true,
-    number: 1337,
-    object: {},
-    string: "foo"
-  };
-  let requirements = {
-    string: { is: string },
-    number: { is: number },
-    boolean: { is: boolean },
-    object: { is: object }
-  };
-  let val = apiUtils.validateOptions(opts, requirements);
-  assert.deepEqual(val, opts);
-
-  // Test the types are optional by default
-  val = apiUtils.validateOptions({foo: 'bar'}, requirements);
-  assert.deepEqual(val, {});
-};
-
-exports.testValidateOptionsIsWithEither = function (assert) {
-  let { string, number, boolean, either } = apiUtils;
-  let text = { is: either(string, number) };
-
-  let requirements = {
-    text: text,
-    boolOrText: { is: either(text, boolean) }
-  };
-
-  let val = apiUtils.validateOptions({text: 12}, requirements);
-  assert.deepEqual(val, {text: 12});
-
-  val = apiUtils.validateOptions({text: "12"}, requirements);
-  assert.deepEqual(val, {text: "12"});
-
-  val = apiUtils.validateOptions({boolOrText: true}, requirements);
-  assert.deepEqual(val, {boolOrText: true});
-
-  val = apiUtils.validateOptions({boolOrText: "true"}, requirements);
-  assert.deepEqual(val, {boolOrText: "true"});
-
-  val = apiUtils.validateOptions({boolOrText: 1}, requirements);
-  assert.deepEqual(val, {boolOrText: 1});
-
-  assert.throws(
-    () => apiUtils.validateOptions({text: true}, requirements),
-    /^The option "text" must be one of the following types/,
-    "Invalid type should raise exception"
-  );
-
-  assert.throws(
-    () => apiUtils.validateOptions({boolOrText: []}, requirements),
-    /^The option "boolOrText" must be one of the following types/,
-    "Invalid type should raise exception"
-  );
-};
-
-exports.testValidateOptionsWithRequiredAndOptional = function (assert) {
-  let { string, number, required, optional } = apiUtils;
-
-  let opts = {
-    number: 1337,
-    string: "foo"
-  };
-
-  let requirements = {
-    string: required(string),
-    number: number
-  };
-
-  let val = apiUtils.validateOptions(opts, requirements);
-  assert.deepEqual(val, opts);
-
-  val = apiUtils.validateOptions({string: "foo"}, requirements);
-  assert.deepEqual(val, {string: "foo"});
-
-  assert.throws(
-    () => apiUtils.validateOptions({number: 10}, requirements),
-    /^The option "string" must be one of the following types/,
-    "Invalid type should raise exception"
-  );
-
-  // Makes string optional
-  requirements.string = optional(requirements.string);
-
-  val = apiUtils.validateOptions({number: 10}, requirements),
-  assert.deepEqual(val, {number: 10});
-
-};
-
-
-
-exports.testValidateOptionsWithExportedValue = function (assert) {
-  let { string, number, boolean, object } = apiUtils;
-
-  let opts = {
-    boolean: true,
-    number: 1337,
-    object: {},
-    string: "foo"
-  };
-  let requirements = {
-    string: string,
-    number: number,
-    boolean: boolean,
-    object: object
-  };
-  let val = apiUtils.validateOptions(opts, requirements);
-  assert.deepEqual(val, opts);
-
-  // Test the types are optional by default
-  val = apiUtils.validateOptions({foo: 'bar'}, requirements);
-  assert.deepEqual(val, {});
-};
-
-
-exports.testValidateOptionsMapIsOk = function (assert) {
-  let [map, is, ok] = [false, false, false];
-  let val = apiUtils.validateOptions({ foo: 1337 }, {
-    foo: {
-      map: v => v.toString(),
-      is: ["string"],
-      ok: v => v.length > 0
-    }
-  });
-  assert.deepEqual(val, { foo: "1337" });
-
-  let requirements = {
-    foo: {
-      is: ["object"],
-      ok: () => assert.fail("is should have caused us to throw by now")
-    }
-  };
-  assert.throws(
-    () => apiUtils.validateOptions(null, requirements),
-    /^The option "foo" must be one of the following types: object/,
-    "is should be used before ok is called"
-  );
-};
-
-exports.testValidateOptionsErrorMsg = function (assert) {
-  assert.throws(
-    () => apiUtils.validateOptions(null, {
-      foo: { ok: v => v, msg: "foo!" }
-    }),
-    /^foo!/,
-    "ok should raise exception with customized message"
-  );
-};
-
-exports.testValidateMapWithMissingKey = function (assert) {
-  let val = apiUtils.validateOptions({ }, {
-    foo: {
-      map: v => v || "bar"
-    }
-  });
-  assert.deepEqual(val, { foo: "bar" });
-
-  val = apiUtils.validateOptions({ }, {
-    foo: {
-      map: v => { throw "bar" }
-    }
-  });
-  assert.deepEqual(val, { });
-};
-
-exports.testValidateMapWithMissingKeyAndThrown = function (assert) {
-  let val = apiUtils.validateOptions({}, {
-    bar: {
-      map: function(v) { throw "bar" }
-    },
-    baz: {
-      map: v => "foo"
-    }
-  });
-  assert.deepEqual(val, { baz: "foo" });
-};
-
-function forEachEnabled() {
-  try {
-    eval(`for each (var x in {}) {}`);
-  } catch (e) {
-    return false;
-  }
-  return true;
-}
-
-exports.testAddIterator = function testAddIterator (assert) {
-  let obj = {};
-  let keys = ["foo", "bar", "baz"];
-  let vals = [1, 2, 3];
-  let keysVals = [["foo", 1], ["bar", 2], ["baz", 3]];
-  apiUtils.addIterator(
-    obj,
-    function keysValsGen() {
-      for (let keyVal of keysVals)
-        yield keyVal;
-    }
-  );
-
-  let keysItr = [];
-  for (let key in obj)
-    keysItr.push(key);
-
-  assert.equal(keysItr.length, keys.length,
-                   "the keys iterator returns the correct number of items");
-  for (let i = 0; i < keys.length; i++)
-    assert.equal(keysItr[i], keys[i], "the key is correct");
-
-  if (forEachEnabled()) {
-    eval(`
-    let valsItr = [];
-    for each (let val in obj)
-      valsItr.push(val);
-    assert.equal(valsItr.length, vals.length,
-                     "the vals iterator returns the correct number of items");
-    for (let i = 0; i < vals.length; i++)
-      assert.equal(valsItr[i], vals[i], "the val is correct");
-  `);
-  }
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-array.js
+++ /dev/null
@@ -1,103 +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 array = require('sdk/util/array');
-
-exports.testHas = function(assert) {
-  var testAry = [1, 2, 3];
-  assert.equal(array.has([1, 2, 3], 1), true);
-  assert.equal(testAry.length, 3);
-  assert.equal(testAry[0], 1);
-  assert.equal(testAry[1], 2);
-  assert.equal(testAry[2], 3);
-  assert.equal(array.has(testAry, 2), true);
-  assert.equal(array.has(testAry, 3), true);
-  assert.equal(array.has(testAry, 4), false);
-  assert.equal(array.has(testAry, '1'), false);
-};
-exports.testHasAny = function(assert) {
-  var testAry = [1, 2, 3];
-  assert.equal(array.hasAny([1, 2, 3], [1]), true);
-  assert.equal(array.hasAny([1, 2, 3], [1, 5]), true);
-  assert.equal(array.hasAny([1, 2, 3], [5, 1]), true);
-  assert.equal(array.hasAny([1, 2, 3], [5, 2]), true);
-  assert.equal(array.hasAny([1, 2, 3], [5, 3]), true);
-  assert.equal(array.hasAny([1, 2, 3], [5, 4]), false);
-  assert.equal(testAry.length, 3);
-  assert.equal(testAry[0], 1);
-  assert.equal(testAry[1], 2);
-  assert.equal(testAry[2], 3);
-  assert.equal(array.hasAny(testAry, [2]), true);
-  assert.equal(array.hasAny(testAry, [3]), true);
-  assert.equal(array.hasAny(testAry, [4]), false);
-  assert.equal(array.hasAny(testAry), false);
-  assert.equal(array.hasAny(testAry, '1'), false);
-};
-
-exports.testAdd = function(assert) {
-  var testAry = [1];
-  assert.equal(array.add(testAry, 1), false);
-  assert.equal(testAry.length, 1);
-  assert.equal(testAry[0], 1);
-  assert.equal(array.add(testAry, 2), true);
-  assert.equal(testAry.length, 2);
-  assert.equal(testAry[0], 1);
-  assert.equal(testAry[1], 2);
-};
-
-exports.testRemove = function(assert) {
-  var testAry = [1, 2];
-  assert.equal(array.remove(testAry, 3), false);
-  assert.equal(testAry.length, 2);
-  assert.equal(testAry[0], 1);
-  assert.equal(testAry[1], 2);
-  assert.equal(array.remove(testAry, 2), true);
-  assert.equal(testAry.length, 1);
-  assert.equal(testAry[0], 1);
-};
-
-exports.testFlatten = function(assert) {
-  assert.equal(array.flatten([1, 2, 3]).length, 3);
-  assert.equal(array.flatten([1, [2, 3]]).length, 3);
-  assert.equal(array.flatten([1, [2, [3]]]).length, 3);
-  assert.equal(array.flatten([[1], [[2, [3]]]]).length, 3);
-};
-
-exports.testUnique = function(assert) {
-  var Class = function () {};
-  var A = {};
-  var B = new Class();
-  var C = [ 1, 2, 3 ];
-  var D = {};
-  var E = new Class();
-
-  assert.deepEqual(array.unique([1,2,3,1,2]), [1,2,3]);
-  assert.deepEqual(array.unique([1,1,1,4,9,5,5]), [1,4,9,5]);
-  assert.deepEqual(array.unique([A, A, A, B, B, D]), [A,B,D]);
-  assert.deepEqual(array.unique([A, D, A, E, E, D, A, A, C]), [A, D, E, C])
-};
-
-exports.testUnion = function(assert) {
-  var Class = function () {};
-  var A = {};
-  var B = new Class();
-  var C = [ 1, 2, 3 ];
-  var D = {};
-  var E = new Class();
-
-  assert.deepEqual(array.union([1, 2, 3],[7, 1, 2]), [1, 2, 3, 7]);
-  assert.deepEqual(array.union([1, 1, 1, 4, 9, 5, 5], [10, 1, 5]), [1, 4, 9, 5, 10]);
-  assert.deepEqual(array.union([A, B], [A, D]), [A, B, D]);
-  assert.deepEqual(array.union([A, D], [A, E], [E, D, A], [A, C]), [A, D, E, C]);
-};
-
-exports.testFind = function(assert) {
-  let isOdd = (x) => x % 2;
-  assert.equal(array.find([2, 4, 5, 7, 8, 9], isOdd), 5);
-  assert.equal(array.find([2, 4, 6, 8], isOdd), undefined);
-  assert.equal(array.find([2, 4, 6, 8], isOdd, null), null);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-base64.js
+++ /dev/null
@@ -1,100 +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 base64 = require("sdk/base64");
-
-const text = "Awesome!";
-const b64text = "QXdlc29tZSE=";
-
-const utf8text = "\u2713 à la mode";
-const badutf8text = "\u0013 à la mode";
-const b64utf8text = "4pyTIMOgIGxhIG1vZGU=";
-
-// 1 MB string
-const longtext = 'fff'.repeat(333333);
-const b64longtext = 'ZmZm'.repeat(333333);
-
-exports["test base64.encode"] = function (assert) {
-  assert.equal(base64.encode(text), b64text, "encode correctly")
-}
-
-exports["test base64.decode"] = function (assert) {
-  assert.equal(base64.decode(b64text), text, "decode correctly")
-}
-
-exports["test base64.encode Unicode"] = function (assert) {
-
-  assert.equal(base64.encode(utf8text, "utf-8"), b64utf8text,
-    "encode correctly Unicode strings.")
-}
-
-exports["test base64.decode Unicode"] = function (assert) {
-
-  assert.equal(base64.decode(b64utf8text, "utf-8"), utf8text,
-    "decode correctly Unicode strings.")
-}
-
-exports["test base64.encode long string"] = function (assert) {
-
-  assert.equal(base64.encode(longtext), b64longtext, "encode long strings")
-}
-
-exports["test base64.decode long string"] = function (assert) {
-
-  assert.equal(base64.decode(b64longtext), longtext, "decode long strings")
-}
-
-exports["test base64.encode treats input as octet string"] = function (assert) {
-
-  assert.equal(base64.encode("\u0066"), "Zg==",
-    "treat octet string as octet string")
-  assert.equal(base64.encode("\u0166"), "Zg==",
-    "treat non-octet string as octet string")
-  assert.equal(base64.encode("\uff66"), "Zg==",
-    "encode non-octet string as octet string")
-}
-
-exports["test base64.encode with wrong charset"] = function (assert) {
-
-  assert.throws(function() {
-    base64.encode(utf8text, "utf-16");
-  }, "The charset argument can be only 'utf-8'");
-
-  assert.throws(function() {
-    base64.encode(utf8text, "");
-  }, "The charset argument can be only 'utf-8'");
-
-  assert.throws(function() {
-    base64.encode(utf8text, 8);
-  }, "The charset argument can be only 'utf-8'");
-
-}
-
-exports["test base64.decode with wrong charset"] = function (assert) {
-
-  assert.throws(function() {
-    base64.decode(utf8text, "utf-16");
-  }, "The charset argument can be only 'utf-8'");
-
-  assert.throws(function() {
-    base64.decode(utf8text, "");
-  }, "The charset argument can be only 'utf-8'");
-
-  assert.throws(function() {
-    base64.decode(utf8text, 8);
-  }, "The charset argument can be only 'utf-8'");
-
-}
-
-exports["test encode/decode Unicode without utf-8 as charset"] = function (assert) {
-
-  assert.equal(base64.decode(base64.encode(utf8text)), badutf8text,
-    "Unicode strings needs 'utf-8' charset or will be mangled"
-  );
-
-}
-
-require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-bootstrap.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Request } = require("sdk/request");
-
-exports.testBootstrapExists = function (assert, done) {
-  Request({
-    url: "resource://gre/modules/sdk/bootstrap.js",
-    onComplete: function (response) {
-      if (response.text)
-        assert.pass("the bootstrap file was found");
-      done();
-    }
-  }).get();
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-browser-events.js
+++ /dev/null
@@ -1,102 +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 = {
-  engines: {
-    "Firefox": "*"
-  }
-};
-
-const { Loader } = require("sdk/test/loader");
-const { open, getMostRecentBrowserWindow, getOuterId } = require("sdk/window/utils");
-const { setTimeout } = require("sdk/timers");
-
-exports["test browser events"] = function(assert, done) {
-  let loader = Loader(module);
-  let { events } = loader.require("sdk/browser/events");
-  let { on, off } = loader.require("sdk/event/core");
-  let actual = [];
-
-  on(events, "data", function handler(e) {
-    actual.push(e);
-    if (e.type === "load") window.close();
-    if (e.type === "close") {
-      // Unload the module so that all listeners set by observer are removed.
-
-      let [ ready, load, close ] = actual;
-
-      assert.equal(ready.type, "DOMContentLoaded");
-      assert.equal(ready.target, window, "window ready");
-
-      assert.equal(load.type, "load");
-      assert.equal(load.target, window, "window load");
-
-      assert.equal(close.type, "close");
-      assert.equal(close.target, window, "window load");
-
-      // Note: If window is closed right after this GC won't have time
-      // to claim loader and there for this listener, there for it's safer
-      // to remove listener.
-      off(events, "data", handler);
-      loader.unload();
-      done();
-    }
-  });
-
-  // Open window and close it to trigger observers.
-  let window = open();
-};
-
-exports["test browser events ignore other wins"] = function(assert, done) {
-  let loader = Loader(module);
-  let { events: windowEvents } = loader.require("sdk/window/events");
-  let { events: browserEvents } = loader.require("sdk/browser/events");
-  let { on, off } = loader.require("sdk/event/core");
-  let actualBrowser = [];
-  let actualWindow = [];
-
-  function browserEventHandler(e) {
-    return actualBrowser.push(e);
-  }
-  on(browserEvents, "data", browserEventHandler);
-  on(windowEvents, "data", function handler(e) {
-    actualWindow.push(e);
-    // Delay close so that if "load" is also emitted on `browserEvents`
-    // `browserEventHandler` will be invoked.
-    if (e.type === "load") setTimeout(window.close);
-    if (e.type === "close") {
-      assert.deepEqual(actualBrowser, [], "browser events were not triggered");
-      let [ open, ready, load, close ] = actualWindow;
-
-      assert.equal(open.type, "open");
-      assert.equal(open.target, window, "window is open");
-
-
-
-      assert.equal(ready.type, "DOMContentLoaded");
-      assert.equal(ready.target, window, "window ready");
-
-      assert.equal(load.type, "load");
-      assert.equal(load.target, window, "window load");
-
-      assert.equal(close.type, "close");
-      assert.equal(close.target, window, "window load");
-
-
-      // Note: If window is closed right after this GC won't have time
-      // to claim loader and there for this listener, there for it's safer
-      // to remove listener.
-      off(windowEvents, "data", handler);
-      off(browserEvents, "data", browserEventHandler);
-      loader.unload();
-      done();
-    }
-  });
-
-  // Open window and close it to trigger observers.
-  let window = open("data:text/html,not a browser");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-buffer.js
+++ /dev/null
@@ -1,563 +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/. */
-
-
-/*
- * Many of these tests taken from Joyent's Node
- * https://github.com/joyent/node/blob/master/test/simple/test-buffer.js
- */
-
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
-const { safeMerge } = require('sdk/util/object');
-
-const ENCODINGS = ['utf-8'];
-
-exports.testBufferMain = function (assert) {
-  let b = Buffer('abcdef');
-
-  // try to create 0-length buffers
-  new Buffer('');
-  new Buffer(0);
-  // test encodings supported by node;
-  // this is different than what node supports, details
-  // in buffer.js
-  ENCODINGS.forEach(enc => {
-    new Buffer('', enc);
-    assert.pass('Creating a buffer with ' + enc + ' does not throw');
-  });
-
-  ENCODINGS.forEach(function(encoding) {
-    // Does not work with utf8
-    if (encoding === 'utf-8') return;
-    var b = new Buffer(10);
-    b.write('あいうえお', encoding);
-    assert.equal(b.toString(encoding), 'あいうえお',
-      'encode and decodes buffer with ' + encoding);
-  });
-
-  // invalid encoding for Buffer.toString
-  assert.throws(() => {
-    b.toString('invalid');
-  }, RangeError, 'invalid encoding for Buffer.toString');
-
-  // try to toString() a 0-length slice of a buffer, both within and without the
-  // valid buffer range
-  assert.equal(new Buffer('abc').toString('utf8', 0, 0), '',
-    'toString 0-length buffer, valid range');
-  assert.equal(new Buffer('abc').toString('utf8', -100, -100), '',
-    'toString 0-length buffer, invalid range');
-  assert.equal(new Buffer('abc').toString('utf8', 100, 100), '',
-    'toString 0-length buffer, invalid range');
-
-  // try toString() with a object as a encoding
-  assert.equal(new Buffer('abc').toString({toString: function() {
-    return 'utf8';
-  }}), 'abc', 'toString with object as an encoding');
-
-  // test for buffer overrun
-  var buf = new Buffer([0, 0, 0, 0, 0]); // length: 5
-  var sub = buf.slice(0, 4); // length: 4
-  var written = sub.write('12345', 'utf8');
-  assert.equal(written, 4, 'correct bytes written in slice');
-  assert.equal(buf[4], 0, 'correct origin buffer value');
-
-  // Check for fractional length args, junk length args, etc.
-  // https://github.com/joyent/node/issues/1758
-  Buffer(3.3).toString(); // throws bad argument error in commit 43cb4ec
-  assert.equal(Buffer(-1).length, 0);
-  assert.equal(Buffer(NaN).length, 0);
-  assert.equal(Buffer(3.3).length, 3);
-  assert.equal(Buffer({length: 3.3}).length, 3);
-  assert.equal(Buffer({length: 'BAM'}).length, 0);
-
-  // Make sure that strings are not coerced to numbers.
-  assert.equal(Buffer('99').length, 2);
-  assert.equal(Buffer('13.37').length, 5);
-};
-
-exports.testIsEncoding = function (assert) {
-  ENCODINGS.map(encoding => {
-    assert.ok(Buffer.isEncoding(encoding),
-      'Buffer.isEncoding ' + encoding + ' truthy');
-  });
-  ['not-encoding', undefined, null, 100, {}].map(encoding => {
-    assert.ok(!Buffer.isEncoding(encoding),
-      'Buffer.isEncoding ' + encoding + ' falsy');
-  });
-};
-
-exports.testBufferCopy = function (assert) {
-  // counter to ensure unique value is always copied
-  var cntr = 0;
-  var b = Buffer(1024); // safe constructor
-
-  assert.strictEqual(1024, b.length);
-  b[0] = -1;
-  assert.strictEqual(b[0], 255);
-
-  var shimArray = [];
-  for (var i = 0; i < 1024; i++) {
-    b[i] = i % 256;
-    shimArray[i] = i % 256;
-  }
-
-  compareBuffers(assert, b, shimArray, 'array notation');
-
-  var c = new Buffer(512);
-  assert.strictEqual(512, c.length);
-  // copy 512 bytes, from 0 to 512.
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = b.copy(c, 0, 0, 512);
-  assert.strictEqual(512, copied,
-    'copied ' + copied + ' bytes from b into c');
-
-  compareBuffers(assert, b, c, 'copied to other buffer');
-
-  // copy c into b, without specifying sourceEnd
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = c.copy(b, 0, 0);
-  assert.strictEqual(c.length, copied,
-    'copied ' + copied + ' bytes from c into b w/o sourceEnd');
-  compareBuffers(assert, b, c,
-    'copied to other buffer without specifying sourceEnd');
-
-  // copy c into b, without specifying sourceStart
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = c.copy(b, 0);
-  assert.strictEqual(c.length, copied,
-    'copied ' + copied + ' bytes from c into b w/o sourceStart');
-  compareBuffers(assert, b, c,
-    'copied to other buffer without specifying sourceStart');
-
-  // copy longer buffer b to shorter c without targetStart
-  b.fill(++cntr);
-  c.fill(++cntr);
-
-  var copied = b.copy(c);
-  assert.strictEqual(c.length, copied,
-    'copied ' + copied + ' bytes from b into c w/o targetStart');
-  compareBuffers(assert, b, c,
-    'copy long buffer to shorter buffer without targetStart');
-
-  // copy starting near end of b to c
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
-  assert.strictEqual(Math.floor(c.length / 2), copied,
-    'copied ' + copied + ' bytes from end of b into beg. of c');
-
-  let successStatus = true;
-  for (var i = 0; i < Math.floor(c.length / 2); i++) {
-    if (b[b.length - Math.floor(c.length / 2) + i] !== c[i])
-      successStatus = false;
-  }
-
-  for (var i = Math.floor(c.length /2) + 1; i < c.length; i++) {
-    if (c[c.length-1] !== c[i])
-      successStatus = false;
-  }
-  assert.ok(successStatus,
-    'Copied bytes from end of large buffer into beginning of small buffer');
-
-  // try to copy 513 bytes, and check we don't overrun c
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = b.copy(c, 0, 0, 513);
-  assert.strictEqual(c.length, copied,
-    'copied ' + copied + ' bytes from b trying to overrun c');
-  compareBuffers(assert, b, c,
-    'copying to buffer that would overflow');
-
-  // copy 768 bytes from b into b
-  b.fill(++cntr);
-  b.fill(++cntr, 256);
-  var copied = b.copy(b, 0, 256, 1024);
-  assert.strictEqual(768, copied,
-    'copied ' + copied + ' bytes from b into b');
-
-  compareBuffers(assert, b, shimArray.map(()=>cntr),
-    'copy partial buffer to itself');
-
-  // copy string longer than buffer length (failure will segfault)
-  var bb = new Buffer(10);
-  bb.fill('hello crazy world');
-
-  // copy throws at negative sourceStart
-  assert.throws(function() {
-    Buffer(5).copy(Buffer(5), 0, -1);
-  }, RangeError, 'buffer copy throws at negative sourceStart');
-
-  // check sourceEnd resets to targetEnd if former is greater than the latter
-  b.fill(++cntr);
-  c.fill(++cntr);
-  var copied = b.copy(c, 0, 0, 1025);
-  assert.strictEqual(copied, c.length,
-    'copied ' + copied + ' bytes from b into c');
-  compareBuffers(assert, b, c, 'copying should reset sourceEnd if targetEnd if sourceEnd > targetEnd');
-
-  // throw with negative sourceEnd
-  assert.throws(function() {
-    b.copy(c, 0, 0, -1);
-  }, RangeError, 'buffer copy throws at negative sourceEnd');
-
-  // when sourceStart is greater than sourceEnd, zero copied
-  assert.equal(b.copy(c, 0, 100, 10), 0);
-
-  // when targetStart > targetLength, zero copied
-  assert.equal(b.copy(c, 512, 0, 10), 0);
-
-  // try to copy 0 bytes worth of data into an empty buffer
-  b.copy(new Buffer(0), 0, 0, 0);
-
-  // try to copy 0 bytes past the end of the target buffer
-  b.copy(new Buffer(0), 1, 1, 1);
-  b.copy(new Buffer(1), 1, 1, 1);
-
-  // try to copy 0 bytes from past the end of the source buffer
-  b.copy(new Buffer(1), 0, 2048, 2048);
-};
-
-exports.testBufferWrite = function (assert) {
-  let b = Buffer(1024);
-  b.fill(0);
-
-  // try to write a 0-length string beyond the end of b
-  assert.throws(function() {
-    b.write('', 2048);
-  }, RangeError, 'writing a 0-length string beyond buffer throws');
-  // throw when writing to negative offset
-  assert.throws(function() {
-    b.write('a', -1);
-  }, RangeError, 'writing negative offset on buffer throws');
-
-  // throw when writing past bounds from the pool
-  assert.throws(function() {
-    b.write('a', 2048);
-  }, RangeError, 'writing past buffer bounds from pool throws');
-
-  // testing for smart defaults and ability to pass string values as offset
-
-  // previous write API was the following:
-  // write(string, encoding, offset, length)
-  // this is planned on being removed in node v0.13,
-  // we will not support it
-  var writeTest = new Buffer('abcdes');
-  writeTest.write('n', 'utf8');
-//  writeTest.write('o', 'utf8', '1');
-  writeTest.write('d', '2', 'utf8');
-  writeTest.write('e', 3, 'utf8');
-//  writeTest.write('j', 'utf8', 4);
-  assert.equal(writeTest.toString(), 'nbdees',
-    'buffer write API alternative syntax works');
-};
-
-exports.testBufferWriteEncoding = function (assert) {
-
-  // Node #1210 Test UTF-8 string includes null character
-  var buf = new Buffer('\0');
-  assert.equal(buf.length, 1);
-  buf = new Buffer('\0\0');
-  assert.equal(buf.length, 2);
-
-  buf = new Buffer(2);
-  var written = buf.write(''); // 0byte
-  assert.equal(written, 0);
-  written = buf.write('\0'); // 1byte (v8 adds null terminator)
-  assert.equal(written, 1);
-  written = buf.write('a\0'); // 1byte * 2
-  assert.equal(written, 2);
-  // TODO, these tests write 0, possibly due to character encoding
-/*
-  written = buf.write('あ'); // 3bytes
-  assert.equal(written, 0);
-  written = buf.write('\0あ'); // 1byte + 3bytes
-  assert.equal(written, 1);
-*/
-  written = buf.write('\0\0あ'); // 1byte * 2 + 3bytes
-  buf = new Buffer(10);
-  written = buf.write('あいう'); // 3bytes * 3 (v8 adds null terminator)
-  assert.equal(written, 9);
-  written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
-  assert.equal(written, 10);
-};
-
-exports.testBufferWriteWithMaxLength = function (assert) {
-  // Node #243 Test write() with maxLength
-  var buf = new Buffer(4);
-  buf.fill(0xFF);
-  var written = buf.write('abcd', 1, 2, 'utf8');
-  assert.equal(written, 2);
-  assert.equal(buf[0], 0xFF);
-  assert.equal(buf[1], 0x61);
-  assert.equal(buf[2], 0x62);
-  assert.equal(buf[3], 0xFF);
-
-  buf.fill(0xFF);
-  written = buf.write('abcd', 1, 4);
-  assert.equal(written, 3);
-  assert.equal(buf[0], 0xFF);
-  assert.equal(buf[1], 0x61);
-  assert.equal(buf[2], 0x62);
-  assert.equal(buf[3], 0x63);
-
-  buf.fill(0xFF);
-  // Ignore legacy API
-  /*
-     written = buf.write('abcd', 'utf8', 1, 2); // legacy style
-     console.log(buf);
-     assert.equal(written, 2);
-     assert.equal(buf[0], 0xFF);
-     assert.equal(buf[1], 0x61);
-     assert.equal(buf[2], 0x62);
-     assert.equal(buf[3], 0xFF);
-     */
-};
-
-exports.testBufferSlice = function (assert) {
-  var asciiString = 'hello world';
-  var offset = 100;
-  var b = Buffer(1024);
-  b.fill(0);
-
-  for (var i = 0; i < asciiString.length; i++) {
-    b[i] = asciiString.charCodeAt(i);
-  }
-  var asciiSlice = b.toString('utf8', 0, asciiString.length);
-  assert.equal(asciiString, asciiSlice);
-
-  var written = b.write(asciiString, offset, 'utf8');
-  assert.equal(asciiString.length, written);
-  asciiSlice = b.toString('utf8', offset, offset + asciiString.length);
-  assert.equal(asciiString, asciiSlice);
-
-  var sliceA = b.slice(offset, offset + asciiString.length);
-  var sliceB = b.slice(offset, offset + asciiString.length);
-  compareBuffers(assert, sliceA, sliceB,
-    'slicing is idempotent');
-
-  let sliceTest = true;
-  for (var j = 0; j < 100; j++) {
-    var slice = b.slice(100, 150);
-    if (50 !== slice.length)
-      sliceTest = false;
-    for (var i = 0; i < 50; i++) {
-      if (b[100 + i] !== slice[i])
-        sliceTest = false;
-    }
-  }
-  assert.ok(sliceTest, 'massive slice runs do not affect buffer');
-
-  // Single argument slice
-  let testBuf = new Buffer('abcde');
-  assert.equal('bcde', testBuf.slice(1).toString(), 'single argument slice');
-
-  // slice(0,0).length === 0
-  assert.equal(0, Buffer('hello').slice(0, 0).length, 'slice(0,0) === 0');
-
-  var buf = new Buffer('0123456789');
-  assert.equal(buf.slice(-10, 10), '0123456789', 'buffer slice range correct');
-  assert.equal(buf.slice(-20, 10), '0123456789', 'buffer slice range correct');
-  assert.equal(buf.slice(-20, -10), '', 'buffer slice range correct');
-  assert.equal(buf.slice(0, -1), '012345678', 'buffer slice range correct');
-  assert.equal(buf.slice(2, -2), '234567', 'buffer slice range correct');
-  assert.equal(buf.slice(0, 65536), '0123456789', 'buffer slice range correct');
-  assert.equal(buf.slice(65536, 0), '', 'buffer slice range correct');
-
-  sliceTest = true;
-  for (var i = 0, s = buf.toString(); i < buf.length; ++i) {
-    if (buf.slice(-i) != s.slice(-i)) sliceTest = false;
-    if (buf.slice(0, -i) != s.slice(0, -i)) sliceTest = false;
-  }
-  assert.ok(sliceTest, 'buffer.slice should be consistent');
-
-  // Make sure modifying a sliced buffer, affects original and vice versa
-  b.fill(0);
-  let sliced = b.slice(0, 10);
-  let babyslice = sliced.slice(0, 5);
-
-  for (let i = 0; i < sliced.length; i++)
-    sliced[i] = 'jetpack'.charAt(i);
-
-  compareBuffers(assert, b, sliced,
-    'modifying sliced buffer affects original');
-
-  compareBuffers(assert, b, babyslice,
-    'modifying sliced buffer affects child-sliced buffer');
-
-  for (let i = 0; i < sliced.length; i++)
-    b[i] = 'odinmonkey'.charAt(i);
-
-  compareBuffers(assert, b, sliced,
-    'modifying original buffer affects sliced');
-
-  compareBuffers(assert, b, babyslice,
-    'modifying original buffer affects grandchild sliced buffer');
-};
-
-exports.testSlicingParents = function (assert) {
-  let root = Buffer(5);
-  let child = root.slice(0, 4);
-  let grandchild = child.slice(0, 3);
-
-  assert.equal(root.parent, undefined, 'a new buffer should not have a parent');
-
-  // make sure a zero length slice doesn't set the .parent attribute
-  assert.equal(root.slice(0,0).parent, undefined,
-    '0-length slice should not have a parent');
-
-  assert.equal(child.parent, root,
-    'a valid slice\'s parent should be the original buffer (child)');
-
-  assert.equal(grandchild.parent, root,
-    'a valid slice\'s parent should be the original buffer (grandchild)');
-};
-
-exports.testIsBuffer = function (assert) {
-  let buffer = new Buffer('content', 'utf8');
-  assert.ok(Buffer.isBuffer(buffer), 'isBuffer truthy on buffers');
-  assert.ok(!Buffer.isBuffer({}), 'isBuffer falsy on objects');
-  assert.ok(!Buffer.isBuffer(new Uint8Array()),
-    'isBuffer falsy on Uint8Array');
-  assert.ok(Buffer.isBuffer(buffer.slice(0)), 'Buffer#slice should be a new buffer');
-};
-
-exports.testBufferConcat = function (assert) {
-  let zero = [];
-  let one = [ new Buffer('asdf') ];
-  let long = [];
-  for (let i = 0; i < 10; i++) long.push(new Buffer('asdf'));
-
-  let flatZero = Buffer.concat(zero);
-  let flatOne = Buffer.concat(one);
-  let flatLong = Buffer.concat(long);
-  let flatLongLen = Buffer.concat(long, 40);
-
-  assert.equal(flatZero.length, 0);
-  assert.equal(flatOne.toString(), 'asdf');
-  assert.equal(flatOne, one[0]);
-  assert.equal(flatLong.toString(), (new Array(10+1).join('asdf')));
-  assert.equal(flatLongLen.toString(), (new Array(10+1).join('asdf')));
-};
-
-exports.testBufferByteLength = function (assert) {
-  let str = '\u00bd + \u00bc = \u00be';
-  assert.equal(Buffer.byteLength(str), 12,
-    'correct byteLength of string');
-
-  assert.equal(14, Buffer.byteLength('Il était tué'));
-  assert.equal(14, Buffer.byteLength('Il était tué', 'utf8'));
-  // We do not currently support these encodings
-  /*
-  ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
-  assert.equal(24, Buffer.byteLength('Il était tué', encoding));
-  });
-  assert.equal(12, Buffer.byteLength('Il était tué', 'ascii'));
-  assert.equal(12, Buffer.byteLength('Il était tué', 'binary'));
-  */
-};
-
-exports.testTextEncoderDecoder = function (assert) {
-  assert.ok(TextEncoder, 'TextEncoder exists');
-  assert.ok(TextDecoder, 'TextDecoder exists');
-};
-
-exports.testOverflowedBuffers = function (assert) {
-  assert.throws(function() {
-    new Buffer(0xFFFFFFFF);
-  }, RangeError, 'correctly throws buffer overflow');
-
-  assert.throws(function() {
-    new Buffer(0xFFFFFFFFF);
-  }, RangeError, 'correctly throws buffer overflow');
-
-  assert.throws(function() {
-    var buf = new Buffer(8);
-    buf.readFloatLE(0xffffffff);
-  }, RangeError, 'correctly throws buffer overflow with readFloatLE');
-
-  assert.throws(function() {
-    var buf = new Buffer(8);
-    buf.writeFloatLE(0.0, 0xffffffff);
-  }, RangeError, 'correctly throws buffer overflow with writeFloatLE');
-
-  //ensure negative values can't get past offset
-  assert.throws(function() {
-    var buf = new Buffer(8);
-    buf.readFloatLE(-1);
-  }, RangeError, 'correctly throws with readFloatLE negative values');
-
-  assert.throws(function() {
-    var buf = new Buffer(8);
-    buf.writeFloatLE(0.0, -1);
-  }, RangeError, 'correctly throws with writeFloatLE with negative values');
-
-  assert.throws(function() {
-    var buf = new Buffer(8);
-    buf.readFloatLE(-1);
-  }, RangeError, 'correctly throws with readFloatLE with negative values');
-};
-
-exports.testReadWriteDataTypeErrors = function (assert) {
-  var buf = new Buffer(0);
-  assert.throws(function() { buf.readUInt8(0); }, RangeError,
-    'readUInt8(0) throws');
-  assert.throws(function() { buf.readInt8(0); }, RangeError,
-    'readInt8(0) throws');
-
-  [16, 32].forEach(function(bits) {
-    var buf = new Buffer(bits / 8 - 1);
-    assert.throws(function() { buf['readUInt' + bits + 'BE'](0); },
-      RangeError,
-      'readUInt' + bits + 'BE');
-
-    assert.throws(function() { buf['readUInt' + bits + 'LE'](0); },
-      RangeError,
-      'readUInt' + bits + 'LE');
-
-    assert.throws(function() { buf['readInt' + bits + 'BE'](0); },
-      RangeError,
-      'readInt' + bits + 'BE()');
-
-    assert.throws(function() { buf['readInt' + bits + 'LE'](0); },
-      RangeError,
-      'readInt' + bits + 'LE()');
-  });
-};
-
-safeMerge(exports, require('./buffers/test-write-types'));
-safeMerge(exports, require('./buffers/test-read-types'));
-
-function compareBuffers (assert, buf1, buf2, message) {
-  let status = true;
-  for (let i = 0; i < Math.min(buf1.length, buf2.length); i++) {
-    if (buf1[i] !== buf2[i])
-      status = false;
-  }
-  assert.ok(status, 'buffer successfully copied: ' + message);
-}
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-byte-streams.js
+++ /dev/null
@@ -1,169 +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 byteStreams = require("sdk/io/byte-streams");
-const file = require("sdk/io/file");
-const { pathFor } = require("sdk/system");
-const { Loader } = require("sdk/test/loader");
-
-const STREAM_CLOSED_ERROR = new RegExp("The stream is closed and cannot be used.");
-
-// This should match the constant of the same name in byte-streams.js.
-const BUFFER_BYTE_LEN = 0x8000;
-
-exports.testWriteRead = function (assert) {
-  let fname = dataFileFilename();
-
-  // Write a small string less than the stream's buffer size...
-  let str = "exports.testWriteRead data!";
-  let stream = open(assert, fname, true);
-  assert.ok(!stream.closed, "stream.closed after open should be false");
-  stream.write(str);
-  stream.close();
-  assert.ok(stream.closed, "Stream should be closed after stream.close");
-  assert.throws(() => stream.write("This shouldn't be written!"),
-    STREAM_CLOSED_ERROR,
-    "stream.write after close should raise error");
-
-  // ... and read it.
-  stream = open(assert, fname);
-  assert.equal(stream.read(), str,
-    "stream.read should return string written");
-  assert.equal(stream.read(), "",
-    "stream.read at EOS should return empty string");
-  stream.close();
-  assert.ok(stream.closed, "Stream should be closed after stream.close");
-  assert.throws(() => stream.read(),
-    STREAM_CLOSED_ERROR,
-    "stream.read after close should raise error");
-
-  file.remove(fname);
-};
-
-// Write a big string many times the size of the stream's buffer and read it.
-exports.testWriteReadBig = function (assert) {
-  let str = "";
-  let bufLen = BUFFER_BYTE_LEN;
-  let fileSize = bufLen * 10;
-  for (let i = 0; i < fileSize; i++)
-    str += i % 10;
-  let fname = dataFileFilename();
-  let stream = open(assert, fname, true);
-  stream.write(str);
-  stream.close();
-  stream = open(assert, fname);
-  assert.equal(stream.read(), str,
-    "stream.read should return string written");
-  stream.close();
-  file.remove(fname);
-};
-
-// The same, but write and read in chunks.
-exports.testWriteReadChunks = function (assert) {
-  let str = "";
-  let bufLen = BUFFER_BYTE_LEN;
-  let fileSize = bufLen * 10;
-  for (let i = 0; i < fileSize; i++)
-    str += i % 10;
-  let fname = dataFileFilename();
-  let stream = open(assert, fname, true);
-  let i = 0;
-  while (i < str.length) {
-    // Use a chunk length that spans buffers.
-    let chunk = str.substr(i, bufLen + 1);
-    stream.write(chunk);
-    i += bufLen + 1;
-  }
-  stream.close();
-  stream = open(assert, fname);
-  let readStr = "";
-  bufLen = BUFFER_BYTE_LEN;
-  let readLen = bufLen + 1;
-  do {
-    var frag = stream.read(readLen);
-    readStr += frag;
-  } while (frag);
-  stream.close();
-  assert.equal(readStr, str,
-    "stream.write and read in chunks should work as expected");
-  file.remove(fname);
-};
-
-exports.testReadLengths = function (assert) {
-  let fname = dataFileFilename();
-  let str = "exports.testReadLengths data!";
-  let stream = open(assert, fname, true);
-  stream.write(str);
-  stream.close();
-
-  stream = open(assert, fname);
-  assert.equal(stream.read(str.length * 1000), str,
-    "stream.read with big byte length should return string " +
-    "written");
-  stream.close();
-
-  stream = open(assert, fname);
-  assert.equal(stream.read(0), "",
-    "string.read with zero byte length should return empty " +
-    "string");
-  stream.close();
-
-  stream = open(assert, fname);
-  assert.equal(stream.read(-1), "",
-    "string.read with negative byte length should return " +
-    "empty string");
-  stream.close();
-
-  file.remove(fname);
-};
-
-exports.testTruncate = function (assert) {
-  let fname = dataFileFilename();
-  let str = "exports.testReadLengths data!";
-  let stream = open(assert, fname, true);
-  stream.write(str);
-  stream.close();
-
-  stream = open(assert, fname);
-  assert.equal(stream.read(), str,
-    "stream.read should return string written");
-  stream.close();
-
-  stream = open(assert, fname, true);
-  stream.close();
-
-  stream = open(assert, fname);
-  assert.equal(stream.read(), "",
-    "stream.read after truncate should be empty");
-  stream.close();
-
-  file.remove(fname);
-};
-
-exports.testUnload = function (assert) {
-  let loader = Loader(module);
-  let file = loader.require("sdk/io/file");
-
-  let filename = dataFileFilename("temp-b");
-  let stream = file.open(filename, "wb");
-
-  loader.unload();
-  assert.ok(stream.closed, "Stream should be closed after module unload");
-};
-
-// Returns the name of a file that should be used to test writing and reading.
-function dataFileFilename() {
-  return file.join(pathFor("ProfD"), "test-byte-streams-data");
-}
-
-// Opens and returns the given file and ensures it's of the correct class.
-function open(assert, filename, forWriting) {
-  let stream = file.open(filename, forWriting ? "wb" : "b");
-  let klass = forWriting ? "ByteWriter" : "ByteReader";
-  assert.ok(stream instanceof byteStreams[klass],
-           "Opened stream should be a " + klass);
-  return stream;
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-child_process.js
+++ /dev/null
@@ -1,545 +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 { spawn, exec, execFile, fork } = require('sdk/system/child_process');
-const { env, platform, pathFor } = require('sdk/system');
-const { isNumber } = require('sdk/lang/type');
-const { after } = require('sdk/test/utils');
-const { emit } = require('sdk/event/core');
-const PROFILE_DIR= pathFor('ProfD');
-const isWindows = platform.toLowerCase().indexOf('win') === 0;
-const { getScript, cleanUp } = require('./fixtures/child-process-scripts');
-
-// We use direct paths to these utilities as we currently cannot
-// call non-absolute paths to utilities in subprocess.jsm
-const CAT_PATH = isWindows ? 'C:\\Windows\\System32\\more.com' : '/bin/cat';
-
-exports.testExecCallbackSuccess = function (assert, done) {
-  exec(isWindows ? 'DIR /A-D' : 'ls -al', {
-    cwd: PROFILE_DIR
-  }, function (err, stdout, stderr) {
-    assert.ok(!err, 'no errors found');
-    assert.equal(stderr, '', 'stderr is empty');
-    assert.ok(/extensions\.ini/.test(stdout), 'stdout output of `ls -al` finds files');
-
-    if (isWindows) {
-      // `DIR /A-D` does not display directories on WIN
-      assert.ok(!/<DIR>/.test(stdout),
-        'passing arguments in `exec` works');
-    }
-    else {
-      // `ls -al` should list all the priviledge information on Unix
-      assert.ok(/d(r[-|w][-|x]){3}/.test(stdout),
-        'passing arguments in `exec` works');
-    }
-    done();
-  });
-};
-
-exports.testExecCallbackError = function (assert, done) {
-  exec('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
-    assert.ok(/not-real-command/.test(err.toString()),
-      'error contains error message');
-    assert.ok(err.lineNumber >= 0, 'error contains lineNumber');
-    assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName');
-    assert.ok(err.code && isNumber(err.code), 'non-zero error code property on error');
-    assert.equal(err.signal, null,
-      'null signal property when not manually terminated');
-    assert.equal(stdout, '', 'stdout is empty');
-    assert.ok(/not-real-command/.test(stderr), 'stderr contains error message');
-    done();
-  });
-};
-
-exports.testExecOptionsEnvironment = function (assert, done) {
-  getScript('check-env').then(envScript => {
-    exec(envScript, {
-      cwd: PROFILE_DIR,
-      env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
-    }, function (err, stdout, stderr) {
-      assert.equal(stderr, '', 'stderr is empty');
-      assert.ok(!err, 'received `cwd` option');
-      assert.ok(/my-value-test/.test(stdout),
-        'receives environment option');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-exports.testExecOptionsTimeout = function (assert, done) {
-  let count = 0;
-  getScript('wait').then(script => {
-    let child = exec(script, { timeout: 100 }, (err, stdout, stderr) => {
-      assert.equal(err.killed, true, 'error has `killed` property as true');
-      assert.equal(err.code, null, 'error has `code` as null');
-      assert.equal(err.signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      assert.equal(stdout, '', 'stdout is empty');
-      assert.equal(stderr, '', 'stderr is empty');
-      if (++count === 3) complete();
-    });
-
-    function exitHandler (code, signal) {
-      assert.equal(code, null, 'error has `code` as null');
-      assert.equal(signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      if (++count === 3) complete();
-    }
-
-    function closeHandler (code, signal) {
-      assert.equal(code, null, 'error has `code` as null');
-      assert.equal(signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      if (++count === 3) complete();
-    }
-
-    child.on('exit', exitHandler);
-    child.on('close', closeHandler);
-
-    function complete () {
-      child.off('exit', exitHandler);
-      child.off('close', closeHandler);
-      done();
-    }
-  }).catch(assert.fail);
-};
-
-exports.testExecFileCallbackSuccess = function (assert, done) {
-  getScript('args').then(script => {
-    execFile(script, ['--myargs', '-j', '-s'], { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
-      assert.ok(!err, 'no errors found');
-      assert.equal(stderr, '', 'stderr is empty');
-      // Trim output since different systems have different new line output
-      assert.equal(stdout.trim(), '--myargs -j -s'.trim(), 'passes in correct arguments');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-exports.testExecFileCallbackError = function (assert, done) {
-  execFile('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
-    assert.ok(/Executable not found/.test(err.message),
-      `error '${err.message}' contains error message`);
-    assert.ok(err.lineNumber >= 0, 'error contains lineNumber');
-    assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName');
-    assert.equal(stdout, '', 'stdout is empty');
-    assert.equal(stderr, '', 'stdout is empty');
-    done();
-  });
-};
-
-exports.testExecFileOptionsEnvironment = function (assert, done) {
-  getScript('check-env').then(script => {
-    execFile(script, {
-      cwd: PROFILE_DIR,
-      env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
-    }, function (err, stdout, stderr) {
-      assert.equal(stderr, '', 'stderr is empty');
-      assert.ok(!err, 'received `cwd` option');
-      assert.ok(/my-value-test/.test(stdout),
-        'receives environment option');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-exports.testExecFileOptionsTimeout = function (assert, done) {
-  let count = 0;
-  getScript('wait').then(script => {
-    let child = execFile(script, { timeout: 100 }, (err, stdout, stderr) => {
-      assert.equal(err.killed, true, 'error has `killed` property as true');
-      assert.equal(err.code, null, 'error has `code` as null');
-      assert.equal(err.signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      assert.equal(stdout, '', 'stdout is empty');
-      assert.equal(stderr, '', 'stderr is empty');
-      if (++count === 3) complete();
-    });
-
-    function exitHandler (code, signal) {
-      assert.equal(code, null, 'error has `code` as null');
-      assert.equal(signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      if (++count === 3) complete();
-    }
-
-    function closeHandler (code, signal) {
-      assert.equal(code, null, 'error has `code` as null');
-      assert.equal(signal, 'SIGTERM',
-        'error has `signal` as SIGTERM by default');
-      if (++count === 3) complete();
-    }
-
-    child.on('exit', exitHandler);
-    child.on('close', closeHandler);
-
-    function complete () {
-      child.off('exit', exitHandler);
-      child.off('close', closeHandler);
-      done();
-    }
-  }).catch(assert.fail);
-};
-
-/**
- * Not necessary to test for both `exec` and `execFile`, but
- * it is necessary to test both when the buffer is larger
- * and smaller than buffer size used by the subprocess library (1024)
- */
-exports.testExecFileOptionsMaxBufferLargeStdOut = function (assert, done) {
-  let count = 0;
-  let stdoutChild;
-
-  // Creates a buffer of 2000 to stdout, greater than 1024
-  getScript('large-out').then(script => {
-    stdoutChild = execFile(script, ['10000'], { maxBuffer: 50 }, (err, stdout, stderr) => {
-      assert.ok(/stdout maxBuffer exceeded/.test(err.toString()),
-        'error contains stdout maxBuffer exceeded message');
-      assert.ok(stdout.length >= 50, 'stdout has full buffer');
-      assert.equal(stderr, '', 'stderr is empty');
-      if (++count === 3) complete();
-    });
-    stdoutChild.on('exit', exitHandler);
-    stdoutChild.on('close', closeHandler);
-  }).catch(assert.fail);
-
-  function exitHandler (code, signal) {
-    assert.equal(code, null, 'Exit code is null in exit handler');
-    assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
-    if (++count === 3) complete();
-  }
-
-  function closeHandler (code, signal) {
-    assert.equal(code, null, 'Exit code is null in close handler');
-    assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler');
-    if (++count === 3) complete();
-  }
-
-  function complete () {
-    stdoutChild.off('exit', exitHandler);
-    stdoutChild.off('close', closeHandler);
-    done();
-  }
-};
-
-exports.testExecFileOptionsMaxBufferLargeStdOErr = function (assert, done) {
-  let count = 0;
-  let stderrChild;
-  // Creates a buffer of 2000 to stderr, greater than 1024
-  getScript('large-err').then(script => {
-    stderrChild = execFile(script, ['10000'], { maxBuffer: 50 }, (err, stdout, stderr) => {
-      assert.ok(/stderr maxBuffer exceeded/.test(err.toString()),
-        'error contains stderr maxBuffer exceeded message');
-      assert.ok(stderr.length >= 50, 'stderr has full buffer');
-      assert.equal(stdout, '', 'stdout is empty');
-      if (++count === 3) complete();
-    });
-    stderrChild.on('exit', exitHandler);
-    stderrChild.on('close', closeHandler);
-  }).catch(assert.fail);
-
-  function exitHandler (code, signal) {
-    assert.equal(code, null, 'Exit code is null in exit handler');
-    assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
-    if (++count === 3) complete();
-  }
-
-  function closeHandler (code, signal) {
-    assert.equal(code, null, 'Exit code is null in close handler');
-    assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler');
-    if (++count === 3) complete();
-  }
-
-  function complete () {
-    stderrChild.off('exit', exitHandler);
-    stderrChild.off('close', closeHandler);
-    done();
-  }
-};
-
-/**
- * When total buffer is < process buffer (1024), the process will exit
- * and not get a chance to be killed for violating the maxBuffer,
- * although the error will still be sent through (node behaviour)
- */
-exports.testExecFileOptionsMaxBufferSmallStdOut = function (assert, done) {
-  let count = 0;
-  let stdoutChild;
-
-  // Creates a buffer of 60 to stdout, less than 1024
-  getScript('large-out').then(script => {
-    stdoutChild = execFile(script, ['60'], { maxBuffer: 50 }, (err, stdout, stderr) => {
-      assert.ok(/stdout maxBuffer exceeded/.test(err.toString()),
-        'error contains stdout maxBuffer exceeded message');
-      assert.ok(stdout.length >= 50, 'stdout has full buffer');
-      assert.equal(stderr, '', 'stderr is empty');
-      if (++count === 3) complete();
-    });
-    stdoutChild.on('exit', exitHandler);
-    stdoutChild.on('close', closeHandler);
-  }).catch(assert.fail);
-
-  function exitHandler (code, signal) {
-    // Sometimes the buffer limit is hit before the process closes successfully
-    // on both OSX/Windows
-    if (code === null) {
-      assert.equal(code, null, 'Exit code is null in exit handler');
-      assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
-    }
-    else {
-      assert.equal(code, 0, 'Exit code is 0 in exit handler');
-      assert.equal(signal, null, 'Signal is null in exit handler');
-    }
-    if (++count === 3) complete();
-  }
-
-  function closeHandler (code, signal) {
-    // Sometimes the buffer limit is hit before the process closes successfully
-    // on both OSX/Windows
-    if (code === null) {
-      assert.equal(code, null, 'Exit code is null in close handler');
-      assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler');
-    }
-    else {
-      assert.equal(code, 0, 'Exit code is 0 in close handler');
-      assert.equal(signal, null, 'Signal is null in close handler');
-    }
-    if (++count === 3) complete();
-  }
-
-  function complete () {
-    stdoutChild.off('exit', exitHandler);
-    stdoutChild.off('close', closeHandler);
-    done();
-  }
-};
-
-exports.testExecFileOptionsMaxBufferSmallStdErr = function (assert, done) {
-  let count = 0;
-  let stderrChild;
-  // Creates a buffer of 60 to stderr, less than 1024
-  getScript('large-err').then(script => {
-    stderrChild = execFile(script, ['60'], { maxBuffer: 50 }, (err, stdout, stderr) => {
-      assert.ok(/stderr maxBuffer exceeded/.test(err.toString()),
-        'error contains stderr maxBuffer exceeded message');
-      assert.ok(stderr.length >= 50, 'stderr has full buffer');
-      assert.equal(stdout, '', 'stdout is empty');
-      if (++count === 3) complete();
-    });
-    stderrChild.on('exit', exitHandler);
-    stderrChild.on('close', closeHandler);
-  }).catch(assert.fail);
-
-  function exitHandler (code, signal) {
-    // Sometimes the buffer limit is hit before the process closes successfully
-    // on both OSX/Windows
-    if (code === null) {
-      assert.equal(code, null, 'Exit code is null in exit handler');
-      assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
-    }
-    else {
-      assert.equal(code, 0, 'Exit code is 0 in exit handler');
-      assert.equal(signal, null, 'Signal is null in exit handler');
-    }
-    if (++count === 3) complete();
-  }
-
-  function closeHandler (code, signal) {
-    // Sometimes the buffer limit is hit before the process closes successfully
-    // on both OSX/Windows
-    if (code === null) {
-      assert.equal(code, null, 'Exit code is null in close handler');
-      assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler');
-    }
-    else {
-      assert.equal(code, 0, 'Exit code is 0 in close handler');
-      assert.equal(signal, null, 'Signal is null in close handler');
-    }
-    if (++count === 3) complete();
-  }
-
-  function complete () {
-    stderrChild.off('exit', exitHandler);
-    stderrChild.off('close', closeHandler);
-    done();
-  }
-};
-
-exports.testChildExecFileKillSignal = function (assert, done) {
-  getScript('wait').then(script => {
-    execFile(script, {
-      killSignal: 'beepbeep',
-      timeout: 10
-    }, function (err, stdout, stderr) {
-      assert.equal(err.signal, 'beepbeep', 'correctly used custom killSignal');
-      done();
-    });
-  }).catch(assert.fail);
-};
-
-exports.testChildProperties = function (assert, done) {
-  getScript('check-env').then(script => {
-    let child = spawn(script, {
-      env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
-    });
-
-    if (isWindows)
-      assert.ok(true, 'Windows environment does not have `pid`');
-    else
-      assert.ok(child.pid > 0, 'Child has a pid');
-  }).then(done, assert.fail);
-};
-
-exports.testChildStdinStreamLarge = function (assert, done) {
-  let REPEAT = 2000;
-  let allData = '';
-  // Use direct paths to more/cat, as we do not currently support calling non-files
-  // from subprocess.jsm
-  let child = spawn(CAT_PATH);
-
-  child.stdout.on('data', onData);
-  child.on('close', onClose);
-
-  for (let i = 0; i < REPEAT; i++)
-    emit(child.stdin, 'data', '12345\n');
-
-  emit(child.stdin, 'end');
-
-  function onData (data) {
-    allData += data;
-  }
-
-  function onClose (code, signal) {
-    child.stdout.off('data', onData);
-    child.off('close', onClose);
-    assert.equal(code, 0, 'exited succesfully');
-    assert.equal(signal, null, 'no kill signal given');
-    assert.equal(allData.replace(/\W/g, '').length, '12345'.length * REPEAT,
-      'all data processed from stdin');
-    done();
-  }
-};
-
-exports.testChildStdinStreamSmall = function (assert, done) {
-  let allData = '';
-  let child = spawn(CAT_PATH);
-  child.stdout.on('data', onData);
-  child.on('close', onClose);
-
-  emit(child.stdin, 'data', '12345');
-  emit(child.stdin, 'end');
-
-  function onData (data) {
-    allData += data;
-  }
-
-  function onClose (code, signal) {
-    child.stdout.off('data', onData);
-    child.off('close', onClose);
-    assert.equal(code, 0, 'exited succesfully');
-    assert.equal(signal, null, 'no kill signal given');
-    assert.equal(allData.trim(), '12345', 'all data processed from stdin');
-    done();
-  }
-};
-/*
- * This tests failures when an error is thrown attempting to
- * spawn the process, like an invalid command
- */
-exports.testChildEventsSpawningError= function (assert, done) {
-  let handlersCalled = 0;
-  let child = execFile('i-do-not-exist', (err, stdout, stderr) => {
-    assert.ok(err, 'error was passed into callback');
-    assert.equal(stdout, '', 'stdout is empty')
-    assert.equal(stderr, '', 'stderr is empty');
-    if (++handlersCalled === 3) complete();
-  });
-
-  child.on('error', handleError);
-  child.on('exit', handleExit);
-  child.on('close', handleClose);
-
-  function handleError (e) {
-    assert.ok(e, 'error passed into error handler');
-    if (++handlersCalled === 3) complete();
-  }
-
-  function handleClose (code, signal) {
-    assert.equal(code, -1,
-      'process was never spawned, therefore exit code is -1');
-    assert.equal(signal, null, 'signal should be null');
-    if (++handlersCalled === 3) complete();
-  }
-
-  function handleExit (code, signal) {
-    assert.fail('Close event should not be called on init failure');
-  }
-
-  function complete () {
-    child.off('error', handleError);
-    child.off('exit', handleExit);
-    child.off('close', handleClose);
-    done();
-  }
-};
-
-exports.testSpawnOptions = function (assert, done) {
-  let count = 0;
-  let envStdout = '';
-  let cwdStdout = '';
-  let checkEnv, checkPwd, envChild, cwdChild;
-  getScript('check-env').then(script => {
-    checkEnv = script;
-    return getScript('check-pwd');
-  }).then(script => {
-    checkPwd = script;
-
-    envChild = spawn(checkEnv, {
-      env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
-    });
-    cwdChild = spawn(checkPwd, { cwd: PROFILE_DIR });
-
-    // Do these need to be unbound?
-    envChild.stdout.on('data', data => envStdout += data);
-    cwdChild.stdout.on('data', data => cwdStdout += data);
-
-    envChild.on('close', envClose);
-    cwdChild.on('close', cwdClose);
-  }).catch(assert.fail);
-
-  function envClose () {
-    assert.equal(envStdout.trim(), 'my-value-test', 'spawn correctly passed in ENV');
-    if (++count === 2) complete();
-  }
-
-  function cwdClose () {
-    // Check for PROFILE_DIR in the output because
-    // some systems resolve symbolic links, and on OSX
-    // /var -> /private/var
-    let isCorrectPath = ~cwdStdout.trim().indexOf(PROFILE_DIR);
-    assert.ok(isCorrectPath, 'spawn correctly passed in cwd');
-    if (++count === 2) complete();
-  }
-
-  function complete () {
-    envChild.off('close', envClose);
-    cwdChild.off('close', cwdClose);
-    done();
-  }
-};
-
-exports.testFork = function (assert) {
-  assert.throws(function () {
-    fork();
-  }, /not currently supported/, 'fork() correctly throws an unsupported error');
-};
-
-after(exports, cleanUp);
-
-require("sdk/test").run(exports);
-
-// Test disabled because of bug 979675
-module.exports = {};
deleted file mode 100644
--- a/addon-sdk/source/test/test-chrome.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-var chrome = require('chrome');
-
-const FIXTURES_URL = module.uri.substr(0, module.uri.lastIndexOf('/') + 1) +
-                     'fixtures/chrome-worker/'
-
-exports['test addEventListener'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'addEventListener.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.addEventListener('message', function(event) {
-    assert.equal(event.data, 'Hello', 'message received');
-    worker.terminate();
-    done();
-  });
-};
-
-exports['test onmessage'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'onmessage.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.onmessage = function(event) {
-    assert.equal(event.data, 'ok', 'message received');
-    worker.terminate();
-    done();
-  };
-  worker.postMessage('ok');
-};
-
-exports['test setTimeout'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'setTimeout.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.onmessage = function(event) {
-    assert.equal(event.data, 'ok', 'setTimeout fired');
-    worker.terminate();
-    done();
-  };
-};
-
-exports['test jsctypes'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'jsctypes.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.onmessage = function(event) {
-    assert.equal(event.data, 'function', 'ctypes.open is a function');
-    worker.terminate();
-    done();
-  };
-};
-
-exports['test XMLHttpRequest'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'xhr.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.onmessage = function(event) {
-    assert.equal(event.data, 'ok', 'XMLHttpRequest works');
-    worker.terminate();
-    done();
-  };
-};
-
-exports['test onerror'] = function(assert, done) {
-  let uri = FIXTURES_URL + 'onerror.js';
-
-  let worker = new chrome.ChromeWorker(uri);
-  worker.onerror = function(event) {
-    assert.equal(event.filename, uri, 'event reports the correct uri');
-    assert.equal(event.lineno, 6, 'event reports the correct line number');
-    assert.equal(event.target, worker, 'event reports the correct worker');
-    assert.ok(event.message.match(/ok/),
-                'event contains the exception message');
-    // Call preventDefault in order to avoid being displayed in JS console.
-    event.preventDefault();
-    worker.terminate();
-    done();
-  };
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-clipboard.js
+++ /dev/null
@@ -1,170 +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";
-
-require("sdk/clipboard");
-
-const { Cc, Ci } = require("chrome");
-
-const imageTools = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools);
-const io = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
-const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].getService(Ci.nsIAppShellService);
-
-const XHTML_NS = "http://www.w3.org/1999/xhtml";
-const base64png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
-                  "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
-                  "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
-                  "bWRR9AAAAABJRU5ErkJggg%3D%3D";
-
-const { base64jpeg } = require("./fixtures");
-
-const { platform } = require("sdk/system");
-// For Windows, Mac and Linux, platform returns the following: winnt, darwin and linux.
-var isWindows = platform.toLowerCase().indexOf("win") == 0;
-
-// Test the typical use case, setting & getting with no flavors specified
-exports["test With No Flavor"] = function(assert) {
-  var contents = "hello there";
-  var flavor = "text";
-  var fullFlavor = "text/unicode";
-  var clip = require("sdk/clipboard");
-
-  // Confirm we set the clipboard
-  assert.ok(clip.set(contents));
-
-  // Confirm flavor is set
-  assert.equal(clip.currentFlavors[0], flavor);
-
-  // Confirm we set the clipboard
-  assert.equal(clip.get(), contents);
-
-  // Confirm we can get the clipboard using the flavor
-  assert.equal(clip.get(flavor), contents);
-
-  // Confirm we can still get the clipboard using the full flavor
-  assert.equal(clip.get(fullFlavor), contents);
-};
-
-// Test the slightly less common case where we specify the flavor
-exports["test With Flavor"] = function(assert) {
-  var contents = "<b>hello there</b>";
-  var contentsText = "hello there";
-
-  // On windows, HTML clipboard includes extra data.
-  // The values are from widget/windows/nsDataObj.cpp.
-  var contentsWindowsHtml = "<html><body>\n<!--StartFragment-->" +
-                            contents +
-                            "<!--EndFragment-->\n</body>\n</html>";
-
-  var flavor = "html";
-  var fullFlavor = "text/html";
-  var unicodeFlavor = "text";
-  var unicodeFullFlavor = "text/unicode";
-  var clip = require("sdk/clipboard");
-
-  assert.ok(clip.set(contents, flavor));
-
-  assert.equal(clip.currentFlavors[0], unicodeFlavor);
-  assert.equal(clip.currentFlavors[1], flavor);
-  assert.equal(clip.get(), contentsText);
-  assert.equal(clip.get(flavor), isWindows ? contentsWindowsHtml : contents);
-  assert.equal(clip.get(fullFlavor), isWindows ? contentsWindowsHtml : contents);
-  assert.equal(clip.get(unicodeFlavor), contentsText);
-  assert.equal(clip.get(unicodeFullFlavor), contentsText);
-};
-
-// Test that the typical case still works when we specify the flavor to set
-exports["test With Redundant Flavor"] = function(assert) {
-  var contents = "<b>hello there</b>";
-  var flavor = "text";
-  var fullFlavor = "text/unicode";
-  var clip = require("sdk/clipboard");
-
-  assert.ok(clip.set(contents, flavor));
-  assert.equal(clip.currentFlavors[0], flavor);
-  assert.equal(clip.get(), contents);
-  assert.equal(clip.get(flavor), contents);
-  assert.equal(clip.get(fullFlavor), contents);
-};
-
-exports["test Not In Flavor"] = function(assert) {
-  var contents = "hello there";
-  var flavor = "html";
-  var clip = require("sdk/clipboard");
-
-  assert.ok(clip.set(contents));
-  // If there's nothing on the clipboard with this flavor, should return null
-  assert.equal(clip.get(flavor), null);
-};
-
-exports["test Set Image"] = function(assert) {
-  var clip = require("sdk/clipboard");
-  var flavor = "image";
-  var fullFlavor = "image/png";
-
-  assert.ok(clip.set(base64png, flavor), "clipboard set");
-  assert.equal(clip.currentFlavors[0], flavor, "flavor is set");
-};
-
-exports["test Get Image"] = function* (assert) {
-  var clip = require("sdk/clipboard");
-
-  clip.set(base64png, "image");
-
-  var contents = clip.get();
-  const hiddenWindow = appShellService.hiddenDOMWindow;
-  const Image = hiddenWindow.Image;
-  const canvas = hiddenWindow.document.createElementNS(XHTML_NS, "canvas");
-  let context = canvas.getContext("2d");
-
-  const imageURLToPixels = (imageURL) => {
-    return new Promise((resolve) => {
-      let img = new Image();
-
-      img.onload = function() {
-        context.drawImage(this, 0, 0);
-
-        let pixels = Array.join(context.getImageData(0, 0, 32, 32).data);
-        resolve(pixels);
-      };
-
-      img.src = imageURL;
-    });
-  };
-
-  let [base64pngPixels, clipboardPixels] = yield Promise.all([
-    imageURLToPixels(base64png), imageURLToPixels(contents),
-  ]);
-
-  assert.ok(base64pngPixels === clipboardPixels,
-            "Image gets from clipboard equals to image sets to the clipboard");
-};
-
-exports["test Set Image Type Not Supported"] = function(assert) {
-  var clip = require("sdk/clipboard");
-  var flavor = "image";
-
-  assert.throws(function () {
-    clip.set(base64jpeg, flavor);
-  }, "Invalid flavor for image/jpeg");
-
-};
-
-// Notice that `imageTools.decodeImage`, used by `clipboard.set` method for
-// images, write directly to the javascript console the error in case the image
-// is corrupt, even if the error is catched.
-//
-// See: http://mxr.mozilla.org/mozilla-central/source/image/src/Decoder.cpp#136
-exports["test Set Image Type Wrong Data"] = function(assert) {
-  var clip = require("sdk/clipboard");
-  var flavor = "image";
-
-  var wrongPNG = "data:image/png" + base64jpeg.substr(15);
-
-  assert.throws(function () {
-    clip.set(wrongPNG, flavor);
-  }, "Unable to decode data given in a valid image.");
-};
-
-require("sdk/test").run(exports)
deleted file mode 100644
--- a/addon-sdk/source/test/test-collection.js
+++ /dev/null
@@ -1,128 +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 collection = require("sdk/util/collection");
-
-exports.testAddRemove = function (assert) {
-  let coll = new collection.Collection();
-  compare(assert, coll, []);
-  addRemove(assert, coll, [], false);
-};
-
-exports.testAddRemoveBackingArray = function (assert) {
-  let items = ["foo"];
-  let coll = new collection.Collection(items);
-  compare(assert, coll, items);
-  addRemove(assert, coll, items, true);
-
-  items = ["foo", "bar"];
-  coll = new collection.Collection(items);
-  compare(assert, coll, items);
-  addRemove(assert, coll, items, true);
-};
-
-exports.testProperty = function (assert) {
-  let obj = makeObjWithCollProp();
-  compare(assert, obj.coll, []);
-  addRemove(assert, obj.coll, [], false);
-
-  // Test single-value set.
-  let items = ["foo"];
-  obj.coll = items[0];
-  compare(assert, obj.coll, items);
-  addRemove(assert, obj.coll, items, false);
-
-  // Test array set.
-  items = ["foo", "bar"];
-  obj.coll = items;
-  compare(assert, obj.coll, items);
-  addRemove(assert, obj.coll, items, false);
-};
-
-exports.testPropertyBackingArray = function (assert) {
-  let items = ["foo"];
-  let obj = makeObjWithCollProp(items);
-  compare(assert, obj.coll, items);
-  addRemove(assert, obj.coll, items, true);
-
-  items = ["foo", "bar"];
-  obj = makeObjWithCollProp(items);
-  compare(assert, obj.coll, items);
-  addRemove(assert, obj.coll, items, true);
-};
-
-// Adds some values to coll and then removes them.  initialItems is an array
-// containing coll's initial items.  isBacking is true if initialItems is coll's
-// backing array; the point is that updates to coll should affect initialItems
-// if that's the case.
-function addRemove(assert, coll, initialItems, isBacking) {
-  let items = isBacking ? initialItems : initialItems.slice(0);
-  let numInitialItems = items.length;
-
-  // Test add(val).
-  let numInsertions = 5;
-  for (let i = 0; i < numInsertions; i++) {
-    compare(assert, coll, items);
-    coll.add(i);
-    if (!isBacking)
-      items.push(i);
-  }
-  compare(assert, coll, items);
-
-  // Add the items we just added to make sure duplicates aren't added.
-  for (let i = 0; i < numInsertions; i++)
-    coll.add(i);
-  compare(assert, coll, items);
-
-  // Test remove(val).  Do a kind of shuffled remove.  Remove item 1, then
-  // item 0, 3, 2, 5, 4, ...
-  for (let i = 0; i < numInsertions; i++) {
-    let val = i % 2 ? i - 1 :
-              i === numInsertions - 1 ? i : i + 1;
-    coll.remove(val);
-    if (!isBacking)
-      items.splice(items.indexOf(val), 1);
-    compare(assert, coll, items);
-  }
-  assert.equal(coll.length, numInitialItems,
-               "All inserted items should be removed");
-
-  // Remove the items we just removed.  coll should be unchanged.
-  for (let i = 0; i < numInsertions; i++)
-    coll.remove(i);
-  compare(assert, coll, items);
-
-  // Test add and remove([val1, val2]).
-  let newItems = [0, 1];
-  coll.add(newItems);
-  compare(assert, coll, isBacking ? items : items.concat(newItems));
-  coll.remove(newItems);
-  compare(assert, coll, items);
-  assert.equal(coll.length, numInitialItems,
-               "All inserted items should be removed");
-}
-
-// Asserts that the items in coll are the items of array.
-function compare(assert, coll, array) {
-  assert.equal(coll.length, array.length,
-               "Collection length should be correct");
-  let numItems = 0;
-  for (let item in coll) {
-    assert.equal(item, array[numItems], "Items should be equal");
-    numItems++;
-  }
-  assert.equal(numItems, array.length,
-               "Number of items in iteration should be correct");
-}
-
-// Returns a new object with a collection property named "coll".  backingArray,
-// if defined, will create the collection with that backing array.
-function makeObjWithCollProp(backingArray) {
-  let obj = {};
-  collection.addCollectionProperty(obj, "coll", backingArray);
-  return obj;
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-commonjs-test-adapter.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/. */
-
-"use strict";
-
-exports["test custom `Assert`'s"] = require("./commonjs-test-adapter/asserts");
-
-// Disabling this check since it is not yet supported by jetpack.
-// if (module == require.main)
-  require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-content-events.js
+++ /dev/null
@@ -1,92 +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 { Loader } = require("sdk/test/loader");
-const { getMostRecentBrowserWindow, getInnerId } = require("sdk/window/utils");
-const { openTab, closeTab, getBrowserForTab } = require("sdk/tabs/utils");
-const { defer } = require("sdk/core/promise");
-const { curry, identity, partial } = require("sdk/lang/functional");
-
-const { nuke } = require("sdk/loader/sandbox");
-
-const { open: openWindow, close: closeWindow } = require('sdk/window/helpers');
-
-const openBrowserWindow = partial(openWindow, null, {features: {toolbar: true}});
-
-var when = curry(function(options, tab) {
-  let type = options.type || options;
-  let capture = options.capture || false;
-  let target = getBrowserForTab(tab);
-  let { promise, resolve } = defer();
-
-  target.addEventListener(type, function handler(event) {
-    if (!event.target.defaultView.frameElement) {
-      target.removeEventListener(type, handler, capture);
-      resolve(tab);
-    }
-  }, capture);
-
-  return promise;
-});
-
-var use = use = value => () => value;
-
-
-var open = curry((url, window) => openTab(window, url));
-var close = function(tab) {
-  let promise = when("pagehide", tab);
-  closeTab(tab);
-  return promise;
-}
-
-exports["test dead object errors"] = function(assert, done) {
-  let system = require("sdk/system/events");
-  let loader = Loader(module);
-  let { events } = loader.require("sdk/content/events");
-
-  // The dead object error is properly reported on console but
-  // doesn't raise any test's exception
-  function onMessage({ subject }) {
-    let message = subject.wrappedJSObject;
-    let { level } = message;
-    let text = String(message.arguments[0]);
-
-    if (level === "error" && text.includes("can't access dead object"))
-      fail(text);
-  }
-
-  let cleanup = () => system.off("console-api-log-event", onMessage);
-  let fail = (reason) => {
-    cleanup();
-    assert.fail(reason);
-  }
-
-  loader.unload();
-
-  nuke(loader.sharedGlobalSandbox);
-
-  system.on("console-api-log-event", onMessage, true);
-
-  openBrowserWindow().
-    then(closeWindow).
-    then(() => assert.pass("checking dead object errors")).
-    then(cleanup).
-    then(done, fail);
-};
-
-// ignore *-document-global-created events that are not very consistent.
-// only allow data uris that we create to ignore unwanted events, e.g.,
-// about:blank, http:// requests from Fennec's `about:`home page that displays
-// add-ons a user could install, local `searchplugins`, other chrome uris
-// Calls callback if passes filter
-function eventFilter (type, target, callback) {
-  if (target.URL.startsWith("data:text/html,") &&
-    type !== "chrome-document-global-created" &&
-    type !== "content-document-global-created")
-
-    callback();
-}
-require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-content-script.js
+++ /dev/null
@@ -1,838 +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 hiddenFrames = require("sdk/frame/hidden-frame");
-const { create: makeFrame } = require("sdk/frame/utils");
-const { window } = require("sdk/addon/window");
-const { Loader } = require('sdk/test/loader');
-const { URL } = require("sdk/url");
-const testURI = require("./fixtures").url("test.html");
-const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
-
-/*
- * Utility function that allow to easily run a proxy test with a clean
- * new HTML document. See first unit test for usage.
- */
-function createProxyTest(html, callback) {
-  return function (assert, done) {
-    let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
-    let principalLoaded = false;
-
-    let element = makeFrame(window.document, {
-      nodeName: "iframe",
-      type: "content",
-      allowJavascript: true,
-      allowPlugins: true,
-      allowAuth: true,
-      uri: testURI
-    });
-
-    element.addEventListener("DOMContentLoaded", onDOMReady);
-
-    function onDOMReady() {
-      // Reload frame after getting principal from `testURI`
-      if (!principalLoaded) {
-        element.setAttribute("src", url);
-        principalLoaded = true;
-        return;
-      }
-
-      assert.equal(element.getAttribute("src"), url, "correct URL loaded");
-      element.removeEventListener("DOMContentLoaded", onDOMReady);
-      let xrayWindow = element.contentWindow;
-      let rawWindow = xrayWindow.wrappedJSObject;
-
-      let isDone = false;
-      let helper = {
-        xrayWindow: xrayWindow,
-        rawWindow: rawWindow,
-        createWorker: function (contentScript) {
-          return createWorker(assert, xrayWindow, contentScript, helper.done);
-        },
-        done: function () {
-          if (isDone)
-            return;
-          isDone = true;
-          element.remove();
-          done();
-        }
-      };
-      callback(helper, assert);
-    }
-  };
-}
-
-function createWorker(assert, xrayWindow, contentScript, done) {
-  let loader = Loader(module);
-  let Worker = loader.require("sdk/content/worker").Worker;
-  let worker = Worker({
-    window: xrayWindow,
-    contentScript: [
-      'new ' + function () {
-        assert = function assert(v, msg) {
-          self.port.emit("assert", {assertion:v, msg:msg});
-        }
-        done = function done() {
-          self.port.emit("done");
-        }
-      },
-      contentScript
-    ]
-  });
-
-  worker.port.on("done", done);
-  worker.port.on("assert", function (data) {
-    assert.ok(data.assertion, data.msg);
-  });
-
-  return worker;
-}
-
-/* Examples for the `createProxyTest` uses */
-
-var html = "<script>var documentGlobal = true</script>";
-
-exports["test Create Proxy Test"] = createProxyTest(html, function (helper, assert) {
-  // You can get access to regular `test` object in second argument of
-  // `createProxyTest` method:
-  assert.ok(helper.rawWindow.documentGlobal,
-              "You have access to a raw window reference via `helper.rawWindow`");
-  assert.ok(!("documentGlobal" in helper.xrayWindow),
-              "You have access to an XrayWrapper reference via `helper.xrayWindow`");
-
-  // If you do not create a Worker, you have to call helper.done(),
-  // in order to say when your test is finished
-  helper.done();
-});
-
-exports["test Create Proxy Test With Worker"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    "new " + function WorkerScope() {
-      assert(true, "You can do assertions in your content script");
-      // And if you create a worker, you either have to call `done`
-      // from content script or helper.done()
-      done();
-    }
-  );
-
-});
-
-exports["test Create Proxy Test With Events"] = createProxyTest("", function (helper, assert) {
-
-  let worker = helper.createWorker(
-    "new " + function WorkerScope() {
-      self.port.emit("foo");
-    }
-  );
-
-  worker.port.on("foo", function () {
-    assert.pass("You can use events");
-    // And terminate your test with helper.done:
-    helper.done();
-  });
-
-});
-
-/* Disabled due to bug 1038432
-// Bug 714778: There was some issue around `toString` functions
-//             that ended up being shared between content scripts
-exports["test Shared To String Proxies"] = createProxyTest("", function(helper) {
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // We ensure that `toString` can't be modified so that nothing could
-      // leak to/from the document and between content scripts
-      // It only applies to JS proxies, there isn't any such issue with xrays.
-      //document.location.toString = function foo() {};
-      document.location.toString.foo = "bar";
-      assert("foo" in document.location.toString, "document.location.toString can be modified");
-      assert(document.location.toString() == "data:text/html;charset=utf-8,",
-             "First document.location.toString()");
-      self.postMessage("next");
-    }
-  );
-  worker.on("message", function () {
-    helper.createWorker(
-      'new ' + function ContentScriptScope2() {
-        assert(!("foo" in document.location.toString),
-               "document.location.toString is different for each content script");
-        assert(document.location.toString() == "data:text/html;charset=utf-8,",
-               "Second document.location.toString()");
-        done();
-      }
-    );
-  });
-});
-*/
-
-// Ensure that postMessage is working correctly across documents with an iframe
-var html = '<iframe id="iframe" name="test" src="data:text/html;charset=utf-8," />';
-exports["test postMessage"] = createProxyTest(html, function (helper, assert) {
-  let ifWindow = helper.xrayWindow.document.getElementById("iframe").contentWindow;
-  // Listen without proxies, to check that it will work in regular case
-  // simulate listening from a web document.
-  ifWindow.addEventListener("message", function(event) {
-    // As we are in system principal, event is an XrayWrapper
-    // xrays use current compartments when calling postMessage method.
-    // Whereas js proxies was using postMessage method compartment,
-    // not the caller one.
-    assert.strictEqual(event.source, helper.xrayWindow,
-                      "event.source is the top window");
-    assert.equal(event.origin, testHost, "origin matches testHost");
-
-    assert.equal(event.data, "{\"foo\":\"bar\\n \\\"escaped\\\".\"}",
-                     "message data is correct");
-
-    helper.done();
-  }, {once: true});
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      var json = JSON.stringify({foo : "bar\n \"escaped\"."});
-
-      document.getElementById("iframe").contentWindow.postMessage(json, "*");
-    }
-  );
-});
-
-var html = '<input id="input2" type="checkbox" />';
-exports["test Object Listener"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Test objects being given as event listener
-      let input = document.getElementById("input2");
-      let myClickListener = {
-        called: false,
-        handleEvent: function(event) {
-          assert(this === myClickListener, "`this` is the original object");
-          assert(!this.called, "called only once");
-          this.called = true;
-          assert(event.target, input, "event.target is the wrapped window");
-          done();
-        }
-      };
-
-      window.addEventListener("click", myClickListener, true);
-      input.click();
-      window.removeEventListener("click", myClickListener, true);
-    }
-  );
-
-});
-
-exports["test Object Listener 2"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    ('new ' + function ContentScriptScope() {
-      // variable replaced with `testHost`
-      let testHost = "TOKEN";
-      // Verify object as DOM event listener
-      let myMessageListener = {
-        called: false,
-        handleEvent: function(event) {
-          window.removeEventListener("message", myMessageListener, true);
-
-          assert(this == myMessageListener, "`this` is the original object");
-          assert(!this.called, "called only once");
-          this.called = true;
-          assert(event.target == document.defaultView, "event.target is the wrapped window");
-          assert(event.source == document.defaultView, "event.source is the wrapped window");
-          assert(event.origin == testHost, "origin matches testHost");
-          assert(event.data == "ok", "message data is correct");
-          done();
-        }
-      };
-
-      window.addEventListener("message", myMessageListener, true);
-      document.defaultView.postMessage("ok", '*');
-    }
-  ).replace("TOKEN", testHost));
-
-});
-
-var html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
-             '<input id="input2" type="checkbox" />';
-
-exports.testStringOverload = createProxyTest(html, function (helper, assert) {
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // RightJS is hacking around String.prototype, and do similar thing:
-      // Pass `this` from a String prototype method.
-      // It is funny because typeof this == "object"!
-      // So that when we pass `this` to a native method,
-      // our proxy code can fail on another even more crazy thing.
-      // See following test to see what fails around proxies.
-      String.prototype.update = function () {
-        assert(typeof this == "object", "in update, `this` is an object");
-        assert(this.toString() == "input", "in update, `this.toString works");
-        return document.querySelectorAll(this);
-      };
-      assert("input".update().length == 3, "String.prototype overload works");
-      done();
-    }
-  );
-});
-
-exports["test Element.matches()"] = createProxyTest("", function (helper) {
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check matches XrayWrappers bug (Bug 658909):
-      // Test that Element.matches() does not return bad results when we are
-      // not calling it from the node itself.
-      assert(document.createElement( "div" ).matches("div"),
-             "matches works while being called from the node");
-      assert(document.documentElement.matches.call(
-               document.createElement( "div" ),
-               "div"
-             ),
-             "matches works while being called from a " +
-             "function reference to " +
-             "document.documentElement.matches.call");
-      done();
-    }
-  );
-});
-
-exports["test Events Overload"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // If we add a "____proxy" attribute on XrayWrappers in order to store
-      // the related proxy to create an unique proxy for each wrapper;
-      // we end up setting this attribute to prototype objects :x
-      // And so, instances created with such prototype will be considered
-      // as equal to the prototype ...
-      //   // Internal method that return the proxy for a given XrayWrapper
-      //   function proxify(obj) {
-      //     if (obj._proxy) return obj._proxy;
-      //     return obj._proxy = Proxy.create(...);
-      //   }
-      //
-      //   // Get a proxy of an XrayWrapper prototype object
-      //   let proto = proxify(xpcProto);
-      //
-      //   // Use this proxy as a prototype
-      //   function Constr() {}
-      //   Constr.proto = proto;
-      //
-      //   // Try to create an instance using this prototype
-      //   let xpcInstance = new Constr();
-      //   let wrapper = proxify(xpcInstance)
-      //
-      //   xpcProto._proxy = proto and as xpcInstance.__proto__ = xpcProto,
-      //   xpcInstance._proxy = proto ... and profixy(xpcInstance) = proto :(
-      //
-      let proto = window.document.createEvent('HTMLEvents').__proto__;
-      window.Event.prototype = proto;
-      let event = document.createEvent('HTMLEvents');
-      assert(event !== proto, "Event should not be equal to its prototype");
-      event.initEvent('dataavailable', true, true);
-      assert(event.type === 'dataavailable', "Events are working fine");
-      done();
-    }
-  );
-
-});
-
-exports["test Nested Attributes"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // XrayWrappers has a bug when you set an attribute on it,
-      // in some cases, it creates an unnecessary wrapper that introduces
-      // a different object that refers to the same original object
-      // Check that our wrappers don't reproduce this bug
-      // SEE BUG 658560: Fix identity problem with CrossOriginWrappers
-      let o = {sandboxObject:true};
-      window.nested = o;
-      o.foo = true;
-      assert(o === window.nested, "Nested attribute to sandbox object should not be proxified");
-      window.nested = document;
-      assert(window.nested === document, "Nested attribute to proxy should not be double proxified");
-      done();
-    }
-  );
-
-});
-
-exports["test Form nodeName"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Check form[nodeName]
-      let form = document.createElement("form");
-      let input = document.createElement("input");
-      input.setAttribute("name", "test");
-      form.appendChild(input);
-      body.appendChild(form);
-      assert(form.test == input, "form[nodeName] is valid");
-      body.removeChild(form);
-      done();
-    }
-  );
-
-});
-
-exports["test localStorage"] = createProxyTest("", function (helper, assert) {
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check localStorage:
-      assert(window.localStorage, "has access to localStorage");
-      window.localStorage.name = 1;
-      assert(window.localStorage.name == 1, "localStorage appears to work");
-
-      self.port.on("step2", function () {
-        window.localStorage.clear();
-        assert(window.localStorage.name == undefined, "localStorage really, really works");
-        done();
-      });
-      self.port.emit("step1");
-    }
-  );
-
-  worker.port.on("step1", function () {
-    assert.equal(helper.rawWindow.localStorage.name, 1, "localStorage really works");
-    worker.port.emit("step2");
-  });
-
-});
-
-exports["test Auto Unwrap Custom Attributes"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Setting a custom object to a proxy attribute is not wrapped when we get it afterward
-      let object = {custom: true, enumerable: false};
-      body.customAttribute = object;
-      assert(object === body.customAttribute, "custom JS attributes are not wrapped");
-      done();
-    }
-  );
-
-});
-
-exports["test Object Tag"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // <object>, <embed> and other tags return typeof 'object'
-      let flash = document.createElement("object");
-      assert(typeof flash == "object", "<object> is typeof 'function'");
-      assert(flash.toString().match(/\[object HTMLObjectElement.*\]/), "<object> is HTMLObjectElement");
-      assert("setAttribute" in flash, "<object> has a setAttribute method");
-      done();
-    }
-  );
-
-});
-
-exports["test Highlight toString Behavior"] = createProxyTest("", function (helper, assert) {
-  // We do not have any workaround this particular use of toString
-  // applied on <object> elements. So disable this test until we found one!
-  //assert.equal(helper.rawWindow.Object.prototype.toString.call(flash), "[object HTMLObjectElement]", "<object> is HTMLObjectElement");
-  function f() {};
-  let funToString = Object.prototype.toString.call(f);
-  assert.ok(/\[object Function.*\]/.test(funToString), "functions are functions 1");
-
-  // This is how jquery call toString:
-  let strToString = helper.rawWindow.Object.prototype.toString.call("");
-  assert.ok(/\[object String.*\]/.test(strToString), "strings are strings");
-
-  let o = {__exposedProps__:{}};
-  let objToString = helper.rawWindow.Object.prototype.toString.call(o);
-  assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects");
-
-  // Make sure to pass a function from the same compartments
-  // or toString will return [object Object] on FF8+
-  let f2 = helper.rawWindow.eval("(function () {})");
-  let funToString2 = helper.rawWindow.Object.prototype.toString.call(f2);
-  assert.ok(/\[object Function.*\]/.test(funToString2), "functions are functions 2");
-
-  helper.done();
-});
-
-exports["test Document TagName"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      let body = document.body;
-      // Check document[tagName]
-      let div = document.createElement("div");
-      div.setAttribute("name", "test");
-      body.appendChild(div);
-      assert(!document.test, "document[divName] is undefined");
-      body.removeChild(div);
-
-      let form = document.createElement("form");
-      form.setAttribute("name", "test");
-      body.appendChild(form);
-      assert(document.test == form, "document[formName] is valid");
-      body.removeChild(form);
-
-      let img = document.createElement("img");
-      img.setAttribute("name", "test");
-      body.appendChild(img);
-      assert(document.test == img, "document[imgName] is valid");
-      body.removeChild(img);
-      done();
-    }
-  );
-
-});
-
-var html = '<iframe id="iframe" name="test" src="data:text/html;charset=utf-8," />';
-exports["test Window Frames"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'let glob = this; new ' + function ContentScriptScope() {
-      // Check window[frameName] and window.frames[i]
-      let iframe = document.getElementById("iframe");
-      //assert(window.frames.length == 1, "The iframe is reported in window.frames check1");
-      //assert(window.frames[0] == iframe.contentWindow, "The iframe is reported in window.frames check2");
-      assert(window.test == iframe.contentWindow, "window[frameName] is valid");
-      done();
-    }
-  );
-
-});
-
-exports["test Collections"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Highlight XPCNativeWrapper bug with HTMLCollection
-      // tds[0] is only defined on first access :o
-      let body = document.body;
-      let div = document.createElement("div");
-      body.appendChild(div);
-      div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
-      let tds = div.getElementsByTagName("td");
-      assert(tds[0] == tds[0], "We can get array element multiple times");
-      body.removeChild(div);
-      done();
-    }
-  );
-
-});
-
-var html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
-             '<input id="input2" type="checkbox" />';
-exports["test Collections 2"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify that NodeList/HTMLCollection are working fine
-      let body = document.body;
-      let inputs = body.getElementsByTagName("input");
-      assert(body.childNodes.length == 3, "body.childNodes length is correct");
-      assert(inputs.length == 3, "inputs.length is correct");
-      assert(body.childNodes[0] == inputs[0], "body.childNodes[0] is correct");
-      assert(body.childNodes[1] == inputs[1], "body.childNodes[1] is correct");
-      assert(body.childNodes[2] == inputs[2], "body.childNodes[2] is correct");
-      let count = 0;
-      for(let i in body.childNodes) {
-        count++;
-      }
-
-      assert(count >= 3, "body.childNodes is iterable");
-      done();
-    }
-  );
-
-});
-
-exports["test XMLHttpRequest"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // XMLHttpRequest doesn't support XMLHttpRequest.apply,
-      // that may break our proxy code
-      assert(new window.XMLHttpRequest(), "we are able to instantiate XMLHttpRequest object");
-      done();
-    }
-  );
-
-});
-
-exports["test XPathResult"] = createProxyTest("", function (helper, assert) {
-  const XPathResultTypes = ["ANY_TYPE",
-                            "NUMBER_TYPE", "STRING_TYPE", "BOOLEAN_TYPE",
-                            "UNORDERED_NODE_ITERATOR_TYPE",
-                            "ORDERED_NODE_ITERATOR_TYPE",
-                            "UNORDERED_NODE_SNAPSHOT_TYPE",
-                            "ORDERED_NODE_SNAPSHOT_TYPE",
-                            "ANY_UNORDERED_NODE_TYPE",
-                            "FIRST_ORDERED_NODE_TYPE"];
-
-  // Check XPathResult bug with constants being undefined on XPCNativeWrapper
-  let xpcXPathResult = helper.xrayWindow.XPathResult;
-
-  XPathResultTypes.forEach(function(type, i) {
-    assert.equal(xpcXPathResult.wrappedJSObject[type],
-                     helper.rawWindow.XPathResult[type],
-                     "XPathResult's constants are valid on unwrapped node");
-
-    assert.equal(xpcXPathResult[type], i,
-                     "XPathResult's constants are defined on " +
-                     "XPCNativeWrapper (platform bug #)");
-  });
-
-  let value = helper.rawWindow.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      self.port.on("value", function (value) {
-        // Check that our work around is working:
-        assert(window.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE === value,
-               "XPathResult works correctly on Proxies");
-        done();
-      });
-    }
-  );
-  worker.port.emit("value", value);
-});
-
-exports["test Prototype Inheritance"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify that inherited prototype function like initEvent
-      // are handled correctly. (e2.type will return an error if it's not the case)
-      let event1 = document.createEvent( 'MouseEvents' );
-      event1.initEvent( "click", true, true );
-      let event2 = document.createEvent( 'MouseEvents' );
-      event2.initEvent( "click", true, true );
-      assert(event2.type == "click", "We are able to create an event");
-      done();
-    }
-  );
-
-});
-
-exports["test Functions"] = createProxyTest("", function (helper) {
-
-  helper.rawWindow.callFunction = function callFunction(f) {
-    return f();
-  };
-  helper.rawWindow.isEqual = function isEqual(a, b) {
-    return a == b;
-  };
-  // bug 784116: workaround in order to allow proxy code to cache proxies on
-  // these functions:
-  helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'};
-  helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'};
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Check basic usage of functions
-      let closure2 = function () {return "ok";};
-      assert(window.wrappedJSObject.callFunction(closure2) == "ok", "Function references work");
-
-      // Ensure that functions are cached when being wrapped to native code
-      let closure = function () {};
-      assert(window.wrappedJSObject.isEqual(closure, closure), "Function references are cached before being wrapped to native");
-      done();
-    }
-  );
-
-});
-
-var html = '<input id="input2" type="checkbox" />';
-exports["test Listeners"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Verify listeners:
-      let input = document.getElementById("input2");
-      assert(input, "proxy.getElementById works");
-
-      function onclick() {};
-      input.onclick = onclick;
-      assert(input.onclick === onclick, "on* attributes are equal to original function set");
-
-      let addEventListenerCalled = false;
-      let expandoCalled = false;
-      input.addEventListener("click", function onclick(event) {
-        assert(!addEventListenerCalled, "closure given to addEventListener is called once");
-        if (addEventListenerCalled)
-          return;
-        addEventListenerCalled = true;
-
-        assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
-
-        let input2 = document.getElementById("input2");
-
-        input.onclick = function (event) {
-          input.onclick = null;
-          assert(!expandoCalled, "closure set to expando is called once");
-          if (expandoCalled) return;
-          expandoCalled = true;
-
-          assert(!event.target.ownerDocument.defaultView.documentGlobal, "event object is still wrapped and doesn't expose document globals");
-
-          setTimeout(function () {
-            input.click();
-            done();
-          }, 0);
-
-        }
-
-        setTimeout(function () {
-          input.click();
-        }, 0);
-
-      }, {capture: true, once: true});
-
-      input.click();
-    }
-  );
-
-});
-
-exports["test requestAnimationFrame"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      var self = (function() { return this; })();
-      window.requestAnimationFrame(function callback() {
-        assert(self == this, "self is equal to `this`");
-        done();
-      });
-    }
-  );
-
-});
-
-exports["testGlobalScope"] = createProxyTest("", function (helper) {
-
-  helper.createWorker(
-    'var toplevelScope = true;' +
-    'assert(window.toplevelScope, "variables in toplevel scope are set to `window` object");' +
-    'assert(this.toplevelScope, "variables in toplevel scope are set to `this` object");' +
-    'done();'
-  );
-
-});
-
-// Bug 715755: proxy code throw an exception on COW
-// Create an http server in order to simulate real cross domain documents
-exports["test Cross Domain Iframe"] = createProxyTest("", function (helper) {
-  let serverPort = 8099;
-  let server = require("./lib/httpd").startServerAsync(serverPort);
-  server.registerPathHandler("/", function handle(request, response) {
-    // Returns the webpage that receive a message and forward it back to its
-    // parent document by appending ' world'.
-    let content = "<html><head><meta charset='utf-8'></head>\n";
-    content += "<script>\n";
-    content += "  window.addEventListener('message', function (event) {\n";
-    content += "    parent.postMessage(event.data + ' world', '*');\n";
-    content += "  }, true);\n";
-    content += "</script>\n";
-    content += "<body></body>\n";
-    content += "</html>\n";
-    response.write(content);
-  });
-
-  let worker = helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      // Waits for the server page url
-      self.on("message", function (url) {
-        // Creates an iframe with this page
-        let iframe = document.createElement("iframe");
-        iframe.addEventListener("load", function() {
-          try {
-            // Try to communicate with iframe's content
-            window.addEventListener("message", function(event) {
-              assert(event.data == "hello world", "COW works properly");
-              self.port.emit("end");
-            }, {capture: true, once: true});
-            iframe.contentWindow.postMessage("hello", "*");
-          } catch(e) {
-            assert(false, "COW fails : "+e.message);
-          }
-        }, {capture: true, once: true});
-        iframe.setAttribute("src", url);
-        document.body.appendChild(iframe);
-      });
-    }
-  );
-
-  worker.port.on("end", function () {
-    server.stop(helper.done);
-  });
-
-  worker.postMessage("http://localhost:" + serverPort + "/");
-
-});
-
-// Bug 769006: Ensure that MutationObserver works fine with proxies
-var html = '<a href="foo">link</a>';
-exports["test MutationObvserver"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'new ' + function ContentScriptScope() {
-      if (typeof MutationObserver == "undefined") {
-        assert(true, "No MutationObserver for this FF version");
-        done();
-        return;
-      }
-      let link = document.getElementsByTagName("a")[0];
-
-      // Register a Mutation observer
-      let obs = new MutationObserver(function(mutations){
-        // Ensure that mutation data are valid
-        assert(mutations.length == 1, "only one attribute mutation");
-        let mutation = mutations[0];
-        assert(mutation.type == "attributes", "check `type`");
-        assert(mutation.target == link, "check `target`");
-        assert(mutation.attributeName == "href", "check `attributeName`");
-        assert(mutation.oldValue == "foo", "check `oldValue`");
-        obs.disconnect();
-        done();
-      });
-      obs.observe(document, {
-        subtree: true,
-        attributes: true,
-        attributeOldValue: true,
-        attributeFilter: ["href"]
-      });
-
-      // Modify the DOM
-      link.setAttribute("href", "bar");
-    }
-  );
-
-});
-
-var html = '<script>' +
-  'var accessCheck = function() {' +
-  '  assert(true, "exporting function works");' +
-  '  try{' +
-  '    exportedObj.prop;' +
-  '    assert(false, "content should not have access to content-script");' +
-  '  } catch(e) {' +
-  '    assert(e.toString().indexOf("Permission denied") != -1,' +
-  '           "content should not have access to content-script");' +
-  '  }' +
-  '}</script>';
-exports["test nsEp for content-script"] = createProxyTest(html, function (helper) {
-
-  helper.createWorker(
-    'let glob = this; new ' + function ContentScriptScope() {
-
-      exportFunction(assert, unsafeWindow, { defineAs: "assert" });
-      window.wrappedJSObject.assert(true, "assert exported");
-      window.wrappedJSObject.exportedObj = { prop: 42 };
-      window.wrappedJSObject.accessCheck();
-      done();
-    }
-  );
-
-});
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-content-sync-worker.js
+++ /dev/null
@@ -1,962 +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";
-
-// Skipping due to window creation being unsupported in Fennec
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require("chrome");
-const { on } = require("sdk/event/core");
-const { setTimeout } = require("sdk/timers");
-const { LoaderWithHookedConsole } = require("sdk/test/loader");
-const { Worker } = require("sdk/deprecated/sync-worker");
-const { close } = require("sdk/window/helpers");
-const { set: setPref } = require("sdk/preferences/service");
-const { isArray } = require("sdk/lang/type");
-const { URL } = require('sdk/url');
-const fixtures = require("./fixtures");
-
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo";
-
-const WINDOW_SCRIPT_URL = "data:text/html;charset=utf-8," +
-                          "<script>window.addEventListener('message', function (e) {" +
-                          "  if (e.data === 'from -> content-script')" +
-                          "    window.postMessage('from -> window', '*');" +
-                          "});</script>";
-
-function makeWindow() {
-  let content =
-    "<?xml version=\"1.0\"?>" +
-    "<window " +
-    "xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">" +
-    "<script>var documentValue=true;</script>" +
-    "</window>";
-  var url = "data:application/vnd.mozilla.xul+xml;charset=utf-8," +
-            encodeURIComponent(content);
-  var features = ["chrome", "width=10", "height=10"];
-
-  return Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher).
-         openWindow(null, url, null, features.join(","), null);
-}
-
-// Listen for only first one occurence of DOM event
-function listenOnce(node, eventName, callback) {
-  node.addEventListener(eventName, function(event) {
-    callback(node);
-  }, {capture: true, once: true});
-}
-
-// Load a given url in a given browser and fires the callback when it is loaded
-function loadAndWait(browser, url, callback) {
-  listenOnce(browser, "load", callback);
-  // We have to wait before calling `loadURI` otherwise, if we call
-  // `loadAndWait` during browser load event, the history will be broken
-  setTimeout(function () {
-    browser.loadURI(url);
-  }, 0);
-}
-
-// Returns a test function that will automatically open a new chrome window
-// with a <browser> element loaded on a given content URL
-// The callback receive 3 arguments:
-// - test: reference to the jetpack test object
-// - browser: a reference to the <browser> xul node
-// - done: a callback to call when test is over
-function WorkerTest(url, callback) {
-  return function testFunction(assert, done) {
-    let chromeWindow = makeWindow();
-    chromeWindow.addEventListener("load", function() {
-      let browser = chromeWindow.document.createElement("browser");
-      browser.setAttribute("type", "content");
-      chromeWindow.document.documentElement.appendChild(browser);
-      // Wait for about:blank load event ...
-      listenOnce(browser, "load", function onAboutBlankLoad() {
-        // ... before loading the expected doc and waiting for its load event
-        loadAndWait(browser, url, function onDocumentLoaded() {
-          callback(assert, browser, function onTestDone() {
-
-            close(chromeWindow).then(done);
-          });
-        });
-      });
-    }, {capture: true, once: true});
-  };
-}
-
-exports["test:sample"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    assert.notEqual(browser.contentWindow.location.href, "about:blank",
-                        "window is now on the right document");
-
-    let window = browser.contentWindow
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        // window is accessible
-        let myLocation = window.location.toString();
-        self.on("message", function(data) {
-          if (data == "hi!")
-            self.postMessage("bye!");
-        });
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.equal("bye!", msg);
-        assert.equal(worker.url, window.location.href,
-                         "worker.url still works");
-        done();
-      }
-    });
-
-    assert.equal(worker.url, window.location.href,
-                     "worker.url works");
-    assert.equal(worker.contentURL, window.location.href,
-                     "worker.contentURL works");
-    worker.postMessage("hi!");
-  }
-);
-
-exports["test:emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (data) {
-            self.port.emit("content-to-addon", data);
-          });
-
-          // Check for global pollution
-          //if (typeof on != "undefined")
-          //  self.postMessage("`on` is in globals");
-          if (typeof once != "undefined")
-            self.postMessage("`once` is in globals");
-          if (typeof emit != "undefined")
-            self.postMessage("`emit` is in globals");
-
-        },
-        onMessage: function(msg) {
-          assert.fail("Got an unexpected message : "+msg);
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.port.emit("addon-to-content", "event data");
-  }
-);
-
-exports["test:emit hack message"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.port
-          self.port.on("message", function (data) {
-            self.port.emit("message", data);
-          });
-          // We should not receive message on self, but only on self.port
-          self.on("message", function (data) {
-            self.postMessage("message", data);
-          });
-        },
-        onError: function(e) {
-          assert.fail("Got exception: "+e);
-        }
-      });
-
-    worker.port.on("message", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.on("message", function (data) {
-      assert.fail("Got an unexpected message : "+msg);
-    });
-    worker.port.emit("message", "event data");
-  }
-);
-
-exports["test:n-arguments emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let repeat = 0;
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (a1, a2, a3) {
-            self.port.emit("content-to-addon", a1, a2, a3);
-          });
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (arg1, arg2, arg3) {
-      if (!repeat++) {
-        this.emit("addon-to-content", "first argument", "second", "third");
-      } else {
-        assert.equal(arg1, "first argument");
-        assert.equal(arg2, "second");
-        assert.equal(arg3, "third");
-        done();
-      }
-    });
-    worker.port.emit("addon-to-content", "first argument", "second", "third");
-  }
-);
-
-exports["test:post-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          self.on("message", function (message) {
-            self.postMessage([ message.fun === undefined,
-                               typeof message.w,
-                               message.w && "port" in message.w,
-                               message.w._url,
-                               Array.isArray(message.array),
-                               JSON.stringify(message.array)]);
-          });
-        }
-      });
-
-    // Validate worker.onMessage
-    let array = [1, 2, 3];
-    worker.on("message", function (message) {
-      assert.ok(message[0], "function becomes undefined");
-      assert.equal(message[1], "object", "object stays object");
-      assert.ok(message[2], "object's attributes are enumerable");
-      assert.equal(message[3], DEFAULT_CONTENT_URL,
-                       "jsonable attributes are accessible");
-      // See bug 714891, Arrays may be broken over compartements:
-      assert.ok(message[4], "Array keeps being an array");
-      assert.equal(message[5], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-
-    worker.postMessage({ fun: function () {}, w: worker, array: array });
-  }
-);
-
-exports["test:emit-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (fun, w, obj, array) {
-            self.port.emit("content-to-addon", [
-                            fun === null,
-                            typeof w,
-                            "port" in w,
-                            w._url,
-                            "fun" in obj,
-                            Object.keys(obj.dom).length,
-                            Array.isArray(array),
-                            JSON.stringify(array)
-                          ]);
-          });
-        }
-      });
-
-    // Validate worker.port
-    let array = [1, 2, 3];
-    worker.port.on("content-to-addon", function (result) {
-      assert.ok(result[0], "functions become null");
-      assert.equal(result[1], "object", "objects stay objects");
-      assert.ok(result[2], "object's attributes are enumerable");
-      assert.equal(result[3], DEFAULT_CONTENT_URL,
-                       "json attribute is accessible");
-      assert.ok(!result[4], "function as object attribute is removed");
-      assert.equal(result[5], 0, "DOM nodes are converted into empty object");
-      // See bug 714891, Arrays may be broken over compartments:
-      assert.ok(result[6], "Array keeps being an array");
-      assert.equal(result[7], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-
-    let obj = {
-      fun: function () {},
-      dom: browser.contentWindow.document.createElement("div")
-    };
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-    worker.port.emit("addon-to-content", function () {}, worker, obj, array);
-  }
-);
-
-exports["test:content is wrapped"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(!window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has a wrapped access to content document");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:chrome is unwrapped"] = function(assert, done) {
-  let window = makeWindow();
-
-  listenOnce(window, "load", function onload() {
-
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has an unwrapped access to chrome document");
-        close(window).then(done);
-      }
-    });
-
-  });
-}
-
-exports["test:nothing is leaked to content script"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage([
-          "ContentWorker" in window,
-          "UNWRAP_ACCESS_KEY" in window,
-          "getProxyForObject" in window
-        ]);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(list) {
-        assert.ok(!list[0], "worker API constructor isn't leaked");
-        assert.ok(!list[1], "Proxy API stuff isn't leaked 1/2");
-        assert.ok(!list[2], "Proxy API stuff isn't leaked 2/2");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:ensure console.xxx works in cs"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let { loader } = LoaderWithHookedConsole(module, onMessage);
-
-    // Intercept all console method calls
-    let calls = [];
-    function onMessage(type, msg) {
-      assert.equal(type, msg,
-        "console.xxx(\"xxx\"), i.e. message is equal to the " +
-        "console method name we are calling");
-      calls.push(msg);
-    }
-
-    // Finally, create a worker that will call all console methods
-    let worker =  loader.require("sdk/deprecated/sync-worker").Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.time("time");
-        console.log("log");
-        console.info("info");
-        console.warn("warn");
-        console.error("error");
-        console.debug("debug");
-        console.exception("exception");
-        console.timeEnd("timeEnd");
-        self.postMessage();
-      },
-      onMessage: function() {
-        // Ensure that console methods are called in the same execution order
-        const EXPECTED_CALLS = ["time", "log", "info", "warn", "error",
-          "debug", "exception", "timeEnd"];
-        assert.equal(JSON.stringify(calls),
-          JSON.stringify(EXPECTED_CALLS),
-          "console methods have been called successfully, in expected order");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout works with string argument"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var docVal=5;</script>",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function ContentScriptScope() {
-        // must use "window.scVal" instead of "var csVal"
-        // since we are inside ContentScriptScope function.
-        // i'm NOT putting code-in-string inside code-in-string </YO DAWG>
-        window.csVal = 13;
-        setTimeout("self.postMessage([" +
-                      "csVal, " +
-                      "window.docVal, " +
-                      "'ContentWorker' in window, " +
-                      "'UNWRAP_ACCESS_KEY' in window, " +
-                      "'getProxyForObject' in window, " +
-                    "])", 1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function([csVal, docVal, chrome1, chrome2, chrome3]) {
-        // test timer code is executed in the correct context
-        assert.equal(csVal, 13, "accessing content-script values");
-        assert.notEqual(docVal, 5, "can't access document values (directly)");
-        assert.ok(!chrome1 && !chrome2 && !chrome3, "nothing is leaked from chrome");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval works with string argument"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval('self.postMessage(1)', 50)",
-      contentScriptWhen: "ready",
-      onMessage: function(one) {
-        count++;
-        assert.equal(one, 1, "got " + count + " message(s) from setInterval");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval(() => { throw Error('ubik') }, 50)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        count++;
-        assert.equal(err.message, "ubik",
-            "error (correctly) propagated  " + count + " time(s)");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout throws array, passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout(function() { throw ['array', 42] }, 1)",
-      contentScriptWhen: "ready",
-      onError: function(arr) {
-        assert.ok(isArray(arr),
-            "the type of thrown/propagated object is array");
-        assert.ok(arr.length==2,
-            "the propagated thrown array is the right length");
-        assert.equal(arr[1], 42,
-            "element inside the thrown array correctly propagated");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout string arg with SyntaxError to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout('syntax 123 error', 1)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        assert.equal(err.name, "SyntaxError",
-            "received SyntaxError thrown from bad code in string argument to setTimeout");
-        assert.ok('fileName' in err,
-            "propagated SyntaxError contains a fileName property");
-        assert.ok('stack' in err,
-            "propagated SyntaxError contains a stack property");
-        assert.equal(err.message, "missing ; before statement",
-            "propagated SyntaxError has the correct (helpful) message");
-        assert.equal(err.lineNumber, 1,
-            "propagated SyntaxError was thrown on the right lineNumber");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout can't be cancelled by content"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setTimeout(function () {
-          self.postMessage("timeout");
-        }, 100);
-        unsafeWindow.eval("clearTimeout("+id+");");
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content didn't managed to cancel our setTimeout");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:clearTimeout"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id1 = setTimeout(function() {
-          self.postMessage("failed");
-        }, 10);
-        let id2 = setTimeout(function() {
-          self.postMessage("done");
-        }, 100);
-        clearTimeout(id1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "failed") {
-          assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("timer cancelled");
-          done();
-        }
-      }
-    });
-  }
-);
-
-exports["test:clearInterval"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let called = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setInterval(function() {
-          self.postMessage("intreval")
-          clearInterval(id)
-          setTimeout(function() {
-            self.postMessage("done")
-          }, 100)
-        }, 10);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "intreval") {
-          called = called + 1;
-          if (called > 1) assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("interval cancelled");
-          done();
-        }
-      }
-    });
-  }
-)
-
-exports["test:setTimeout are unregistered on content unload"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let originalWindow = browser.contentWindow;
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        document.title = "ok";
-        let i = 0;
-        setInterval(function () {
-          document.title = i++;
-        }, 10);
-      },
-      contentScriptWhen: "ready"
-    });
-
-    // Change location so that content script is destroyed,
-    // and all setTimeout/setInterval should be unregistered.
-    // Wait some cycles in order to execute some intervals.
-    setTimeout(function () {
-      // Bug 689621: Wait for the new document load so that we are sure that
-      // previous document cancelled its intervals
-      let url2 = "data:text/html;charset=utf-8,<title>final</title>";
-      loadAndWait(browser, url2, function onload() {
-        let titleAfterLoad = originalWindow.document.title;
-        // Wait additional cycles to verify that intervals are really cancelled
-        setTimeout(function () {
-          assert.equal(browser.contentDocument.title, "final",
-                           "New document has not been modified");
-          assert.equal(originalWindow.document.title, titleAfterLoad,
-                           "Nor previous one");
-
-          done();
-        }, 100);
-      });
-    }, 100);
-  }
-);
-
-exports['test:check window attribute in iframes'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    // Create a first iframe and wait for its loading
-    let contentWin = browser.contentWindow;
-    let contentDoc = contentWin.document;
-    let iframe = contentDoc.createElement("iframe");
-    contentDoc.body.appendChild(iframe);
-
-    listenOnce(iframe, "load", function onload() {
-
-      // Create a second iframe inside the first one and wait for its loading
-      let iframeDoc = iframe.contentWindow.document;
-      let subIframe = iframeDoc.createElement("iframe");
-      iframeDoc.body.appendChild(subIframe);
-
-      listenOnce(subIframe, "load", function onload() {
-        subIframe.removeEventListener("load", onload, true);
-
-        // And finally create a worker against this second iframe
-        let worker =  Worker({
-          window: subIframe.contentWindow,
-          contentScript: 'new ' + function WorkerScope() {
-            self.postMessage([
-              window.top !== window,
-              frameElement,
-              window.parent !== window,
-              top.location.href,
-              parent.location.href,
-            ]);
-          },
-          onMessage: function(msg) {
-            assert.ok(msg[0], "window.top != window");
-            assert.ok(msg[1], "window.frameElement is defined");
-            assert.ok(msg[2], "window.parent != window");
-            assert.equal(msg[3], contentWin.location.href,
-                             "top.location refers to the toplevel content doc");
-            assert.equal(msg[4], iframe.contentWindow.location.href,
-                             "parent.location refers to the first iframe doc");
-            done();
-          }
-        });
-
-      });
-      subIframe.setAttribute("src", "data:text/html;charset=utf-8,bar");
-
-    });
-    iframe.setAttribute("src", "data:text/html;charset=utf-8,foo");
-  }
-);
-
-exports['test:check window attribute in toplevel documents'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage([
-          window.top === window,
-          frameElement,
-          window.parent === window
-        ]);
-      },
-      onMessage: function(msg) {
-        assert.ok(msg[0], "window.top == window");
-        assert.ok(!msg[1], "window.frameElement is null");
-        assert.ok(msg[2], "window.parent == window");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:check worker API with page history"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let url2 = "data:text/html;charset=utf-8,bar";
-
-    loadAndWait(browser, url2, function () {
-      let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Just before the content script is disable, we register a timeout
-          // that will be disable until the page gets visible again
-          self.on("pagehide", function () {
-            setTimeout(function () {
-              self.postMessage("timeout restored");
-            }, 0);
-          });
-        },
-        contentScriptWhen: "start"
-      });
-
-      // postMessage works correctly when the page is visible
-      worker.postMessage("ok");
-
-      // We have to wait before going back into history,
-      // otherwise `goBack` won't do anything.
-      setTimeout(function () {
-        browser.goBack();
-      }, 0);
-
-      // Wait for the document to be hidden
-      browser.addEventListener("pagehide", function() {
-        // Now any event sent to this worker should throw
-
-        assert.throws(
-            function () { worker.postMessage("data"); },
-            /The page is currently hidden and can no longer be used/,
-            "postMessage should throw when the page is hidden in history"
-            );
-
-        assert.throws(
-            function () { worker.port.emit("event"); },
-            /The page is currently hidden and can no longer be used/,
-            "port.emit should throw when the page is hidden in history"
-            );
-
-        // Display the page with attached content script back in order to resume
-        // its timeout and receive the expected message.
-        // We have to delay this in order to not break the history.
-        // We delay for a non-zero amount of time in order to ensure that we
-        // do not receive the message immediatly, so that the timeout is
-        // actually disabled
-        setTimeout(function () {
-          worker.on("message", function (data) {
-            assert.ok(data, "timeout restored");
-            done();
-          });
-          browser.goForward();
-        }, 500);
-
-      }, {once: true});
-    });
-
-  }
-);
-
-exports['test:conentScriptFile as URL instance'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let url = new URL(fixtures.url("test-contentScriptFile.js"));
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScriptFile: url,
-      onMessage: function(msg) {
-        assert.equal(msg, "msg from contentScriptFile",
-            "received a wrong message from contentScriptFile");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:worker events"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function (assert, browser, done) {
-    let window = browser.contentWindow;
-    let events = [];
-    let worker = Worker({
-      window: window,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage('start');
-      },
-      onAttach: win => {
-        events.push('attach');
-        assert.pass('attach event called when attached');
-        assert.equal(window, win, 'attach event passes in attached window');
-      },
-      onError: err => {
-        assert.equal(err.message, 'Custom',
-          'Error passed into error event');
-        worker.detach();
-      },
-      onMessage: msg => {
-        assert.pass('`onMessage` handles postMessage')
-        throw new Error('Custom');
-      },
-      onDetach: _ => {
-        assert.pass('`onDetach` called when worker detached');
-        done();
-      }
-    });
-    // `attach` event is called synchronously during instantiation,
-    // so we can't listen to that, TODO FIX?
-    //  worker.on('attach', obj => console.log('attach', obj));
-  }
-);
-
-exports["test:onDetach in contentScript on destroy"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-    });
-    browser.contentWindow.addEventListener('hashchange', _ => {
-      assert.equal(browser.contentWindow.location.hash, '#detach!',
-                   "location.href is as expected");
-      done();
-    })
-    worker.destroy();
-  }
-);
-
-exports["test:onDetach in contentScript on unload"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker = loader.require("sdk/deprecated/sync-worker").Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-    });
-    browser.contentWindow.addEventListener('hashchange', _ => {
-      assert.equal(browser.contentWindow.location.hash, '#detach!shutdown',
-                   "location.href is as expected");
-      done();
-    })
-    loader.unload('shutdown');
-  }
-);
-
-exports["test:console method log functions properly"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let logs = [];
-
-    let clean = message =>
-          message.trim().
-          replace(/[\r\n]/g, " ").
-          replace(/ +/g, " ");
-
-    let onMessage = (type, message) => logs.push(clean(message));
-    let { loader } = LoaderWithHookedConsole(module, onMessage);
-
-    let worker =  loader.require("sdk/deprecated/sync-worker").Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.log(Function);
-        console.log((foo) => foo * foo);
-        console.log(function foo(bar) { return bar + bar });
-
-        self.postMessage();
-      },
-      onMessage: () => {
-        assert.deepEqual(logs, [
-          "function Function() { [native code] }",
-          "(foo) => foo * foo",
-          "function foo(bar) { return bar + bar }"
-        ]);
-
-        done();
-      }
-    });
-  }
-);
-
-exports["test:global postMessage"] = WorkerTest(
-  WINDOW_SCRIPT_URL,
-  function(assert, browser, done) {
-    let contentScript = "window.addEventListener('message', function (e) {" +
-                        "  if (e.data === 'from -> window')" +
-                        "    self.port.emit('response', e.data, e.origin);" +
-                        "});" +
-                        "postMessage('from -> content-script', '*');";
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker =  loader.require("sdk/deprecated/sync-worker").Worker({
-      window: browser.contentWindow,
-      contentScriptWhen: "ready",
-      contentScript: contentScript
-    });
-
-    worker.port.on("response", (data, origin) => {
-      assert.equal(data, "from -> window", "Communication from content-script to window completed");
-      done();
-    });
-});
-
-exports["test:destroy unbinds listeners from port"] = WorkerTest(
-  "data:text/html;charset=utf-8,portdestroyer",
-  function(assert, browser, done) {
-    let destroyed = false;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.emit("destroy");
-        setInterval(self.port.emit, 10, "ping");
-      },
-      onDestroy: done
-    });
-    worker.port.on("ping", () => {
-      if (destroyed) {
-        assert.fail("Should not call events on port after destroy.");
-      }
-    });
-    worker.port.on("destroy", () => {
-      destroyed = true;
-      worker.destroy();
-      assert.pass("Worker destroyed, waiting for no future listeners handling events.");
-      setTimeout(done, 500);
-    });
-  }
-);
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-content-worker.js
+++ /dev/null
@@ -1,1126 +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";
-
-// Skipping due to window creation being unsupported in Fennec
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require("chrome");
-const { on } = require("sdk/event/core");
-const { setTimeout } = require("sdk/timers");
-const { LoaderWithHookedConsole, Loader } = require("sdk/test/loader");
-const { Worker } = require("sdk/content/worker");
-const { close } = require("sdk/window/helpers");
-const { set: setPref } = require("sdk/preferences/service");
-const { isArray } = require("sdk/lang/type");
-const { URL } = require('sdk/url');
-const fixtures = require("./fixtures");
-const system = require("sdk/system/events");
-
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo";
-
-const WINDOW_SCRIPT_URL = "data:text/html;charset=utf-8," +
-                          "<script>window.addEventListener('message', function (e) {" +
-                          "  if (e.data === 'from -> content-script')" +
-                          "    window.postMessage('from -> window', '*');" +
-                          "});</script>";
-
-function makeWindow() {
-  let content =
-    "<?xml version=\"1.0\"?>" +
-    "<window " +
-    "xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">" +
-    "<script>var documentValue=true;</script>" +
-    "</window>";
-  var url = "data:application/vnd.mozilla.xul+xml;charset=utf-8," +
-            encodeURIComponent(content);
-  var features = ["chrome", "width=10", "height=10"];
-
-  return Cc["@mozilla.org/embedcomp/window-watcher;1"].
-         getService(Ci.nsIWindowWatcher).
-         openWindow(null, url, null, features.join(","), null);
-}
-
-// Listen for only first one occurence of DOM event
-function listenOnce(node, eventName, callback) {
-  node.addEventListener(eventName, function(event) {
-    callback(node);
-  }, {capture: true, once: true});
-}
-
-// Load a given url in a given browser and fires the callback when it is loaded
-function loadAndWait(browser, url, callback) {
-  listenOnce(browser, "load", callback);
-  // We have to wait before calling `loadURI` otherwise, if we call
-  // `loadAndWait` during browser load event, the history will be broken
-  setTimeout(function () {
-    browser.loadURI(url);
-  }, 0);
-}
-
-// Returns a test function that will automatically open a new chrome window
-// with a <browser> element loaded on a given content URL
-// The callback receive 3 arguments:
-// - test: reference to the jetpack test object
-// - browser: a reference to the <browser> xul node
-// - done: a callback to call when test is over
-function WorkerTest(url, callback) {
-  return function testFunction(assert, done) {
-    let chromeWindow = makeWindow();
-    chromeWindow.addEventListener("load", function() {
-      let browser = chromeWindow.document.createElement("browser");
-      browser.setAttribute("type", "content");
-      chromeWindow.document.documentElement.appendChild(browser);
-      // Wait for about:blank load event ...
-      listenOnce(browser, "load", function onAboutBlankLoad() {
-        // ... before loading the expected doc and waiting for its load event
-        loadAndWait(browser, url, function onDocumentLoaded() {
-          callback(assert, browser, function onTestDone() {
-
-            close(chromeWindow).then(done);
-          });
-        });
-      });
-    }, {capture: true, once: true});
-  };
-}
-
-exports["test:sample"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    assert.notEqual(browser.contentWindow.location.href, "about:blank",
-                        "window is now on the right document");
-
-    let window = browser.contentWindow
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        // window is accessible
-        let myLocation = window.location.toString();
-        self.on("message", function(data) {
-          if (data == "hi!")
-            self.postMessage("bye!");
-        });
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.equal("bye!", msg);
-        assert.equal(worker.url, window.location.href,
-                         "worker.url still works");
-        done();
-      },
-      onAttach: function() {
-        assert.equal(worker.url, window.location.href,
-                         "worker.url works");
-        assert.equal(worker.contentURL, window.location.href,
-                         "worker.contentURL works");
-        worker.postMessage("hi!");
-      }
-    });
-  }
-);
-
-exports["test:emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (data) {
-            self.port.emit("content-to-addon", data);
-          });
-
-          // Check for global pollution
-          //if (typeof on != "undefined")
-          //  self.postMessage("`on` is in globals");
-          if (typeof once != "undefined")
-            self.postMessage("`once` is in globals");
-          if (typeof emit != "undefined")
-            self.postMessage("`emit` is in globals");
-
-        },
-        onMessage: function(msg) {
-          assert.fail("Got an unexpected message : "+msg);
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.port.emit("addon-to-content", "event data");
-  }
-);
-
-exports["test:emit hack message"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.port
-          self.port.on("message", function (data) {
-            self.port.emit("message", data);
-          });
-          // We should not receive message on self, but only on self.port
-          self.on("message", function (data) {
-            self.postMessage("message", data);
-          });
-        },
-        onError: function(e) {
-          assert.fail("Got exception: "+e);
-        }
-      });
-
-    worker.port.on("message", function (data) {
-      assert.equal(data, "event data");
-      done();
-    });
-    worker.on("message", function (data) {
-      assert.fail("Got an unexpected message : "+msg);
-    });
-    worker.port.emit("message", "event data");
-  }
-);
-
-exports["test:n-arguments emit"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let repeat = 0;
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (a1, a2, a3) {
-            self.port.emit("content-to-addon", a1, a2, a3);
-          });
-        }
-      });
-
-    // Validate worker.port
-    worker.port.on("content-to-addon", function (arg1, arg2, arg3) {
-      if (!repeat++) {
-        this.emit("addon-to-content", "first argument", "second", "third");
-      } else {
-        assert.equal(arg1, "first argument");
-        assert.equal(arg2, "second");
-        assert.equal(arg3, "third");
-        done();
-      }
-    });
-    worker.port.emit("addon-to-content", "first argument", "second", "third");
-  }
-);
-
-exports["test:post-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          self.on("message", function (message) {
-            self.postMessage([ message.fun === undefined,
-                               typeof message.w,
-                               message.w && "port" in message.w,
-                               message.w._url,
-                               Array.isArray(message.array),
-                               JSON.stringify(message.array)]);
-          });
-        }
-      });
-
-    // Validate worker.onMessage
-    let array = [1, 2, 3];
-    worker.on("message", function (message) {
-      assert.ok(message[0], "function becomes undefined");
-      assert.equal(message[1], "object", "object stays object");
-      assert.ok(message[2], "object's attributes are enumerable");
-      assert.equal(message[3], DEFAULT_CONTENT_URL,
-                       "jsonable attributes are accessible");
-      // See bug 714891, Arrays may be broken over compartements:
-      assert.ok(message[4], "Array keeps being an array");
-      assert.equal(message[5], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-
-    worker.postMessage({ fun: function () {}, w: worker, array: array });
-  }
-);
-
-exports["test:emit-json-values-only"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Validate self.on and self.emit
-          self.port.on("addon-to-content", function (fun, w, obj, array) {
-            self.port.emit("content-to-addon", [
-                            fun === null,
-                            typeof w,
-                            "port" in w,
-                            w._url,
-                            "fun" in obj,
-                            Object.keys(obj.dom).length,
-                            Array.isArray(array),
-                            JSON.stringify(array)
-                          ]);
-          });
-        }
-      });
-
-    // Validate worker.port
-    let array = [1, 2, 3];
-    worker.port.on("content-to-addon", function (result) {
-      assert.ok(result[0], "functions become null");
-      assert.equal(result[1], "object", "objects stay objects");
-      assert.ok(result[2], "object's attributes are enumerable");
-      assert.equal(result[3], DEFAULT_CONTENT_URL,
-                       "json attribute is accessible");
-      assert.ok(!result[4], "function as object attribute is removed");
-      assert.equal(result[5], 0, "DOM nodes are converted into empty object");
-      // See bug 714891, Arrays may be broken over compartments:
-      assert.ok(result[6], "Array keeps being an array");
-      assert.equal(result[7], JSON.stringify(array),
-                       "Array is correctly serialized");
-      done();
-    });
-
-    let obj = {
-      fun: function () {},
-      dom: browser.contentWindow.document.createElement("div")
-    };
-    // Add a new url property sa the Class function used by
-    // Worker doesn't set enumerables to true for non-functions
-    worker._url = DEFAULT_CONTENT_URL;
-    worker.port.emit("addon-to-content", function () {}, worker, obj, array);
-  }
-);
-
-exports["test:content is wrapped"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(!window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has a wrapped access to content document");
-        done();
-      }
-    });
-  }
-);
-
-// ContentWorker is not for chrome
-/*
-exports["test:chrome is unwrapped"] = function(assert, done) {
-  let window = makeWindow();
-
-  listenOnce(window, "load", function onload() {
-
-    let worker =  Worker({
-      window: window,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage(window.documentValue);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content script has an unwrapped access to chrome document");
-        close(window).then(done);
-      }
-    });
-
-  });
-}
-*/
-
-exports["test:nothing is leaked to content script"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.postMessage([
-          "ContentWorker" in window,
-          "UNWRAP_ACCESS_KEY" in window,
-          "getProxyForObject" in window
-        ]);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(list) {
-        assert.ok(!list[0], "worker API contrustor isn't leaked");
-        assert.ok(!list[1], "Proxy API stuff isn't leaked 1/2");
-        assert.ok(!list[2], "Proxy API stuff isn't leaked 2/2");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:ensure console.xxx works in cs"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    const EXPECTED = ["time", "log", "info", "warn", "error", "error", "timeEnd"];
-
-    let calls = [];
-    let levels = [];
-
-    system.on('console-api-log-event', onMessage);
-
-    function onMessage({ subject }) {
-      calls.push(subject.wrappedJSObject.arguments[0]);
-      levels.push(subject.wrappedJSObject.level);
-    }
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.time("time");
-        console.log("log");
-        console.info("info");
-        console.warn("warn");
-        console.error("error");
-        console.debug("debug");
-        console.exception("error");
-        console.timeEnd("timeEnd");
-        self.postMessage();
-      },
-      onMessage: function() {
-        system.off('console-api-log-event', onMessage);
-
-        assert.equal(JSON.stringify(calls),
-          JSON.stringify(EXPECTED),
-          "console methods have been called successfully, in expected order");
-
-        assert.equal(JSON.stringify(levels),
-          JSON.stringify(EXPECTED),
-          "console messages have correct log levels, in expected order");
-
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout works with string argument"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var docVal=5;</script>",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function ContentScriptScope() {
-        // must use "window.scVal" instead of "var csVal"
-        // since we are inside ContentScriptScope function.
-        // i'm NOT putting code-in-string inside code-in-string </YO DAWG>
-        window.csVal = 13;
-        setTimeout("self.postMessage([" +
-                      "csVal, " +
-                      "window.docVal, " +
-                      "'ContentWorker' in window, " +
-                      "'UNWRAP_ACCESS_KEY' in window, " +
-                      "'getProxyForObject' in window, " +
-                    "])", 1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function([csVal, docVal, chrome1, chrome2, chrome3]) {
-        // test timer code is executed in the correct context
-        assert.equal(csVal, 13, "accessing content-script values");
-        assert.notEqual(docVal, 5, "can't access document values (directly)");
-        assert.ok(!chrome1 && !chrome2 && !chrome3, "nothing is leaked from chrome");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval works with string argument"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval('self.postMessage(1)', 50)",
-      contentScriptWhen: "ready",
-      onMessage: function(one) {
-        count++;
-        assert.equal(one, 1, "got " + count + " message(s) from setInterval");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let count = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setInterval(() => { throw Error('ubik') }, 50)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        count++;
-        assert.equal(err.message, "ubik",
-            "error (correctly) propagated  " + count + " time(s)");
-        if (count >= 3) done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout throws array, passed to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout(function() { throw ['array', 42] }, 1)",
-      contentScriptWhen: "ready",
-      onError: function(arr) {
-        assert.ok(isArray(arr),
-            "the type of thrown/propagated object is array");
-        assert.ok(arr.length==2,
-            "the propagated thrown array is the right length");
-        assert.equal(arr[1], 42,
-            "element inside the thrown array correctly propagated");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout string arg with SyntaxError to .onError"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "setTimeout('syntax 123 error', 1)",
-      contentScriptWhen: "ready",
-      onError: function(err) {
-        assert.equal(err.name, "SyntaxError",
-            "received SyntaxError thrown from bad code in string argument to setTimeout");
-        assert.ok('fileName' in err,
-            "propagated SyntaxError contains a fileName property");
-        assert.ok('stack' in err,
-            "propagated SyntaxError contains a stack property");
-        assert.equal(err.message, "missing ; before statement",
-            "propagated SyntaxError has the correct (helpful) message");
-        assert.equal(err.lineNumber, 1,
-            "propagated SyntaxError was thrown on the right lineNumber");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:setTimeout can't be cancelled by content"] = WorkerTest(
-  "data:text/html;charset=utf-8,<script>var documentValue=true;</script>",
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setTimeout(function () {
-          self.postMessage("timeout");
-        }, 100);
-        unsafeWindow.eval("clearTimeout("+id+");");
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        assert.ok(msg,
-          "content didn't managed to cancel our setTimeout");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:clearTimeout"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id1 = setTimeout(function() {
-          self.postMessage("failed");
-        }, 10);
-        let id2 = setTimeout(function() {
-          self.postMessage("done");
-        }, 100);
-        clearTimeout(id1);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "failed") {
-          assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("timer cancelled");
-          done();
-        }
-      }
-    });
-  }
-);
-
-exports["test:clearInterval"] = WorkerTest(
-  "data:text/html;charset=utf-8,clear timeout",
-  function(assert, browser, done) {
-    let called = 0;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        let id = setInterval(function() {
-          self.postMessage("intreval")
-          clearInterval(id)
-          setTimeout(function() {
-            self.postMessage("done")
-          }, 100)
-        }, 10);
-      },
-      contentScriptWhen: "ready",
-      onMessage: function(msg) {
-        if (msg === "intreval") {
-          called = called + 1;
-          if (called > 1) assert.fail("failed to cancel timer");
-        } else {
-          assert.pass("interval cancelled");
-          done();
-        }
-      }
-    });
-  }
-)
-
-exports["test:setTimeout are unregistered on content unload"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let originalWindow = browser.contentWindow;
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        document.title = "ok";
-        let i = 0;
-        setInterval(function () {
-          document.title = i++;
-        }, 10);
-      },
-      contentScriptWhen: "ready"
-    });
-
-    // Change location so that content script is destroyed,
-    // and all setTimeout/setInterval should be unregistered.
-    // Wait some cycles in order to execute some intervals.
-    setTimeout(function () {
-      // Bug 689621: Wait for the new document load so that we are sure that
-      // previous document cancelled its intervals
-      let url2 = "data:text/html;charset=utf-8,<title>final</title>";
-      loadAndWait(browser, url2, function onload() {
-        let titleAfterLoad = originalWindow.document.title;
-        // Wait additional cycles to verify that intervals are really cancelled
-        setTimeout(function () {
-          assert.equal(browser.contentDocument.title, "final",
-                           "New document has not been modified");
-          assert.equal(originalWindow.document.title, titleAfterLoad,
-                           "Nor previous one");
-
-          done();
-        }, 100);
-      });
-    }, 100);
-  }
-);
-
-exports['test:check window attribute in iframes'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    // Create a first iframe and wait for its loading
-    let contentWin = browser.contentWindow;
-    let contentDoc = contentWin.document;
-    let iframe = contentDoc.createElement("iframe");
-    contentDoc.body.appendChild(iframe);
-
-    listenOnce(iframe, "load", function onload() {
-
-      // Create a second iframe inside the first one and wait for its loading
-      let iframeDoc = iframe.contentWindow.document;
-      let subIframe = iframeDoc.createElement("iframe");
-      iframeDoc.body.appendChild(subIframe);
-
-      listenOnce(subIframe, "load", function onload() {
-        subIframe.removeEventListener("load", onload, true);
-
-        // And finally create a worker against this second iframe
-        let worker =  Worker({
-          window: subIframe.contentWindow,
-          contentScript: 'new ' + function WorkerScope() {
-            self.postMessage([
-              window.top !== window,
-              frameElement,
-              window.parent !== window,
-              top.location.href,
-              parent.location.href,
-            ]);
-          },
-          onMessage: function(msg) {
-            assert.ok(msg[0], "window.top != window");
-            assert.ok(msg[1], "window.frameElement is defined");
-            assert.ok(msg[2], "window.parent != window");
-            assert.equal(msg[3], contentWin.location.href,
-                             "top.location refers to the toplevel content doc");
-            assert.equal(msg[4], iframe.contentWindow.location.href,
-                             "parent.location refers to the first iframe doc");
-            done();
-          }
-        });
-
-      });
-      subIframe.setAttribute("src", "data:text/html;charset=utf-8,bar");
-
-    });
-    iframe.setAttribute("src", "data:text/html;charset=utf-8,foo");
-  }
-);
-
-exports['test:check window attribute in toplevel documents'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage([
-          window.top === window,
-          frameElement,
-          window.parent === window
-        ]);
-      },
-      onMessage: function(msg) {
-        assert.ok(msg[0], "window.top == window");
-        assert.ok(!msg[1], "window.frameElement is null");
-        assert.ok(msg[2], "window.parent == window");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:check worker API with page history"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let url2 = "data:text/html;charset=utf-8,bar";
-
-    loadAndWait(browser, url2, function () {
-      let worker =  Worker({
-        window: browser.contentWindow,
-        contentScript: "new " + function WorkerScope() {
-          // Just before the content script is disable, we register a timeout
-          // that will be disable until the page gets visible again
-          self.on("pagehide", function () {
-            setTimeout(function () {
-              self.port.emit("timeout");
-            }, 0);
-          });
-
-          self.on("message", function() {
-            self.postMessage("saw message");
-          });
-
-          self.on("event", function() {
-            self.port.emit("event", "saw event");
-          });
-        },
-        contentScriptWhen: "start"
-      });
-
-      // postMessage works correctly when the page is visible
-      worker.postMessage("ok");
-
-      // We have to wait before going back into history,
-      // otherwise `goBack` won't do anything.
-      setTimeout(function () {
-        browser.goBack();
-      }, 0);
-
-      // Wait for the document to be hidden
-      browser.addEventListener("pagehide", function() {
-        // Now any event sent to this worker should be cached
-
-        worker.postMessage("message");
-        worker.port.emit("event");
-
-        // Display the page with attached content script back in order to resume
-        // its timeout and receive the expected message.
-        // We have to delay this in order to not break the history.
-        // We delay for a non-zero amount of time in order to ensure that we
-        // do not receive the message immediatly, so that the timeout is
-        // actually disabled
-        setTimeout(function () {
-          worker.on("pageshow", function() {
-            let promise = Promise.all([
-              new Promise(resolve => {
-                worker.port.on("event", () => {
-                  assert.pass("Saw event");
-                  resolve();
-                });
-              }),
-              new Promise(resolve => {
-                worker.on("message", () => {
-                  assert.pass("Saw message");
-                  resolve();
-                });
-              }),
-              new Promise(resolve => {
-                worker.port.on("timeout", () => {
-                  assert.pass("Timer fired");
-                  resolve();
-                });
-              })
-            ]);
-            promise.then(done);
-          });
-
-          browser.goForward();
-        }, 500);
-
-      }, {once: true});
-    });
-
-  }
-);
-
-exports['test:conentScriptFile as URL instance'] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-
-    let url = new URL(fixtures.url("test-contentScriptFile.js"));
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScriptFile: url,
-      onMessage: function(msg) {
-        assert.equal(msg, "msg from contentScriptFile",
-            "received a wrong message from contentScriptFile");
-        done();
-      }
-    });
-  }
-);
-
-exports["test:worker events"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function (assert, browser, done) {
-    let window = browser.contentWindow;
-    let events = [];
-    let worker = Worker({
-      window: window,
-      contentScript: 'new ' + function WorkerScope() {
-        self.postMessage('start');
-      },
-      onAttach: () => {
-        events.push('attach');
-        assert.pass('attach event called when attached');
-      },
-      onError: err => {
-        assert.equal(err.message, 'Custom',
-          'Error passed into error event');
-        worker.detach();
-      },
-      onMessage: msg => {
-        assert.pass('`onMessage` handles postMessage')
-        throw new Error('Custom');
-      },
-      onDetach: _ => {
-        assert.pass('`onDetach` called when worker detached');
-        done();
-      }
-    });
-    // `attach` event is called synchronously during instantiation,
-    // so we can't listen to that, TODO FIX?
-    //  worker.on('attach', obj => console.log('attach', obj));
-  }
-);
-
-exports["test:onDetach in contentScript on destroy"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-
-      onAttach: function() {
-        browser.contentWindow.addEventListener('hashchange', _ => {
-          assert.equal(browser.contentWindow.location.hash, '#detach!',
-                       "location.href is as expected");
-          done();
-        })
-        worker.destroy();
-      }
-    });
-  }
-);
-
-exports["test:onDetach in contentScript on unload"] = WorkerTest(
-  "data:text/html;charset=utf-8,foo#detach",
-  function(assert, browser, done) {
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker = loader.require("sdk/content/worker").Worker({
-      window: browser.contentWindow,
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('detach', function(reason) {
-          window.location.hash += '!' + reason;
-        })
-      },
-    });
-    browser.contentWindow.addEventListener('hashchange', _ => {
-      assert.equal(browser.contentWindow.location.hash, '#detach!shutdown',
-                   "location.href is as expected");
-      done();
-    })
-    loader.unload('shutdown');
-  }
-);
-
-exports["test:console method log functions properly"] = WorkerTest(
-  DEFAULT_CONTENT_URL,
-  function(assert, browser, done) {
-    let logs = [];
-
-    system.on('console-api-log-event', onMessage);
-
-    function onMessage({ subject }) {
-      logs.push(clean(subject.wrappedJSObject.arguments[0]));
-    }
-
-    let clean = message =>
-          message.trim().
-          replace(/[\r\n]/g, " ").
-          replace(/ +/g, " ");
-
-    let worker =  Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        console.log(Function);
-        console.log((foo) => foo * foo);
-        console.log(function foo(bar) { return bar + bar });
-
-        self.postMessage();
-      },
-      onMessage: () => {
-        system.off('console-api-log-event', onMessage);
-
-        assert.deepEqual(logs, [
-          "function Function() { [native code] }",
-          "(foo) => foo * foo",
-          "function foo(bar) { return bar + bar }"
-        ]);
-
-        done();
-      }
-    });
-  }
-);
-
-exports["test:global postMessage"] = WorkerTest(
-  WINDOW_SCRIPT_URL,
-  function(assert, browser, done) {
-    let contentScript = "window.addEventListener('message', function (e) {" +
-                        "  if (e.data === 'from -> window')" +
-                        "    self.port.emit('response', e.data, e.origin);" +
-                        "});" +
-                        "postMessage('from -> content-script', '*');";
-    let { loader } = LoaderWithHookedConsole(module);
-    let worker =  loader.require("sdk/content/worker").Worker({
-      window: browser.contentWindow,
-      contentScriptWhen: "ready",
-      contentScript: contentScript
-    });
-
-    worker.port.on("response", (data, origin) => {
-      assert.equal(data, "from -> window", "Communication from content-script to window completed");
-      done();
-    });
-});
-
-exports["test:destroy unbinds listeners from port"] = WorkerTest(
-  "data:text/html;charset=utf-8,portdestroyer",
-  function(assert, browser, done) {
-    let destroyed = false;
-    let worker = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.emit("destroy");
-        setInterval(self.port.emit, 10, "ping");
-      },
-      onDestroy: done
-    });
-    worker.port.on("ping", () => {
-      if (destroyed) {
-        assert.fail("Should not call events on port after destroy.");
-      }
-    });
-    worker.port.on("destroy", () => {
-      destroyed = true;
-      worker.destroy();
-      assert.pass("Worker destroyed, waiting for no future listeners handling events.");
-      setTimeout(done, 500);
-    });
-  }
-);
-
-exports["test:destroy kills child worker"] = WorkerTest(
-  "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>",
-  function(assert, browser, done) {
-    let worker1 = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.on("ping", detail => {
-          let event = document.createEvent("CustomEvent");
-          event.initCustomEvent("Test:Ping", true, true, detail);
-          document.dispatchEvent(event);
-          self.port.emit("pingsent");
-        });
-
-        let listener = function(event) {
-          self.port.emit("pong", event.detail);
-        };
-
-        self.port.on("detach", () => {
-          window.removeEventListener("Test:Pong", listener);
-        });
-        window.addEventListener("Test:Pong", listener);
-      },
-      onAttach: function() {
-        let worker2 = Worker({
-          window: browser.contentWindow,
-          contentScript: "new " + function WorkerScope() {
-            let listener = function(event) {
-              let newEvent = document.createEvent("CustomEvent");
-              newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-              document.dispatchEvent(newEvent);
-            };
-            self.port.on("detach", () => {
-              window.removeEventListener("Test:Ping", listener);
-            })
-            window.addEventListener("Test:Ping", listener);
-            self.postMessage();
-          },
-          onMessage: function() {
-            worker1.port.emit("ping", "test1");
-            worker1.port.once("pong", detail => {
-              assert.equal(detail, "test1", "Saw the right message");
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-
-                worker2.destroy();
-
-                worker1.port.emit("ping", "test2");
-                worker1.port.once("pong", detail => {
-                  assert.fail("worker2 shouldn't have responded");
-                })
-                worker1.port.once("pingsent", () => {
-                  assert.pass("The message was sent");
-                  worker1.destroy();
-                  done();
-                });
-              });
-            })
-          }
-        });
-      }
-    });
-  }
-);
-
-exports["test:unload kills child worker"] = WorkerTest(
-  "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>",
-  function(assert, browser, done) {
-    let loader = Loader(module);
-    let worker1 = Worker({
-      window: browser.contentWindow,
-      contentScript: "new " + function WorkerScope() {
-        self.port.on("ping", detail => {
-          let event = document.createEvent("CustomEvent");
-          event.initCustomEvent("Test:Ping", true, true, detail);
-          document.dispatchEvent(event);
-          self.port.emit("pingsent");
-        });
-
-        let listener = function(event) {
-          self.port.emit("pong", event.detail);
-        };
-
-        self.port.on("detach", () => {
-          window.removeEventListener("Test:Pong", listener);
-        });
-        window.addEventListener("Test:Pong", listener);
-      },
-      onAttach: function() {
-        let worker2 = loader.require("sdk/content/worker").Worker({
-          window: browser.contentWindow,
-          contentScript: "new " + function WorkerScope() {
-            let listener = function(event) {
-              let newEvent = document.createEvent("CustomEvent");
-              newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-              document.dispatchEvent(newEvent);
-            };
-            self.port.on("detach", () => {
-              window.removeEventListener("Test:Ping", listener);
-            })
-            window.addEventListener("Test:Ping", listener);
-            self.postMessage();
-          },
-          onMessage: function() {
-            worker1.port.emit("ping", "test1");
-            worker1.port.once("pong", detail => {
-              assert.equal(detail, "test1", "Saw the right message");
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-
-                loader.unload();
-
-                worker1.port.emit("ping", "test2");
-                worker1.port.once("pong", detail => {
-                  assert.fail("worker2 shouldn't have responded");
-                })
-                worker1.port.once("pingsent", () => {
-                  assert.pass("The message was sent");
-                  worker1.destroy();
-                  done();
-                });
-              });
-            })
-          }
-        });
-      }
-    });
-  }
-);
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-context-menu.html
+++ /dev/null
@@ -1,98 +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 charset="UTF-8">
-    <title>Context menu test</title>
-    <style>
-      p { display: inline-block; }
-    </style>
-  </head>
-  <body>
-    <p>
-      <img id="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==">
-    </p>
-
-    <p>
-      <a id="link" href="">
-        A simple link.
-      </a>
-    </p>
-
-    <p>
-      <a href="">
-        <span id="span-link">
-          A span inside a link.
-        </span>
-      </a>
-    </p>
-
-    <p id="text">
-      Some text.
-    </p>
-
-    <p>
-      <textarea id="textfield">
-        A text field,
-        with some text.
-      </textarea>
-    </p>
-
-    <p>
-      <iframe id="iframe" src="data:text/html;charset=utf-8,<p id='text'>An iframe</p>."
-              width="200" height="100">
-      </iframe>
-    </p>
-
-    <p>
-      <a id="targetlink" target="_blank" href="">
-        A targetted link.
-      </a>
-    </p>
-
-    <p>
-      <input type="submit" id="button">
-    </p>
-
-    <p>
-      <a class="predicate-test-a" href="#test">
-        A link with no ID and an anchor, used by PredicateContext tests.
-      </a>
-    </p>
-
-    <p>
-      <a class="predicate-test-b" href="#nested-image">
-        <img id="predicate-test-nested-image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==">
-      </a>
-    </p>
-    <p>
-      <a class="predicate-test-c" href="#nested-structure">
-        <span>
-          <span>
-            <span id="predicate-test-nested-structure">
-              A complex nested structure.
-            </span>
-          </span>
-        </span>
-      </a>
-    </p>
-
-    <p>
-      <input type="text" id="textbox" value="test value">
-    </p>
-
-    <p>
-      <input type="text" id="readonly-textbox" readonly="true" value="readonly value">
-    </p>
-
-    <p>
-      <input type="text" id="disabled-textbox" disabled="true" value="disabled value">
-    </p>
-
-    <p>
-      <p contenteditable="true" id="editable">This content is editable.</p>
-    </p>
-  </body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/test/test-context-menu.js
+++ /dev/null
@@ -1,3763 +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';
-
-require("sdk/context-menu");
-
-const { defer } = require("sdk/core/promise");
-const { isTravisCI } = require("sdk/test/utils");
-const packaging = require('@loader/options');
-
-// These should match the same constants in the module.
-const OVERFLOW_THRESH_DEFAULT = 10;
-const OVERFLOW_THRESH_PREF =
-  "extensions.addon-sdk.context-menu.overflowThreshold";
-
-const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html");
-const data = require("./fixtures");
-
-const { TestHelper } = require("./context-menu/test-helper.js")
-
-// Tests that when present the separator is placed before the separator from
-// the old context-menu module
-exports.testSeparatorPosition = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  // Create the old separator
-  let oldSeparator = test.contextMenuPopup.ownerDocument.createElement("menuseparator");
-  oldSeparator.id = "jetpack-context-menu-separator";
-  test.contextMenuPopup.appendChild(oldSeparator);
-
-  // Create an item.
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-    assert.equal(test.contextMenuSeparator.nextSibling.nextSibling, oldSeparator,
-                     "New separator should appear before the old one");
-    test.contextMenuPopup.removeChild(oldSeparator);
-    test.done();
-  });
-};
-
-// Destroying items that were previously created should cause them to be absent
-// from the menu.
-exports.testConstructDestroy = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  // Create an item.
-  let item = new loader.cm.Item({ label: "item" });
-  assert.equal(item.parentMenu, loader.cm.contentContextMenu,
-                   "item's parent menu should be correct");
-
-  test.showMenu(null, function (popup) {
-
-    // It should be present when the menu is shown.
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    // Destroy the item.  Multiple destroys should be harmless.
-    item.destroy();
-    item.destroy();
-    test.showMenu(null, function (popup) {
-
-      // It should be removed from the menu.
-      test.checkMenu([item], [], [item]);
-      test.done();
-    });
-  });
-};
-
-
-// Destroying an item twice should not cause an error.
-exports.testDestroyTwice = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-  item.destroy();
-  item.destroy();
-
-  test.pass("Destroying an item twice should not cause an error.");
-  test.done();
-};
-
-
-// CSS selector contexts should cause their items to be present in the menu
-// when the menu is invoked on nodes that match the selectors.
-exports.testSelectorContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    data: "item",
-    context: loader.cm.SelectorContext("img")
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// CSS selector contexts should cause their items to be present in the menu
-// when the menu is invoked on nodes that have ancestors that match the
-// selectors.
-exports.testSelectorAncestorContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    data: "item",
-    context: loader.cm.SelectorContext("a[href]")
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#span-link", function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// CSS selector contexts should cause their items to be absent from the menu
-// when the menu is not invoked on nodes that match or have ancestors that
-// match the selectors.
-exports.testSelectorContextNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    data: "item",
-    context: loader.cm.SelectorContext("img")
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [item], []);
-    test.done();
-  });
-};
-
-
-// Page contexts should cause their items to be present in the menu when the
-// menu is not invoked on an active element.
-exports.testPageContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({
-      label: "item 0"
-    }),
-    new loader.cm.Item({
-      label: "item 1",
-      context: undefined
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.PageContext()
-    }),
-    new loader.cm.Item({
-      label: "item 3",
-      context: [loader.cm.PageContext()]
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Page contexts should cause their items to be absent from the menu when the
-// menu is invoked on an active element.
-exports.testPageContextNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({
-      label: "item 0"
-    }),
-    new loader.cm.Item({
-      label: "item 1",
-      context: undefined
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.PageContext()
-    }),
-    new loader.cm.Item({
-      label: "item 3",
-      context: [loader.cm.PageContext()]
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-
-// Selection contexts should cause items to appear when a selection exists.
-exports.testSelectionContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    window.getSelection().selectAllChildren(doc.body);
-    test.showMenu(null, function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Selection contexts should cause items to appear when a selection exists in
-// a text field.
-exports.testSelectionContextMatchInTextField = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.selectRange("#textfield", 0, null);
-    test.showMenu("#textfield", function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Selection contexts should not cause items to appear when a selection does
-// not exist in a text field.
-exports.testSelectionContextNoMatchInTextField = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.selectRange("#textfield", 0, 0);
-    test.showMenu("#textfield", function (popup) {
-      test.checkMenu([item], [item], []);
-      test.done();
-    });
-  });
-};
-
-
-// Selection contexts should not cause items to appear when a selection does
-// not exist.
-exports.testSelectionContextNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [item], []);
-    test.done();
-  });
-};
-
-
-// Selection contexts should cause items to appear when a selection exists even
-// for newly opened pages
-exports.testSelectionContextInNewTab = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    let link = doc.getElementById("targetlink");
-    link.click();
-
-    let tablistener = event => {
-      this.tabBrowser.tabContainer.removeEventListener("TabOpen", tablistener);
-      let tab = event.target;
-      let browser = tab.linkedBrowser;
-      this.loadFrameScript(browser);
-      this.delayedEventListener(browser, "load", () => {
-        let window = browser.contentWindow;
-        let doc = browser.contentDocument;
-        window.getSelection().selectAllChildren(doc.body);
-
-        test.showMenu(null, function (popup) {
-          test.checkMenu([item], [], []);
-          popup.hidePopup();
-
-          test.tabBrowser.removeTab(test.tabBrowser.selectedTab);
-          test.tabBrowser.selectedTab = test.tab;
-
-          test.showMenu(null, function (popup) {
-            test.checkMenu([item], [item], []);
-            test.done();
-          });
-        });
-      }, true);
-    };
-    this.tabBrowser.tabContainer.addEventListener("TabOpen", tablistener);
-  });
-};
-
-
-// Selection contexts should work when right clicking a form button
-exports.testSelectionContextButtonMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    window.getSelection().selectAllChildren(doc.body);
-    test.showMenu("#button", function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-//Selection contexts should work when right clicking a form button
-exports.testSelectionContextButtonNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "item",
-    context: loader.cm.SelectionContext()
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#button", function (popup) {
-      test.checkMenu([item], [item], []);
-      test.done();
-    });
-  });
-};
-
-
-// URL contexts should cause items to appear on pages that match.
-exports.testURLContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    loader.cm.Item({
-      label: "item 0",
-      context: loader.cm.URLContext(TEST_DOC_URL)
-    }),
-    loader.cm.Item({
-      label: "item 1",
-      context: loader.cm.URLContext([TEST_DOC_URL, "*.bogus.com"])
-    }),
-    loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.URLContext([new RegExp(".*\\.html")])
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// URL contexts should not cause items to appear on pages that do not match.
-exports.testURLContextNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    loader.cm.Item({
-      label: "item 0",
-      context: loader.cm.URLContext("*.bogus.com")
-    }),
-    loader.cm.Item({
-      label: "item 1",
-      context: loader.cm.URLContext(["*.bogus.com", "*.gnarly.com"])
-    }),
-    loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.URLContext([new RegExp(".*\\.js")])
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-
-// Loading a new page in the same tab should correctly start a new worker for
-// any content scripts
-exports.testPageReload = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({
-    label: "Item",
-    contentScript: "var doc = document; self.on('context', node => doc.body.getAttribute('showItem') == 'true');"
-  });
-
-  test.withTestDoc(function (window, doc) {
-    // Set a flag on the document that the item uses
-    doc.body.setAttribute("showItem", "true");
-
-    test.showMenu(null, function (popup) {
-      // With the attribute true the item should be visible in the menu
-      test.checkMenu([item], [], []);
-      test.hideMenu(function() {
-        let browser = this.tabBrowser.getBrowserForTab(this.tab)
-        test.delayedEventListener(browser, "load", function() {
-          test.delayedEventListener(browser, "load", function() {
-            window = browser.contentWindow;
-            doc = window.document;
-
-            // Set a flag on the document that the item uses
-            doc.body.setAttribute("showItem", "false");
-
-            test.showMenu(null, function (popup) {
-              // In the new document with the attribute false the item should be
-              // hidden, but if the contentScript hasn't been reloaded it will
-              // still see the old value
-              test.checkMenu([item], [item], []);
-
-              test.done();
-            });
-          }, true);
-          browser.loadURI(TEST_DOC_URL, null, null);
-        }, true);
-        // Required to make sure we load a new page in history rather than
-        // just reloading the current page which would unload it
-        browser.loadURI("about:blank", null, null);
-      });
-    });
-  });
-};
-
-// Closing a page after it's been used with a worker should cause the worker
-// to be destroyed
-/*exports.testWorkerDestroy = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let loadExpected = false;
-
-  let item = loader.cm.Item({
-    label: "item",
-    contentScript: 'self.postMessage("loaded"); self.on("detach", function () { console.log("saw detach"); self.postMessage("detach") });',
-    onMessage: function (msg) {
-      switch (msg) {
-      case "loaded":
-        assert.ok(loadExpected, "Should have seen the load event at the right time");
-        loadExpected = false;
-        break;
-      case "detach":
-        test.done();
-        break;
-      }
-    }
-  });
-
-  test.withTestDoc(function (window, doc) {
-    loadExpected = true;
-    test.showMenu(null, function (popup) {
-      assert.ok(!loadExpected, "Should have seen a message");
-
-      test.checkMenu([item], [], []);
-
-      test.closeTab();
-    });
-  });
-};*/
-
-
-// Content contexts that return true should cause their items to be present
-// in the menu.
-exports.testContentContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => true);'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    test.done();
-  });
-};
-
-
-// Content contexts that return false should cause their items to be absent
-// from the menu.
-exports.testContentContextNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => false);'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [item], []);
-    test.done();
-  });
-};
-
-
-// Content contexts that return undefined should cause their items to be absent
-// from the menu.
-exports.testContentContextUndefined = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", function () {});'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [item], []);
-    test.done();
-  });
-};
-
-
-// Content contexts that return an empty string should cause their items to be
-// absent from the menu and shouldn't wipe the label
-exports.testContentContextEmptyString = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => "");'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [item], []);
-    assert.equal(item.label, "item", "Label should still be correct");
-    test.done();
-  });
-};
-
-
-// If any content contexts returns true then their items should be present in
-// the menu.
-exports.testMultipleContentContextMatch1 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => true); ' +
-                   'self.on("context", () => false);',
-    onMessage: function() {
-      test.fail("Should not have called the second context listener");
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    test.done();
-  });
-};
-
-
-// If any content contexts returns true then their items should be present in
-// the menu.
-exports.testMultipleContentContextMatch2 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => false); ' +
-                   'self.on("context", () => true);'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    test.done();
-  });
-};
-
-
-// If any content contexts returns a string then their items should be present
-// in the menu.
-exports.testMultipleContentContextString1 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => "new label"); ' +
-                   'self.on("context", () => false);'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    assert.equal(item.label, "new label", "Label should have changed");
-    test.done();
-  });
-};
-
-
-// If any content contexts returns a string then their items should be present
-// in the menu.
-exports.testMultipleContentContextString2 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => false); ' +
-                   'self.on("context", () => "new label");'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    assert.equal(item.label, "new label", "Label should have changed");
-    test.done();
-  });
-};
-
-
-// If many content contexts returns a string then the first should take effect
-exports.testMultipleContentContextString3 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", () => "new label 1"); ' +
-                   'self.on("context", () => "new label 2");'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    assert.equal(item.label, "new label 1", "Label should have changed");
-    test.done();
-  });
-};
-
-
-// Content contexts that return true should cause their items to be present
-// in the menu when context clicking an active element.
-exports.testContentContextMatchActiveElement = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({
-      label: "item 1",
-      contentScript: 'self.on("context", () => true);'
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: undefined,
-      contentScript: 'self.on("context", () => true);'
-    }),
-    // These items will always be hidden by the declarative usage of PageContext
-    new loader.cm.Item({
-      label: "item 3",
-      context: loader.cm.PageContext(),
-      contentScript: 'self.on("context", () => true);'
-    }),
-    new loader.cm.Item({
-      label: "item 4",
-      context: [loader.cm.PageContext()],
-      contentScript: 'self.on("context", () => true);'
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, [items[2], items[3]], []);
-      test.done();
-    });
-  });
-};
-
-
-// Content contexts that return false should cause their items to be absent
-// from the menu when context clicking an active element.
-exports.testContentContextNoMatchActiveElement = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({
-      label: "item 1",
-      contentScript: 'self.on("context", () => false);'
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: undefined,
-      contentScript: 'self.on("context", () => false);'
-    }),
-    // These items will always be hidden by the declarative usage of PageContext
-    new loader.cm.Item({
-      label: "item 3",
-      context: loader.cm.PageContext(),
-      contentScript: 'self.on("context", () => false);'
-    }),
-    new loader.cm.Item({
-      label: "item 4",
-      context: [loader.cm.PageContext()],
-      contentScript: 'self.on("context", () => false);'
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-
-// Content contexts that return undefined should cause their items to be absent
-// from the menu when context clicking an active element.
-exports.testContentContextNoMatchActiveElement = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({
-      label: "item 1",
-      contentScript: 'self.on("context", () => {});'
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: undefined,
-      contentScript: 'self.on("context", () => {});'
-    }),
-    // These items will always be hidden by the declarative usage of PageContext
-    new loader.cm.Item({
-      label: "item 3",
-      context: loader.cm.PageContext(),
-      contentScript: 'self.on("context", () => {});'
-    }),
-    new loader.cm.Item({
-      label: "item 4",
-      context: [loader.cm.PageContext()],
-      contentScript: 'self.on("context", () => {});'
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-
-// Content contexts that return a string should cause their items to be present
-// in the menu and the items' labels to be updated.
-exports.testContentContextMatchString = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "first label",
-    contentScript: 'self.on("context", () => "second label");'
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    assert.equal(item.label, "second label",
-                     "item's label should be updated");
-    test.done();
-  });
-};
-
-
-// Ensure that contentScriptFile is working correctly
-exports.testContentScriptFile = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let { defer, all } = require("sdk/core/promise");
-  let itemScript = [defer(), defer()];
-  let menuShown = defer();
-  let menuPromises = itemScript.concat(menuShown).map(({promise}) => promise);
-
-  // Reject remote files
-  assert.throws(function() {
-      new loader.cm.Item({
-        label: "item",
-        contentScriptFile: "http://mozilla.com/context-menu.js"
-      });
-    },
-    /The `contentScriptFile` option must be a local URL or an array of URLs/,
-    "Item throws when contentScriptFile is a remote URL");
-
-  // But accept files from data folder
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScriptFile: data.url("test-contentScriptFile.js"),
-    onMessage: (message) => {
-      assert.equal(message, "msg from contentScriptFile",
-        "contentScriptFile loaded with absolute url");
-      itemScript[0].resolve();
-    }
-  });
-
-  let item2 = new loader.cm.Item({
-    label: "item2",
-    contentScriptFile: "./test-contentScriptFile.js",
-    onMessage: (message) => {
-      assert.equal(message, "msg from contentScriptFile",
-        "contentScriptFile loaded with relative url");
-      itemScript[1].resolve();
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item, item2], [], []);
-    menuShown.resolve();
-  });
-
-  all(menuPromises).then(() => test.done());
-};
-
-
-// The args passed to context listeners should be correct.
-exports.testContentContextArgs = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let callbacks = 0;
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'self.on("context", function (node) {' +
-                   '  self.postMessage(node.tagName);' +
-                   '  return false;' +
-                   '});',
-    onMessage: function (tagName) {
-      assert.equal(tagName, "HTML", "node should be an HTML element");
-      if (++callbacks == 2) test.done();
-    }
-  });
-
-  test.showMenu(null, function () {
-    if (++callbacks == 2) test.done();
-  });
-};
-
-// Multiple contexts imply intersection, not union.
-exports.testMultipleContexts = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    context: [loader.cm.SelectorContext("a[href]"), loader.cm.PageContext()],
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#span-link", function (popup) {
-      test.checkMenu([item], [item], []);
-      test.done();
-    });
-  });
-};
-
-// Once a context is removed, it should no longer cause its item to appear.
-exports.testRemoveContext = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let ctxt = loader.cm.SelectorContext("img");
-  let item = new loader.cm.Item({
-    label: "item",
-    context: ctxt
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-
-      // The item should be present at first.
-      test.checkMenu([item], [], []);
-      popup.hidePopup();
-
-      // Remove the img context and check again.
-      item.context.remove(ctxt);
-      test.showMenu("#image", function (popup) {
-        test.checkMenu([item], [item], []);
-        test.done();
-      });
-    });
-  });
-};
-
-// Once a context is removed, it should no longer cause its item to appear.
-exports.testSetContextRemove = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let ctxt = loader.cm.SelectorContext("img");
-  let item = new loader.cm.Item({
-    label: "item",
-    context: ctxt
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-
-      // The item should be present at first.
-      test.checkMenu([item], [], []);
-      popup.hidePopup();
-
-      // Remove the img context and check again.
-      item.context = [];
-      test.showMenu("#image", function (popup) {
-        test.checkMenu([item], [item], []);
-        test.done();
-      });
-    });
-  });
-};
-
-// Once a context is added, it should affect whether the item appears.
-exports.testAddContext = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let ctxt = loader.cm.SelectorContext("img");
-  let item = new loader.cm.Item({
-    label: "item"
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-
-      // The item should not be present at first.
-      test.checkMenu([item], [item], []);
-      popup.hidePopup();
-
-      // Add the img context and check again.
-      item.context.add(ctxt);
-      test.showMenu("#image", function (popup) {
-        test.checkMenu([item], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-// Once a context is added, it should affect whether the item appears.
-exports.testSetContextAdd = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let ctxt = loader.cm.SelectorContext("img");
-  let item = new loader.cm.Item({
-    label: "item"
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-
-      // The item should not be present at first.
-      test.checkMenu([item], [item], []);
-      popup.hidePopup();
-
-      // Add the img context and check again.
-      item.context = [ctxt];
-      test.showMenu("#image", function (popup) {
-        test.checkMenu([item], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-// Lots of items should overflow into the overflow submenu.
-exports.testOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [];
-  for (let i = 0; i < OVERFLOW_THRESH_DEFAULT + 1; i++) {
-    let item = new loader.cm.Item({ label: "item " + i });
-    items.push(item);
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Module unload should cause all items to be removed.
-exports.testUnload = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain the item.
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    // Unload the module.
-    loader.unload();
-    test.showMenu(null, function (popup) {
-
-      // The item should be removed from the menu.
-      test.checkMenu([item], [], [item]);
-      test.done();
-    });
-  });
-};
-
-
-// Using multiple module instances to add items without causing overflow should
-// work OK.  Assumes OVERFLOW_THRESH_DEFAULT >= 2.
-exports.testMultipleModulesAdd = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  // Use each module to add an item, then unload each module in turn.
-  let item0 = new loader0.cm.Item({ label: "item 0" });
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain both items.
-    test.checkMenu([item0, item1], [], []);
-    popup.hidePopup();
-
-    // Unload the first module.
-    loader0.unload();
-    test.showMenu(null, function (popup) {
-
-      // The first item should be removed from the menu.
-      test.checkMenu([item0, item1], [], [item0]);
-      popup.hidePopup();
-
-      // Unload the second module.
-      loader1.unload();
-      test.showMenu(null, function (popup) {
-
-        // Both items should be removed from the menu.
-        test.checkMenu([item0, item1], [], [item0, item1]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Using multiple module instances to add items causing overflow should work OK.
-exports.testMultipleModulesAddOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  // Use module 0 to add OVERFLOW_THRESH_DEFAULT items.
-  let items0 = [];
-  for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) {
-    let item = new loader0.cm.Item({ label: "item 0 " + i });
-    items0.push(item);
-  }
-
-  // Use module 1 to add one item.
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  let allItems = items0.concat(item1);
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain all items in overflow.
-    test.checkMenu(allItems, [], []);
-    popup.hidePopup();
-
-    // Unload the first module.
-    loader0.unload();
-    test.showMenu(null, function (popup) {
-
-      // The first items should be removed from the menu, which should not
-      // overflow.
-      test.checkMenu(allItems, [], items0);
-      popup.hidePopup();
-
-      // Unload the second module.
-      loader1.unload();
-      test.showMenu(null, function (popup) {
-
-        // All items should be removed from the menu.
-        test.checkMenu(allItems, [], allItems);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Using multiple module instances to modify the menu without causing overflow
-// should work OK.  This test creates two loaders and:
-// loader0 create item -> loader1 create item -> loader0.unload ->
-// loader1.unload
-exports.testMultipleModulesDiffContexts1 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item0 = new loader0.cm.Item({
-    label: "item 0",
-    context: loader0.cm.SelectorContext("img")
-  });
-
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain item1.
-    test.checkMenu([item0, item1], [item0], []);
-    popup.hidePopup();
-
-    // Unload module 0.
-    loader0.unload();
-    test.showMenu(null, function (popup) {
-
-      // item0 should be removed from the menu.
-      test.checkMenu([item0, item1], [], [item0]);
-      popup.hidePopup();
-
-      // Unload module 1.
-      loader1.unload();
-      test.showMenu(null, function (popup) {
-
-        // Both items should be removed from the menu.
-        test.checkMenu([item0, item1], [], [item0, item1]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Using multiple module instances to modify the menu without causing overflow
-// should work OK.  This test creates two loaders and:
-// loader1 create item -> loader0 create item -> loader0.unload ->
-// loader1.unload
-exports.testMultipleModulesDiffContexts2 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  let item0 = new loader0.cm.Item({
-    label: "item 0",
-    context: loader0.cm.SelectorContext("img")
-  });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain item1.
-    test.checkMenu([item0, item1], [item0], []);
-    popup.hidePopup();
-
-    // Unload module 0.
-    loader0.unload();
-    test.showMenu(null, function (popup) {
-
-      // item0 should be removed from the menu.
-      test.checkMenu([item0, item1], [], [item0]);
-      popup.hidePopup();
-
-      // Unload module 1.
-      loader1.unload();
-      test.showMenu(null, function (popup) {
-
-        // Both items should be removed from the menu.
-        test.checkMenu([item0, item1], [], [item0, item1]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Using multiple module instances to modify the menu without causing overflow
-// should work OK.  This test creates two loaders and:
-// loader0 create item -> loader1 create item -> loader1.unload ->
-// loader0.unload
-exports.testMultipleModulesDiffContexts3 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item0 = new loader0.cm.Item({
-    label: "item 0",
-    context: loader0.cm.SelectorContext("img")
-  });
-
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain item1.
-    test.checkMenu([item0, item1], [item0], []);
-    popup.hidePopup();
-
-    // Unload module 1.
-    loader1.unload();
-    test.showMenu(null, function (popup) {
-
-      // item1 should be removed from the menu.
-      test.checkMenu([item0, item1], [item0], [item1]);
-      popup.hidePopup();
-
-      // Unload module 0.
-      loader0.unload();
-      test.showMenu(null, function (popup) {
-
-        // Both items should be removed from the menu.
-        test.checkMenu([item0, item1], [], [item0, item1]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Using multiple module instances to modify the menu without causing overflow
-// should work OK.  This test creates two loaders and:
-// loader1 create item -> loader0 create item -> loader1.unload ->
-// loader0.unload
-exports.testMultipleModulesDiffContexts4 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  let item0 = new loader0.cm.Item({
-    label: "item 0",
-    context: loader0.cm.SelectorContext("img")
-  });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain item1.
-    test.checkMenu([item0, item1], [item0], []);
-    popup.hidePopup();
-
-    // Unload module 1.
-    loader1.unload();
-    test.showMenu(null, function (popup) {
-
-      // item1 should be removed from the menu.
-      test.checkMenu([item0, item1], [item0], [item1]);
-      popup.hidePopup();
-
-      // Unload module 0.
-      loader0.unload();
-      test.showMenu(null, function (popup) {
-
-        // Both items should be removed from the menu.
-        test.checkMenu([item0, item1], [], [item0, item1]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Test interactions between a loaded module, unloading another module, and the
-// menu separator and overflow submenu.
-exports.testMultipleModulesAddRemove = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item = new loader0.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain the item.
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    // Remove the item.
-    item.destroy();
-    test.showMenu(null, function (popup) {
-
-      // The item should be removed from the menu.
-      test.checkMenu([item], [], [item]);
-      popup.hidePopup();
-
-      // Unload module 1.
-      loader1.unload();
-      test.showMenu(null, function (popup) {
-
-        // There shouldn't be any errors involving the menu separator or
-        // overflow submenu.
-        test.checkMenu([item], [], [item]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Checks that the order of menu items is correct when adding/removing across
-// multiple modules. All items from a single module should remain in a group
-exports.testMultipleModulesOrder = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  // Use each module to add an item, then unload each module in turn.
-  let item0 = new loader0.cm.Item({ label: "item 0" });
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain both items.
-    test.checkMenu([item0, item1], [], []);
-    popup.hidePopup();
-
-    let item2 = new loader0.cm.Item({ label: "item 2" });
-
-    test.showMenu(null, function (popup) {
-
-      // The new item should be grouped with the same items from loader0.
-      test.checkMenu([item0, item2, item1], [], []);
-      popup.hidePopup();
-
-      let item3 = new loader1.cm.Item({ label: "item 3" });
-
-      test.showMenu(null, function (popup) {
-
-        // Same again
-        test.checkMenu([item0, item2, item1, item3], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Checks that the order of menu items is correct when adding/removing across
-// multiple modules when overflowing. All items from a single module should
-// remain in a group
-exports.testMultipleModulesOrderOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 0);
-
-  // Use each module to add an item, then unload each module in turn.
-  let item0 = new loader0.cm.Item({ label: "item 0" });
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-
-    // The menu should contain both items.
-    test.checkMenu([item0, item1], [], []);
-    popup.hidePopup();
-
-    let item2 = new loader0.cm.Item({ label: "item 2" });
-
-    test.showMenu(null, function (popup) {
-
-      // The new item should be grouped with the same items from loader0.
-      test.checkMenu([item0, item2, item1], [], []);
-      popup.hidePopup();
-
-      let item3 = new loader1.cm.Item({ label: "item 3" });
-
-      test.showMenu(null, function (popup) {
-
-        // Same again
-        test.checkMenu([item0, item2, item1, item3], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Checks that if a module's items are all hidden then the overflow menu doesn't
-// get hidden
-exports.testMultipleModulesOverflowHidden = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 0);
-
-  // Use each module to add an item, then unload each module in turn.
-  let item0 = new loader0.cm.Item({ label: "item 0" });
-  let item1 = new loader1.cm.Item({
-    label: "item 1",
-    context: loader1.cm.SelectorContext("a")
-  });
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu([item0, item1], [item1], []);
-    test.done();
-  });
-};
-
-
-// Checks that if a module's items are all hidden then the overflow menu doesn't
-// get hidden (reverse order to above)
-exports.testMultipleModulesOverflowHidden2 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 0);
-
-  // Use each module to add an item, then unload each module in turn.
-  let item0 = new loader0.cm.Item({
-    label: "item 0",
-    context: loader0.cm.SelectorContext("a")
-  });
-  let item1 = new loader1.cm.Item({ label: "item 1" });
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu([item0, item1], [item0], []);
-    test.done();
-  });
-};
-
-
-// Checks that we don't overflow if there are more items than the overflow
-// threshold but not all of them are visible
-exports.testOverflowIgnoresHidden = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let prefs = loader.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 2);
-
-  let allItems = [
-    new loader.cm.Item({
-      label: "item 0"
-    }),
-    new loader.cm.Item({
-      label: "item 1"
-    }),
-    new loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.SelectorContext("a")
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu(allItems, [allItems[2]], []);
-    test.done();
-  });
-};
-
-
-// Checks that we don't overflow if there are more items than the overflow
-// threshold but not all of them are visible
-exports.testOverflowIgnoresHiddenMultipleModules1 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 2);
-
-  let allItems = [
-    new loader0.cm.Item({
-      label: "item 0"
-    }),
-    new loader0.cm.Item({
-      label: "item 1"
-    }),
-    new loader1.cm.Item({
-      label: "item 2",
-      context: loader1.cm.SelectorContext("a")
-    }),
-    new loader1.cm.Item({
-      label: "item 3",
-      context: loader1.cm.SelectorContext("a")
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu(allItems, [allItems[2], allItems[3]], []);
-    test.done();
-  });
-};
-
-
-// Checks that we don't overflow if there are more items than the overflow
-// threshold but not all of them are visible
-exports.testOverflowIgnoresHiddenMultipleModules2 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 2);
-
-  let allItems = [
-    new loader0.cm.Item({
-      label: "item 0"
-    }),
-    new loader0.cm.Item({
-      label: "item 1",
-      context: loader0.cm.SelectorContext("a")
-    }),
-    new loader1.cm.Item({
-      label: "item 2"
-    }),
-    new loader1.cm.Item({
-      label: "item 3",
-      context: loader1.cm.SelectorContext("a")
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu(allItems, [allItems[1], allItems[3]], []);
-    test.done();
-  });
-};
-
-
-// Checks that we don't overflow if there are more items than the overflow
-// threshold but not all of them are visible
-exports.testOverflowIgnoresHiddenMultipleModules3 = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let prefs = loader0.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 2);
-
-  let allItems = [
-    new loader0.cm.Item({
-      label: "item 0",
-      context: loader0.cm.SelectorContext("a")
-    }),
-    new loader0.cm.Item({
-      label: "item 1",
-      context: loader0.cm.SelectorContext("a")
-    }),
-    new loader1.cm.Item({
-      label: "item 2"
-    }),
-    new loader1.cm.Item({
-      label: "item 3"
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    // One should be hidden
-    test.checkMenu(allItems, [allItems[0], allItems[1]], []);
-    test.done();
-  });
-};
-
-
-// Tests that we transition between overflowing to non-overflowing to no items
-// and back again
-exports.testOverflowTransition = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let prefs = loader.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 2);
-
-  let pItems = [
-    new loader.cm.Item({
-      label: "item 0",
-      context: loader.cm.SelectorContext("p")
-    }),
-    new loader.cm.Item({
-      label: "item 1",
-      context: loader.cm.SelectorContext("p")
-    })
-  ];
-
-  let aItems = [
-    new loader.cm.Item({
-      label: "item 2",
-      context: loader.cm.SelectorContext("a")
-    }),
-    new loader.cm.Item({
-      label: "item 3",
-      context: loader.cm.SelectorContext("a")
-    })
-  ];
-
-  let allItems = pItems.concat(aItems);
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#link", function (popup) {
-      // The menu should contain all items and will overflow
-      test.checkMenu(allItems, [], []);
-      popup.hidePopup();
-
-      test.showMenu("#text", function (popup) {
-        // Only contains hald the items and will not overflow
-        test.checkMenu(allItems, aItems, []);
-        popup.hidePopup();
-
-        test.showMenu(null, function (popup) {
-          // None of the items will be visible
-          test.checkMenu(allItems, allItems, []);
-          popup.hidePopup();
-
-          test.showMenu("#text", function (popup) {
-            // Only contains hald the items and will not overflow
-            test.checkMenu(allItems, aItems, []);
-            popup.hidePopup();
-
-            test.showMenu("#link", function (popup) {
-              // The menu should contain all items and will overflow
-              test.checkMenu(allItems, [], []);
-              popup.hidePopup();
-
-              test.showMenu(null, function (popup) {
-                // None of the items will be visible
-                test.checkMenu(allItems, allItems, []);
-                popup.hidePopup();
-
-                test.showMenu("#link", function (popup) {
-                  // The menu should contain all items and will overflow
-                  test.checkMenu(allItems, [], []);
-                  test.done();
-                });
-              });
-            });
-          });
-        });
-      });
-    });
-  });
-};
-
-
-// An item's command listener should work.
-exports.testItemCommand = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    data: "item data",
-    contentScript: 'self.on("click", function (node, data) {' +
-                   '  self.postMessage({' +
-                   '    tagName: node.tagName,' +
-                   '    data: data' +
-                   '  });' +
-                   '});',
-    onMessage: function (data) {
-      assert.equal(this, item, "`this` inside onMessage should be item");
-      assert.equal(data.tagName, "HTML", "node should be an HTML element");
-      assert.equal(data.data, item.data, "data should be item data");
-      test.done();
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    let elt = test.getItemElt(popup, item);
-
-    // create a command event
-    let evt = elt.ownerDocument.createEvent('Event');
-    evt.initEvent('command', true, true);
-    elt.dispatchEvent(evt);
-  });
-};
-
-
-// A menu's click listener should work and receive bubbling 'command' events from
-// sub-items appropriately.  This also tests menus and ensures that when a CSS
-// selector context matches the clicked node's ancestor, the matching ancestor
-// is passed to listeners as the clicked node.
-exports.testMenuCommand = function (assert, done) {
-  // Create a top-level menu, submenu, and item, like this:
-  // topMenu -> submenu -> item
-  // Click the item and make sure the click bubbles.
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "submenu item",
-    data: "submenu item data",
-    context: loader.cm.SelectorContext("a"),
-  });
-
-  let submenu = new loader.cm.Menu({
-    label: "submenu",
-    context: loader.cm.SelectorContext("a"),
-    items: [item]
-  });
-
-  let topMenu = new loader.cm.Menu({
-    label: "top menu",
-    contentScript: 'self.on("click", function (node, data) {' +
-                   '  self.postMessage({' +
-                   '    tagName: node.tagName,' +
-                   '    data: data' +
-                   '  });' +
-                   '});',
-    onMessage: function (data) {
-      assert.equal(this, topMenu, "`this` inside top menu should be menu");
-      assert.equal(data.tagName, "A", "Clicked node should be anchor");
-      assert.equal(data.data, item.data,
-                       "Clicked item data should be correct");
-      test.done();
-    },
-    items: [submenu],
-    context: loader.cm.SelectorContext("a")
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#span-link", function (popup) {
-      test.checkMenu([topMenu], [], []);
-      let topMenuElt = test.getItemElt(popup, topMenu);
-      let topMenuPopup = topMenuElt.firstChild;
-      let submenuElt = test.getItemElt(topMenuPopup, submenu);
-      let submenuPopup = submenuElt.firstChild;
-      let itemElt = test.getItemElt(submenuPopup, item);
-
-      // create a command event
-      let evt = itemElt.ownerDocument.createEvent('Event');
-      evt.initEvent('command', true, true);
-      itemElt.dispatchEvent(evt);
-    });
-  });
-};
-
-
-// Click listeners should work when multiple modules are loaded.
-exports.testItemCommandMultipleModules = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item0 = loader0.cm.Item({
-    label: "loader 0 item",
-    contentScript: 'self.on("click", self.postMessage);',
-    onMessage: function () {
-      test.fail("loader 0 item should not emit click event");
-    }
-  });
-  let item1 = loader1.cm.Item({
-    label: "loader 1 item",
-    contentScript: 'self.on("click", self.postMessage);',
-    onMessage: function () {
-      test.pass("loader 1 item clicked as expected");
-      test.done();
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item0, item1], [], []);
-    let item1Elt = test.getItemElt(popup, item1);
-
-    // create a command event
-    let evt = item1Elt.ownerDocument.createEvent('Event');
-    evt.initEvent('command', true, true);
-    item1Elt.dispatchEvent(evt);
-  });
-};
-
-
-
-
-// An item's click listener should work.
-exports.testItemClick = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    data: "item data",
-    contentScript: 'self.on("click", function (node, data) {' +
-                   '  self.postMessage({' +
-                   '    tagName: node.tagName,' +
-                   '    data: data' +
-                   '  });' +
-                   '});',
-    onMessage: function (data) {
-      assert.equal(this, item, "`this` inside onMessage should be item");
-      assert.equal(data.tagName, "HTML", "node should be an HTML element");
-      assert.equal(data.data, item.data, "data should be item data");
-      test.done();
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    let elt = test.getItemElt(popup, item);
-    elt.click();
-  });
-};
-
-
-// A menu's click listener should work and receive bubbling clicks from
-// sub-items appropriately.  This also tests menus and ensures that when a CSS
-// selector context matches the clicked node's ancestor, the matching ancestor
-// is passed to listeners as the clicked node.
-exports.testMenuClick = function (assert, done) {
-  // Create a top-level menu, submenu, and item, like this:
-  // topMenu -> submenu -> item
-  // Click the item and make sure the click bubbles.
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "submenu item",
-    data: "submenu item data",
-    context: loader.cm.SelectorContext("a"),
-  });
-
-  let submenu = new loader.cm.Menu({
-    label: "submenu",
-    context: loader.cm.SelectorContext("a"),
-    items: [item]
-  });
-
-  let topMenu = new loader.cm.Menu({
-    label: "top menu",
-    contentScript: 'self.on("click", function (node, data) {' +
-                   '  self.postMessage({' +
-                   '    tagName: node.tagName,' +
-                   '    data: data' +
-                   '  });' +
-                   '});',
-    onMessage: function (data) {
-      assert.equal(this, topMenu, "`this` inside top menu should be menu");
-      assert.equal(data.tagName, "A", "Clicked node should be anchor");
-      assert.equal(data.data, item.data,
-                       "Clicked item data should be correct");
-      test.done();
-    },
-    items: [submenu],
-    context: loader.cm.SelectorContext("a")
-  });
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#span-link", function (popup) {
-      test.checkMenu([topMenu], [], []);
-      let topMenuElt = test.getItemElt(popup, topMenu);
-      let topMenuPopup = topMenuElt.firstChild;
-      let submenuElt = test.getItemElt(topMenuPopup, submenu);
-      let submenuPopup = submenuElt.firstChild;
-      let itemElt = test.getItemElt(submenuPopup, item);
-      itemElt.click();
-    });
-  });
-};
-
-// Click listeners should work when multiple modules are loaded.
-exports.testItemClickMultipleModules = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let item0 = loader0.cm.Item({
-    label: "loader 0 item",
-    contentScript: 'self.on("click", self.postMessage);',
-    onMessage: function () {
-      test.fail("loader 0 item should not emit click event");
-    }
-  });
-  let item1 = loader1.cm.Item({
-    label: "loader 1 item",
-    contentScript: 'self.on("click", self.postMessage);',
-    onMessage: function () {
-      test.pass("loader 1 item clicked as expected");
-      test.done();
-    }
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item0, item1], [], []);
-    let item1Elt = test.getItemElt(popup, item1);
-    item1Elt.click();
-  });
-};
-
-
-// Adding a separator to a submenu should work OK.
-exports.testSeparator = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = new loader.cm.Menu({
-    label: "submenu",
-    items: [new loader.cm.Separator()]
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// The parentMenu option should work
-exports.testParentMenu = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = new loader.cm.Menu({
-    label: "submenu",
-    items: [loader.cm.Item({ label: "item 1" })],
-    parentMenu: loader.cm.contentContextMenu
-  });
-
-  let item = loader.cm.Item({
-    label: "item 2",
-    parentMenu: menu,
-  });
-
-  assert.equal(menu.items[1], item, "Item should be in the sub menu");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Existing context menu modifications should apply to new windows.
-exports.testNewWindow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.withNewWindow(function () {
-    test.showMenu(null, function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// When a new window is opened, items added by an unloaded module should not
-// be present in the menu.
-exports.testNewWindowMultipleModules = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-    loader.unload();
-    test.withNewWindow(function () {
-      test.showMenu(null, function (popup) {
-        test.checkMenu([item], [], [item]);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Existing context menu modifications should not apply to new private windows.
-exports.testNewPrivateWindow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    test.withNewPrivateWindow(function () {
-      test.showMenu(null, function (popup) {
-        test.checkMenu([], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Existing context menu modifications should apply to new private windows when
-// private browsing support is enabled.
-exports.testNewPrivateEnabledWindow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newPrivateLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    test.withNewPrivateWindow(function () {
-      test.showMenu(null, function (popup) {
-        test.checkMenu([item], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Existing context menu modifications should apply to new private windows when
-// private browsing support is enabled unless unloaded.
-exports.testNewPrivateEnabledWindowUnloaded = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newPrivateLoader();
-
-  let item = new loader.cm.Item({ label: "item" });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    popup.hidePopup();
-
-    loader.unload();
-
-    test.withNewPrivateWindow(function () {
-      test.showMenu(null, function (popup) {
-        test.checkMenu([], [], []);
-        test.done();
-      });
-    });
-  });
-};
-
-
-// Items in the context menu should be sorted according to locale.
-exports.testSorting = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  // Make an unsorted items list.  It'll look like this:
-  //   item 1, item 0, item 3, item 2, item 5, item 4, ...
-  let items = [];
-  for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i += 2) {
-    items.push(new loader.cm.Item({ label: "item " + (i + 1) }));
-    items.push(new loader.cm.Item({ label: "item " + i }));
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Items in the overflow menu should be sorted according to locale.
-exports.testSortingOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  // Make an unsorted items list.  It'll look like this:
-  //   item 1, item 0, item 3, item 2, item 5, item 4, ...
-  let items = [];
-  for (let i = 0; i < OVERFLOW_THRESH_DEFAULT * 2; i += 2) {
-    items.push(new loader.cm.Item({ label: "item " + (i + 1) }));
-    items.push(new loader.cm.Item({ label: "item " + i }));
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Multiple modules shouldn't interfere with sorting.
-exports.testSortingMultipleModules = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader0 = test.newLoader();
-  let loader1 = test.newLoader();
-
-  let items0 = [];
-  let items1 = [];
-  for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) {
-    if (i % 2) {
-      let item = new loader0.cm.Item({ label: "item " + i });
-      items0.push(item);
-    }
-    else {
-      let item = new loader1.cm.Item({ label: "item " + i });
-      items1.push(item);
-    }
-  }
-  let allItems = items0.concat(items1);
-
-  test.showMenu(null, function (popup) {
-
-    // All items should be present and sorted.
-    test.checkMenu(allItems, [], []);
-    popup.hidePopup();
-    loader0.unload();
-    loader1.unload();
-    test.showMenu(null, function (popup) {
-
-      // All items should be removed.
-      test.checkMenu(allItems, [], allItems);
-      test.done();
-    });
-  });
-};
-
-
-// Content click handlers and context handlers should be able to communicate,
-// i.e., they're eval'ed in the same worker and sandbox.
-exports.testContentCommunication = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({
-    label: "item",
-    contentScript: 'var potato;' +
-                   'self.on("context", function () {' +
-                   '  potato = "potato";' +
-                   '  return true;' +
-                   '});' +
-                   'self.on("click", function () {' +
-                   '  self.postMessage(potato);' +
-                   '});',
-  });
-
-  item.on("message", function (data) {
-    assert.equal(data, "potato", "That's a lot of potatoes!");
-    test.done();
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    let elt = test.getItemElt(popup, item);
-    elt.click();
-  });
-};
-
-
-// When the context menu is invoked on a tab that was already open when the
-// module was loaded, it should contain the expected items and content workers
-// should function as expected.
-exports.testLoadWithOpenTab = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  test.withTestDoc(function (window, doc) {
-    let loader = test.newLoader();
-    let item = new loader.cm.Item({
-      label: "item",
-      contentScript:
-        'self.on("click", () => self.postMessage("click"));',
-      onMessage: function (msg) {
-        if (msg === "click")
-          test.done();
-      }
-    });
-    test.showMenu(null, function (popup) {
-      test.checkMenu([item], [], []);
-      test.getItemElt(popup, item).click();
-    });
-  });
-};
-
-// Bug 732716: Ensure that the node given in `click` event works fine
-// (i.e. is correctly wrapped)
-exports.testDrawImageOnClickNode = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  test.withTestDoc(function (window, doc) {
-    let loader = test.newLoader();
-    let item = new loader.cm.Item({
-      label: "item",
-      context: loader.cm.SelectorContext("img"),
-      contentScript: "new " + function() {
-        self.on("click", function (img, data) {
-          let ctx = document.createElement("canvas").getContext("2d");
-          ctx.drawImage(img, 1, 1, 1, 1);
-          self.postMessage("done");
-        });
-      },
-      onMessage: function (msg) {
-        if (msg === "done")
-          test.done();
-      }
-    });
-    test.showMenu("#image", function (popup) {
-      test.checkMenu([item], [], []);
-      test.getItemElt(popup, item).click();
-    });
-  });
-};
-
-
-// Setting an item's label before the menu is ever shown should correctly change
-// its label.
-exports.testSetLabelBeforeShow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({ label: "a" }),
-    new loader.cm.Item({ label: "b" })
-  ]
-  items[0].label = "z";
-  assert.equal(items[0].label, "z");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Setting an item's label after the menu is shown should correctly change its
-// label.
-exports.testSetLabelAfterShow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    new loader.cm.Item({ label: "a" }),
-    new loader.cm.Item({ label: "b" })
-  ];
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    popup.hidePopup();
-
-    items[0].label = "z";
-    assert.equal(items[0].label, "z");
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Setting an item's label before the menu is ever shown should correctly change
-// its label.
-exports.testSetLabelBeforeShowOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let prefs = loader.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 0);
-
-  let items = [
-    new loader.cm.Item({ label: "a" }),
-    new loader.cm.Item({ label: "b" })
-  ]
-  items[0].label = "z";
-  assert.equal(items[0].label, "z");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    test.done();
-  });
-};
-
-
-// Setting an item's label after the menu is shown should correctly change its
-// label.
-exports.testSetLabelAfterShowOverflow = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let prefs = loader.loader.require("sdk/preferences/service");
-  prefs.set(OVERFLOW_THRESH_PREF, 0);
-
-  let items = [
-    new loader.cm.Item({ label: "a" }),
-    new loader.cm.Item({ label: "b" })
-  ];
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, [], []);
-    popup.hidePopup();
-
-    items[0].label = "z";
-    assert.equal(items[0].label, "z");
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Setting the label of an item in a Menu should work.
-exports.testSetLabelMenuItem = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [loader.cm.Item({ label: "a" })]
-  });
-  menu.items[0].label = "z";
-
-  assert.equal(menu.items[0].label, "z");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Menu.addItem() should work.
-exports.testMenuAddItem = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [
-      loader.cm.Item({ label: "item 0" })
-    ]
-  });
-  menu.addItem(loader.cm.Item({ label: "item 1" }));
-  menu.addItem(loader.cm.Item({ label: "item 2" }));
-
-  assert.equal(menu.items.length, 3,
-                   "menu should have correct number of items");
-  for (let i = 0; i < 3; i++) {
-    assert.equal(menu.items[i].label, "item " + i,
-                     "item label should be correct");
-    assert.equal(menu.items[i].parentMenu, menu,
-                     "item's parent menu should be correct");
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Adding the same item twice to a menu should work as expected.
-exports.testMenuAddItemTwice = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: []
-  });
-  let subitem = loader.cm.Item({ label: "item 1" })
-  menu.addItem(subitem);
-  menu.addItem(loader.cm.Item({ label: "item 0" }));
-  menu.addItem(subitem);
-
-  assert.equal(menu.items.length, 2,
-                   "menu should have correct number of items");
-  for (let i = 0; i < 2; i++) {
-    assert.equal(menu.items[i].label, "item " + i,
-                     "item label should be correct");
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Menu.removeItem() should work.
-exports.testMenuRemoveItem = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let subitem = loader.cm.Item({ label: "item 1" });
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [
-      loader.cm.Item({ label: "item 0" }),
-      subitem,
-      loader.cm.Item({ label: "item 2" })
-    ]
-  });
-
-  // Removing twice should be harmless.
-  menu.removeItem(subitem);
-  menu.removeItem(subitem);
-
-  assert.equal(subitem.parentMenu, null,
-                   "item's parent menu should be correct");
-
-  assert.equal(menu.items.length, 2,
-                   "menu should have correct number of items");
-  assert.equal(menu.items[0].label, "item 0",
-                   "item label should be correct");
-  assert.equal(menu.items[1].label, "item 2",
-                   "item label should be correct");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Adding an item currently contained in one menu to another menu should work.
-exports.testMenuItemSwap = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let subitem = loader.cm.Item({ label: "item" });
-  let menu0 = loader.cm.Menu({
-    label: "menu 0",
-    items: [subitem]
-  });
-  let menu1 = loader.cm.Menu({
-    label: "menu 1",
-    items: []
-  });
-  menu1.addItem(subitem);
-
-  assert.equal(menu0.items.length, 0,
-                   "menu should have correct number of items");
-
-  assert.equal(menu1.items.length, 1,
-                   "menu should have correct number of items");
-  assert.equal(menu1.items[0].label, "item",
-                   "item label should be correct");
-
-  assert.equal(subitem.parentMenu, menu1,
-                   "item's parent menu should be correct");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu0, menu1], [menu0], []);
-    test.done();
-  });
-};
-
-
-// Destroying an item should remove it from its parent menu.
-exports.testMenuItemDestroy = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let subitem = loader.cm.Item({ label: "item" });
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [subitem]
-  });
-  subitem.destroy();
-
-  assert.equal(menu.items.length, 0,
-                   "menu should have correct number of items");
-  assert.equal(subitem.parentMenu, null,
-                   "item's parent menu should be correct");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [menu], []);
-    test.done();
-  });
-};
-
-
-// Setting Menu.items should work.
-exports.testMenuItemsSetter = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [
-      loader.cm.Item({ label: "old item 0" }),
-      loader.cm.Item({ label: "old item 1" })
-    ]
-  });
-  menu.items = [
-    loader.cm.Item({ label: "new item 0" }),
-    loader.cm.Item({ label: "new item 1" }),
-    loader.cm.Item({ label: "new item 2" })
-  ];
-
-  assert.equal(menu.items.length, 3,
-                   "menu should have correct number of items");
-  for (let i = 0; i < 3; i++) {
-    assert.equal(menu.items[i].label, "new item " + i,
-                     "item label should be correct");
-    assert.equal(menu.items[i].parentMenu, menu,
-                     "item's parent menu should be correct");
-  }
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], []);
-    test.done();
-  });
-};
-
-
-// Setting Item.data should work.
-exports.testItemDataSetter = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = loader.cm.Item({ label: "old item 0", data: "old" });
-  item.data = "new";
-
-  assert.equal(item.data, "new", "item should have correct data");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item], [], []);
-    test.done();
-  });
-};
-
-
-// Open the test doc, load the module, make sure items appear when context-
-// clicking the iframe.
-exports.testAlreadyOpenIframe = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  test.withTestDoc(function (window, doc) {
-    let loader = test.newLoader();
-    let item = new loader.cm.Item({
-      label: "item"
-    });
-    test.showMenu("#iframe", function (popup) {
-      test.checkMenu([item], [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Tests that a missing label throws an exception
-exports.testItemNoLabel = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  try {
-    new loader.cm.Item({});
-    assert.ok(false, "Should have seen exception");
-  }
-  catch (e) {
-    assert.ok(true, "Should have seen exception");
-  }
-
-  try {
-    new loader.cm.Item({ label: null });
-    assert.ok(false, "Should have seen exception");
-  }
-  catch (e) {
-    assert.ok(true, "Should have seen exception");
-  }
-
-  try {
-    new loader.cm.Item({ label: undefined });
-    assert.ok(false, "Should have seen exception");
-  }
-  catch (e) {
-    assert.ok(true, "Should have seen exception");
-  }
-
-  try {
-    new loader.cm.Item({ label: "" });
-    assert.ok(false, "Should have seen exception");
-  }
-  catch (e) {
-    assert.ok(true, "Should have seen exception");
-  }
-
-  test.done();
-}
-
-/* bug 1302854 - disabled this subtest as it is intermittent
-// Tests that items can have an empty data property
-exports.testItemNoData = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  function checkData(data) {
-    assert.equal(data, undefined, "Data should be undefined");
-  }
-
-  let item1 = new loader.cm.Item({
-    label: "item 1",
-    contentScript: 'self.on("click", (node, data) => self.postMessage(data))',
-    onMessage: checkData
-  });
-  let item2 = new loader.cm.Item({
-    label: "item 2",
-    data: null,
-    contentScript: 'self.on("click", (node, data) => self.postMessage(data))',
-    onMessage: checkData
-  });
-  let item3 = new loader.cm.Item({
-    label: "item 3",
-    data: undefined,
-    contentScript: 'self.on("click", (node, data) => self.postMessage(data))',
-    onMessage: checkData
-  });
-
-  assert.equal(item1.data, undefined, "Should be no defined data");
-  assert.equal(item2.data, null, "Should be no defined data");
-  assert.equal(item3.data, undefined, "Should be no defined data");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item1, item2, item3], [], []);
-
-    let itemElt = test.getItemElt(popup, item1);
-    itemElt.click();
-
-    test.hideMenu(function() {
-      test.showMenu(null, function (popup) {
-        let itemElt = test.getItemElt(popup, item2);
-        itemElt.click();
-
-        test.hideMenu(function() {
-          test.showMenu(null, function (popup) {
-            let itemElt = test.getItemElt(popup, item3);
-            itemElt.click();
-
-            test.done();
-          });
-        });
-      });
-    });
-  });
-}
-*/
-
-
-exports.testItemNoAccessKey = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item1 = new loader.cm.Item({ label: "item 1" });
-  let item2 = new loader.cm.Item({ label: "item 2", accesskey: null });
-  let item3 = new loader.cm.Item({ label: "item 3", accesskey: undefined });
-
-  assert.equal(item1.accesskey, undefined, "Should be no defined image");
-  assert.equal(item2.accesskey, null, "Should be no defined image");
-  assert.equal(item3.accesskey, undefined, "Should be no defined image");
-
-  test.showMenu().
-  then((popup) => test.checkMenu([item1, item2, item3], [], [])).
-  then(test.done).
-  catch(assert.fail);
-}
-
-
-// Test accesskey support.
-exports.testItemAccessKey = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item = new loader.cm.Item({ label: "item", accesskey: "i" });
-  assert.equal(item.accesskey, "i", "Should have set the image to i");
-
-  let menu = new loader.cm.Menu({ label: "menu", accesskey: "m", items: [
-    loader.cm.Item({ label: "subitem" })
-  ]});
-  assert.equal(menu.accesskey, "m", "Should have set the accesskey to m");
-
-  test.showMenu().then((popup) => {
-    test.checkMenu([item, menu], [], []);
-
-    let accesskey = "e";
-    menu.accesskey = item.accesskey = accesskey;
-    assert.equal(item.accesskey, accesskey, "Should have set the accesskey to " + accesskey);
-    assert.equal(menu.accesskey, accesskey, "Should have set the accesskey to " + accesskey);
-    test.checkMenu([item, menu], [], []);
-
-    item.accesskey = null;
-    menu.accesskey = null;
-    assert.equal(item.accesskey, null, "Should have set the accesskey to " + accesskey);
-    assert.equal(menu.accesskey, null, "Should have set the accesskey to " + accesskey);
-    test.checkMenu([item, menu], [], []);
-  }).
-  then(test.done).
-  catch(assert.fail);
-};
-
-
-// Tests that items without an image don't attempt to show one
-exports.testItemNoImage = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let item1 = new loader.cm.Item({ label: "item 1" });
-  let item2 = new loader.cm.Item({ label: "item 2", image: null });
-  let item3 = new loader.cm.Item({ label: "item 3", image: undefined });
-
-  assert.equal(item1.image, undefined, "Should be no defined image");
-  assert.equal(item2.image, null, "Should be no defined image");
-  assert.equal(item3.image, undefined, "Should be no defined image");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item1, item2, item3], [], []);
-
-    test.done();
-  });
-}
-
-
-// Test image support.
-exports.testItemImage = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let imageURL = data.url("moz_favicon.ico");
-  let item = new loader.cm.Item({ label: "item", image: imageURL });
-  let menu = new loader.cm.Menu({ label: "menu", image: imageURL, items: [
-    loader.cm.Item({ label: "subitem" })
-  ]});
-  assert.equal(item.image, imageURL, "Should have set the image correctly");
-  assert.equal(menu.image, imageURL, "Should have set the image correctly");
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([item, menu], [], []);
-
-    let imageURL2 = data.url("dummy.ico");
-    item.image = imageURL2;
-    menu.image = imageURL2;
-    assert.equal(item.image, imageURL2, "Should have set the image correctly");
-    assert.equal(menu.image, imageURL2, "Should have set the image correctly");
-    test.checkMenu([item, menu], [], []);
-
-    item.image = null;
-    menu.image = null;
-    assert.equal(item.image, null, "Should have set the image correctly");
-    assert.equal(menu.image, null, "Should have set the image correctly");
-    test.checkMenu([item, menu], [], []);
-
-    test.done();
-  });
-};
-
-// Test image URL validation.
-exports.testItemImageValidURL = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  assert.throws(function(){
-      new loader.cm.Item({
-        label: "item 1",
-        image: "foo"
-      })
-    }, /Image URL validation failed/
-  );
-
-  assert.throws(function(){
-      new loader.cm.Item({
-        label: "item 2",
-        image: false
-      })
-    }, /Image URL validation failed/
-  );
-
-  assert.throws(function(){
-      new loader.cm.Item({
-        label: "item 3",
-        image: 0
-      })
-    }, /Image URL validation failed/
-  );
-
-  let imageURL = data.url("moz_favicon.ico");
-  let item4 = new loader.cm.Item({ label: "item 4", image: imageURL });
-  let item5 = new loader.cm.Item({ label: "item 5", image: null });
-  let item6 = new loader.cm.Item({ label: "item 6", image: undefined });
-
-  assert.equal(item4.image, imageURL, "Should be proper image URL");
-  assert.equal(item5.image, null, "Should be null image");
-  assert.equal(item6.image, undefined, "Should be undefined image");
-
-  test.done();
-};
-
-
-// Menu.destroy should destroy the item tree rooted at that menu.
-exports.testMenuDestroy = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let menu = loader.cm.Menu({
-    label: "menu",
-    items: [
-      loader.cm.Item({ label: "item 0" }),
-      loader.cm.Menu({
-        label: "item 1",
-        items: [
-          loader.cm.Item({ label: "subitem 0" }),
-          loader.cm.Item({ label: "subitem 1" }),
-          loader.cm.Item({ label: "subitem 2" })
-        ]
-      }),
-      loader.cm.Item({ label: "item 2" })
-    ]
-  });
-  menu.destroy();
-
-  /*let numRegistryEntries = 0;
-  loader.globalScope.browserManager.browserWins.forEach(function (bwin) {
-    for (let itemID in bwin.items)
-      numRegistryEntries++;
-  });
-  assert.equal(numRegistryEntries, 0, "All items should be unregistered.");*/
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([menu], [], [menu]);
-    test.done();
-  });
-};
-
-// Checks that if a menu contains sub items that are hidden then the menu is
-// hidden too. Also checks that content scripts and contexts work for sub items.
-exports.testSubItemContextNoMatchHideMenu = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    loader.cm.Menu({
-      label: "menu 1",
-      items: [
-        loader.cm.Item({
-          label: "subitem 1",
-          context: loader.cm.SelectorContext(".foo")
-        })
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 2",
-      items: [
-        loader.cm.Item({
-          label: "subitem 2",
-          contentScript: 'self.on("context", () => false);'
-        })
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 3",
-      items: [
-        loader.cm.Item({
-          label: "subitem 3",
-          context: loader.cm.SelectorContext(".foo")
-        }),
-        loader.cm.Item({
-          label: "subitem 4",
-          contentScript: 'self.on("context", () => false);'
-        })
-      ]
-    })
-  ];
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu(items, items, []);
-    test.done();
-  });
-};
-
-
-// Checks that if a menu contains a combination of hidden and visible sub items
-// then the menu is still visible too.
-exports.testSubItemContextMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let hiddenItems = [
-    loader.cm.Item({
-      label: "subitem 3",
-      context: loader.cm.SelectorContext(".foo")
-    }),
-    loader.cm.Item({
-      label: "subitem 6",
-      contentScript: 'self.on("context", () => false);'
-    })
-  ];
-
-  let items = [
-    loader.cm.Menu({
-      label: "menu 1",
-      items: [
-        loader.cm.Item({
-          label: "subitem 1",
-          context: loader.cm.URLContext(TEST_DOC_URL)
-        })
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 2",
-      items: [
-        loader.cm.Item({
-          label: "subitem 2",
-          contentScript: 'self.on("context", () => true);'
-        })
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 3",
-      items: [
-        hiddenItems[0],
-        loader.cm.Item({
-          label: "subitem 4",
-          contentScript: 'self.on("context", () => true);'
-        })
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 4",
-      items: [
-        loader.cm.Item({
-          label: "subitem 5",
-          context: loader.cm.URLContext(TEST_DOC_URL)
-        }),
-        hiddenItems[1]
-      ]
-    }),
-    loader.cm.Menu({
-      label: "menu 5",
-      items: [
-        loader.cm.Item({
-          label: "subitem 7",
-          context: loader.cm.URLContext(TEST_DOC_URL)
-        }),
-        loader.cm.Item({
-          label: "subitem 8",
-          contentScript: 'self.on("context", () => true);'
-        })
-      ]
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, hiddenItems, []);
-      test.done();
-    });
-  });
-};
-
-
-// Child items should default to visible, not to PageContext
-exports.testSubItemDefaultVisible = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [
-    loader.cm.Menu({
-      label: "menu 1",
-      context: loader.cm.SelectorContext("img"),
-      items: [
-        loader.cm.Item({
-          label: "subitem 1"
-        }),
-        loader.cm.Item({
-          label: "subitem 2",
-          context: loader.cm.SelectorContext("img")
-        }),
-        loader.cm.Item({
-          label: "subitem 3",
-          context: loader.cm.SelectorContext("a")
-        })
-      ]
-    })
-  ];
-
-  // subitem 3 will be hidden
-  let hiddenItems = [items[0].items[2]];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, hiddenItems, []);
-      test.done();
-    });
-  });
-};
-
-// Tests that the click event on sub menuitem
-// tiggers the click event for the sub menuitem and the parent menu
-exports.testSubItemClick = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let state = 0;
-
-  let items = [
-    loader.cm.Menu({
-      label: "menu 1",
-      items: [
-        loader.cm.Item({
-          label: "subitem 1",
-          data: "foobar",
-          contentScript: 'self.on("click", function (node, data) {' +
-                         '  self.postMessage({' +
-                         '    tagName: node.tagName,' +
-                         '    data: data' +
-                         '  });' +
-                         '});',
-          onMessage: function(msg) {
-            assert.equal(msg.tagName, "HTML", "should have seen the right node");
-            assert.equal(msg.data, "foobar", "should have seen the right data");
-            assert.equal(state, 0, "should have seen the event at the right time");
-            state++;
-          }
-        })
-      ],
-      contentScript: 'self.on("click", function (node, data) {' +
-                     '  self.postMessage({' +
-                     '    tagName: node.tagName,' +
-                     '    data: data' +
-                     '  });' +
-                     '});',
-      onMessage: function(msg) {
-        assert.equal(msg.tagName, "HTML", "should have seen the right node");
-        assert.equal(msg.data, "foobar", "should have seen the right data");
-        assert.equal(state, 1, "should have seen the event at the right time");
-
-        test.done();
-      }
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-
-      let topMenuElt = test.getItemElt(popup, items[0]);
-      let topMenuPopup = topMenuElt.firstChild;
-      let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]);
-      itemElt.click();
-    });
-  });
-};
-
-// Tests that the command event on sub menuitem
-// tiggers the click event for the sub menuitem and the parent menu
-exports.testSubItemCommand = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let state = 0;
-
-  let items = [
-    loader.cm.Menu({
-      label: "menu 1",
-      items: [
-        loader.cm.Item({
-          label: "subitem 1",
-          data: "foobar",
-          contentScript: 'self.on("click", function (node, data) {' +
-                         '  self.postMessage({' +
-                         '    tagName: node.tagName,' +
-                         '    data: data' +
-                         '  });' +
-                         '});',
-          onMessage: function(msg) {
-            assert.equal(msg.tagName, "HTML", "should have seen the right node");
-            assert.equal(msg.data, "foobar", "should have seen the right data");
-            assert.equal(state, 0, "should have seen the event at the right time");
-            state++;
-          }
-        })
-      ],
-      contentScript: 'self.on("click", function (node, data) {' +
-                     '  self.postMessage({' +
-                     '    tagName: node.tagName,' +
-                     '    data: data' +
-                     '  });' +
-                     '});',
-      onMessage: function(msg) {
-        assert.equal(msg.tagName, "HTML", "should have seen the right node");
-        assert.equal(msg.data, "foobar", "should have seen the right data");
-        assert.equal(state, 1, "should have seen the event at the right time");
-        state++
-
-        test.done();
-      }
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-
-      let topMenuElt = test.getItemElt(popup, items[0]);
-      let topMenuPopup = topMenuElt.firstChild;
-      let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]);
-
-      // create a command event
-      let evt = itemElt.ownerDocument.createEvent('Event');
-      evt.initEvent('command', true, true);
-      itemElt.dispatchEvent(evt);
-    });
-  });
-};
-
-// Tests that opening a context menu for an outer frame when an inner frame
-// has a selection doesn't activate the SelectionContext
-exports.testSelectionInInnerFrameNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let state = 0;
-
-  let items = [
-    loader.cm.Item({
-      label: "test item",
-      context: loader.cm.SelectionContext()
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    let frame = doc.getElementById("iframe");
-    frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body);
-
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-// Tests that opening a context menu for an inner frame when the inner frame
-// has a selection does activate the SelectionContext
-exports.testSelectionInInnerFrameMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let state = 0;
-
-  let items = [
-    loader.cm.Item({
-      label: "test item",
-      context: loader.cm.SelectionContext()
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    let frame = doc.getElementById("iframe");
-    frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body);
-
-    test.showMenu(["#iframe", "#text"], function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Tests that opening a context menu for an inner frame when the outer frame
-// has a selection doesn't activate the SelectionContext
-exports.testSelectionInOuterFrameNoMatch = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let state = 0;
-
-  let items = [
-    loader.cm.Item({
-      label: "test item",
-      context: loader.cm.SelectionContext()
-    })
-  ];
-
-  test.withTestDoc(function (window, doc) {
-    let frame = doc.getElementById("iframe");
-    window.getSelection().selectAllChildren(doc.body);
-
-    test.showMenu(["#iframe", "#text"], function (popup) {
-      test.checkMenu(items, items, []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the return value of the predicate function determines if
-// item is shown
-exports.testPredicateContextControl = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let itemTrue = loader.cm.Item({
-    label: "visible",
-    context: loader.cm.PredicateContext(function () { return true; })
-  });
-
-  let itemFalse = loader.cm.Item({
-    label: "hidden",
-    context: loader.cm.PredicateContext(function () { return false; })
-  });
-
-  test.showMenu(null, function (popup) {
-    test.checkMenu([itemTrue, itemFalse], [itemFalse], []);
-    test.done();
-  });
-};
-
-// Test that the data object has the correct document type
-exports.testPredicateContextDocumentType = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.equal(data.documentType, 'text/html');
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the correct document URL
-exports.testPredicateContextDocumentURL = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.equal(data.documentURL, TEST_DOC_URL);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object has the correct element name
-exports.testPredicateContextTargetName = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.targetName, "input");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#button", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object has the correct ID
-exports.testPredicateContextTargetIDSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.targetID, "button");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#button", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the correct ID
-exports.testPredicateContextTargetIDNotSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.targetID, null);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(".predicate-test-a", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object is showing editable correctly for regular text inputs
-exports.testPredicateContextTextBoxIsEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, true);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#textbox", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object is showing editable correctly for readonly text inputs
-exports.testPredicateContextReadonlyTextBoxIsNotEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, false);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#readonly-textbox", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object is showing editable correctly for disabled text inputs
-exports.testPredicateContextDisabledTextBoxIsNotEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, false);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#disabled-textbox", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object is showing editable correctly for text areas
-exports.testPredicateContextTextAreaIsEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, true);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#textfield", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that non-text inputs are not considered editable
-exports.testPredicateContextButtonIsNotEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, false);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#button", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object is showing editable correctly
-exports.testPredicateContextNonInputIsNotEditable = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, false);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object is showing editable correctly for HTML contenteditable elements
-exports.testPredicateContextEditableElement = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.isEditable, true);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#editable", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object does not have a selection when there is none
-exports.testPredicateContextNoSelectionInPage = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.selectionText, null);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object includes the selected page text
-exports.testPredicateContextSelectionInPage = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      // since we might get whitespace
-      assert.ok(data.selectionText && data.selectionText.search(/^\s*Some text.\s*$/) != -1,
-		'Expected "Some text.", got "' + data.selectionText + '"');
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    window.getSelection().selectAllChildren(doc.getElementById("text"));
-    test.showMenu(null, function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object includes the selected input text
-exports.testPredicateContextSelectionInTextBox = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      // since we might get whitespace
-      assert.strictEqual(data.selectionText, "t v");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    let textbox = doc.getElementById("textbox");
-    test.selectRange("#textbox", 3, 6);
-    test.showMenu("#textbox", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the correct src for an image
-exports.testPredicateContextTargetSrcSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let image;
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.srcURL, image.src);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    image = doc.getElementById("image");
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has no src for a link
-exports.testPredicateContextTargetSrcNotSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.srcURL, null);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#link", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-
-// Test that the data object has the correct link set
-exports.testPredicateContextTargetLinkSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let image;
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.linkURL, TEST_DOC_URL + "#test");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu(".predicate-test-a", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has no link for an image
-exports.testPredicateContextTargetLinkNotSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.linkURL, null);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the correct link for a nested image
-exports.testPredicateContextTargetLinkSetNestedImage = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.linkURL, TEST_DOC_URL + "#nested-image");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#predicate-test-nested-image", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the correct link for a complex nested structure
-exports.testPredicateContextTargetLinkSetNestedStructure = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.linkURL, TEST_DOC_URL + "#nested-structure");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#predicate-test-nested-structure", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has the value for an input textbox
-exports.testPredicateContextTargetValueSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-  let image;
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.value, "test value");
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#textbox", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-// Test that the data object has no value for an image
-exports.testPredicateContextTargetValueNotSet = function (assert, done) {
-  let test = new TestHelper(assert, done);
-  let loader = test.newLoader();
-
-  let items = [loader.cm.Item({
-    label: "item",
-    context: loader.cm.PredicateContext(function (data) {
-      assert.strictEqual(data.value, null);
-      return true;
-    })
-  })];
-
-  test.withTestDoc(function (window, doc) {
-    test.showMenu("#image", function (popup) {
-      test.checkMenu(items, [], []);
-      test.done();
-    });
-  });
-};
-
-if (isTravisCI) {
-  module.exports = {
-    "test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
-  };
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-context-menu@2.js
+++ /dev/null
@@ -1,1350 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cc, Ci } = require("chrome");
-const {openWindow, closeWindow, openTab, closeTab,
-       openContextMenu, closeContextMenu, select,
-       readNode, captureContextMenu, withTab, withItems } = require("./context-menu/util");
-const {when} = require("sdk/dom/events");
-const {Item, Menu, Separator, Contexts, Readers } = require("sdk/context-menu@2");
-const prefs = require("sdk/preferences/service");
-const { before, after } = require('sdk/test/utils');
-
-const testPageURI = require.resolve("./test-context-menu").replace(".js", ".html");
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-const data = input =>
-  `data:text/html;charset=utf-8,${encodeURIComponent(input)}`
-
-const menugroup = (...children) => Object.assign({
-  tagName: "menugroup",
-  namespaceURI: XUL_NS,
-  style: "-moz-box-orient: vertical;",
-  className: "sdk-context-menu-extension"
-}, children.length ? {children} : {});
-
-const menuseparator = () => ({
-  tagName: "menuseparator",
-  namespaceURI: XUL_NS,
-  className: "sdk-context-menu-separator"
-})
-
-const menuitem = properties => Object.assign({
-  tagName: "menuitem",
-  namespaceURI: XUL_NS,
-  className: "sdk-context-menu-item menuitem-iconic"
-}, properties);
-
-const menu = (properties, ...children) => Object.assign({
-  tagName: "menu",
-  namespaceURI: XUL_NS,
-  className: "sdk-context-menu menu-iconic"
-}, properties, {
-  children: [Object.assign({tagName: "menupopup", namespaceURI: XUL_NS},
-                           children.length ? {children} : {})]
-});
-
-// Destroying items that were previously created should cause them to be absent
-// from the menu.
-exports["test create / destroy menu item"] = withTab(function*(assert) {
-  const item = new Item({
-    label: "test-1"
-  });
-
-  const before = yield captureContextMenu("h1");
-
-  assert.deepEqual(before,
-                   menugroup(menuseparator(),
-                             menuitem({label: "test-1"})),
-                   "context menu contains separator & added item");
-
-  item.destroy();
-
-  const after = yield captureContextMenu("h1");
-  assert.deepEqual(after, menugroup(),
-                   "all items were removed children are present");
-}, data`<h1>hello</h1>`);
-
-
-/* Bug 1115419 - Disable occasionally failing test until we
-                 figure out why it fails.
-// Items created should be present on all browser windows.
-exports["test menu item in new window"] = function*(assert) {
-  const isMenuPopulated = function*(tab) {
-    const state = yield captureContextMenu("h1", tab);
-    assert.deepEqual(state,
-                     menugroup(menuseparator(),
-                               menuitem({label: "multi-window"})),
-                     "created menu item is present")
-  };
-
-  const isMenuEmpty = function*(tab) {
-    const state = yield captureContextMenu("h1", tab);
-    assert.deepEqual(state, menugroup(), "no sdk items present");
-  };
-
-  const item = new Item({ label: "multi-window" });
-
-  const tab1 = yield openTab(`data:text/html,<h1>hello</h1>`);
-  yield* isMenuPopulated(tab1);
-
-  const window2 = yield openWindow();
-  assert.pass("window is ready");
-
-  const tab2 = yield openTab(`data:text/html,<h1>hello window-2</h1>`, window2);
-  assert.pass("tab is ready");
-
-  yield* isMenuPopulated(tab2);
-
-  item.destroy();
-
-  yield* isMenuEmpty(tab2);
-  yield closeWindow(window2);
-
-  yield* isMenuEmpty(tab1);
-
-  yield closeTab(tab1);
-};
-*/
-
-
-// Multilpe items can be created and destroyed at different points
-// in time & they should not affect each other.
-exports["test multiple items"] = withTab(function*(assert) {
-  const item1 = new Item({ label: "one" });
-
-  const step1 = yield captureContextMenu("h1");
-  assert.deepEqual(step1,
-                   menugroup(menuseparator(),
-                             menuitem({label: "one"})),
-                   "item1 is present");
-
-  const item2 = new Item({ label: "two" });
-  const step2 = yield captureContextMenu("h1");
-
-  assert.deepEqual(step2,
-                   menugroup(menuseparator(),
-                             menuitem({label: "one"}),
-                             menuitem({label: "two"})),
-                   "both items where present");
-
-  item1.destroy();
-
-  const step3 = yield captureContextMenu("h1");
-  assert.deepEqual(step3,
-                   menugroup(menuseparator(),
-                             menuitem({label: "two"})),
-                   "one items left");
-
-  item2.destroy();
-
-  const step4 = yield captureContextMenu("h1");
-  assert.deepEqual(step4, menugroup(), "no items left");
-}, data`<h1>Multiple Items</h1>`);
-
-// Destroying an item twice should not cause an error.
-exports["test destroy twice"] = withTab(function*(assert) {
-  const item = new Item({ label: "destroy" });
-  const withItem = yield captureContextMenu("h2");
-  assert.deepEqual(withItem,
-                   menugroup(menuseparator(),
-                             menuitem({label:"destroy"})),
-                   "Item is added");
-
-  item.destroy();
-
-  const withoutItem = yield captureContextMenu("h2");
-  assert.deepEqual(withoutItem, menugroup(), "Item was removed");
-
-  item.destroy();
-  assert.pass("Destroying an item twice should not cause an error.");
-}, "data:text/html,<h2>item destroy</h2>");
-
-// CSS selector contexts should cause their items to be absent from the menu
-// when the menu is not invoked on nodes that match selectors.
-exports["test selector context"] = withTab(function*(assert) {
-  const item = new Item({
-    context: [new Contexts.Selector("body b")],
-    label: "bold"
-  });
-
-  const match = yield captureContextMenu("b");
-  assert.deepEqual(match,
-                   menugroup(menuseparator(),
-                             menuitem({label: "bold"})),
-                   "item mathched context");
-
-  const noMatch = yield captureContextMenu("i");
-  assert.deepEqual(noMatch, menugroup(), "item did not match context");
-
-  item.destroy();
-
-  const cleared = yield captureContextMenu("b");
-  assert.deepEqual(cleared, menugroup(), "item was removed");
-}, data`<body><i>one</i><b>two</b></body>`);
-
-// CSS selector contexts should cause their items to be absent in the menu
-// when the menu is invoked even on nodes that have ancestors that match the
-// selectors.
-exports["test parent selector don't match children"] = withTab(function*(assert) {
-  const item = new Item({
-    label: "parent match",
-    context: [new Contexts.Selector("a[href]")]
-  });
-
-  const match = yield captureContextMenu("a");
-  assert.deepEqual(match,
-                   menugroup(menuseparator(),
-                             menuitem({label: "parent match"})),
-                   "item mathched context");
-
-  const noMatch = yield captureContextMenu("strong");
-  assert.deepEqual(noMatch, menugroup(), "item did not mathch context");
-
-  item.destroy();
-
-  const destroyed = yield captureContextMenu("a");
-  assert.deepEqual(destroyed, menugroup(), "no items left");
-}, data`<a href='/foo'>This text must be long & <strong>bold!</strong></a>`);
-
-// Page contexts should cause their items to be present in the menu when the
-// menu is not invoked on an active element.
-exports["test page context match"] = withTab(function*(assert) {
-  const isPageMatch = (tree, description="page context matched") =>
-    assert.deepEqual(tree,
-                     menugroup(menuseparator(),
-                               menuitem({label: "page match"}),
-                               menuitem({label: "any match"})),
-                     description);
-
-  const isntPageMatch = (tree, description="page context did not match") =>
-    assert.deepEqual(tree,
-                     menugroup(menuseparator(),
-                               menuitem({label: "any match"})),
-                    description);
-
-  yield* withItems({
-    pageMatch: new Item({
-      label: "page match",
-      context: [new Contexts.Page()],
-    }),
-    anyMatch: new Item({
-      label: "any match"
-    })
-  }, function*({pageMatch, anyMatch}) {
-    for (let tagName of [null, "p", "h3"]) {
-      isPageMatch((yield captureContextMenu(tagName)),
-                  `Page context matches ${tagName} passive element`);
-    }
-
-    for (let tagName of ["button", "canvas", "img", "input", "textarea",
-                         "select", "menu", "embed" ,"object", "video", "audio",
-                         "applet"])
-    {
-      isntPageMatch((yield captureContextMenu(tagName)),
-                    `Page context does not match <${tagName}/> active element`);
-    }
-
-    for (let selector of ["span"])
-    {
-      isntPageMatch((yield captureContextMenu(selector)),
-                    `Page context does not match decedents of active element`);
-    }
-  });
-},
-data`<head>
-  <style>
-    p, object, embed { display: inline-block; }
-  </style>
-</head>
-<body>
-  <div><p>paragraph</p></div>
-  <div><a href=./link><span>link</span></a></div>
-  <h3>hi</h3>
-  <div><button>button</button></div>
-  <div><canvas height=10 /></div>
-  <div><img height=10 width=10 /></div>
-  <div><input value=input /></div>
-  <div><textarea>text</textarea></div>
-  <div><select><option>one</option><option>two</option></select></div>
-  <div><menu><button>item</button></menu></div>
-  <div><object width=10 height=10><param name=foo value=bar /></object></div>
-  <div><embed width=10 height=10/></div>
-  <div><video width=10 height=10 controls /></div>
-  <div><audio width=10 height=10 controls /></div>
-  <div><applet width=10 height=10 /></div>
-</body>`);
-
-// Page context does not match if if there is a selection.
-exports["test page context doesn't match on selection"] = withTab(function*(assert) {
-  const isPageMatch = (tree, description="page context matched") =>
-    assert.deepEqual(tree,
-                     menugroup(menuseparator(),
-                               menuitem({label: "page match"}),
-                               menuitem({label: "any match"})),
-                     description);
-
-  const isntPageMatch = (tree, description="page context did not match") =>
-    assert.deepEqual(tree,
-                     menugroup(menuseparator(),
-                               menuitem({label: "any match"})),
-                    description);
-
-  yield* withItems({
-    pageMatch: new Item({
-      label: "page match",
-      context: [new Contexts.Page()],
-    }),
-    anyMatch: new Item({
-      label: "any match"
-    })
-  }, function*({pageMatch, anyMatch}) {
-    yield select("b");
-    isntPageMatch((yield captureContextMenu("i")),
-                  "page context does not match if there is a selection");
-
-    yield select(null);
-    isPageMatch((yield captureContextMenu("i")),
-                "page context match if there is no selection");
-  });
-}, data`<body><i>one</i><b>two</b></body>`);
-
-exports["test selection context"] = withTab(function*(assert) {
-  yield* withItems({
-    item: new Item({
-      label: "selection",
-      context: [new Contexts.Selection()]
-    })
-  }, function*({item}) {
-    assert.deepEqual((yield captureContextMenu()),
-                     menugroup(),
-                     "item does not match if there is no selection");
-
-    yield select("b");
-
-    assert.deepEqual((yield captureContextMenu()),
-                     menugroup(menuseparator(),
-                               menuitem({label: "selection"})),
-                     "item matches if there is a selection");
-  });
-}, data`<i>one</i><b>two</b>`);
-
-exports["test selection context in textarea"] = withTab(function*(assert) {
-  yield* withItems({
-    item: new Item({
-      label: "selection",
-      context: [new Contexts.Selection()]
-    })
-  }, function*({item}) {
-    assert.deepEqual((yield captureContextMenu()),
-                     menugroup(),
-                     "does not match if there's no selection");
-
-    yield select({target:"textarea", start:0, end:5});
-
-    assert.deepEqual((yield captureContextMenu("b")),
-                 menugroup(),
-                 "does not match if target isn't input with selection");
-
-    assert.deepEqual((yield captureContextMenu("textarea")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "selection"})),
-                     "matches if target is input with selected text");
-
-    yield select({target: "textarea", start: 0, end: 0});
-
-    assert.deepEqual((yield captureContextMenu("textarea")),
-                 menugroup(),
-                 "does not match when selection is cleared");
-  });
-}, data`<textarea>Hello World</textarea><b>!!</b>`);
-
-exports["test url contexts"] = withTab(function*(assert) {
-  yield* withItems({
-    a: new Item({
-      label: "a",
-      context: [new Contexts.URL(testPageURI)]
-    }),
-    b: new Item({
-      label: "b",
-      context: [new Contexts.URL("*.bogus.com")]
-    }),
-    c: new Item({
-      label: "c",
-      context: [new Contexts.URL("*.bogus.com"),
-                new Contexts.URL(testPageURI)]
-    }),
-    d: new Item({
-      label: "d",
-      context: [new Contexts.URL(/.*\.html/)]
-    }),
-    e: new Item({
-      label: "e",
-      context: [new Contexts.URL("http://*"),
-                new Contexts.URL(testPageURI)]
-    }),
-    f: new Item({
-      label: "f",
-      context: [new Contexts.URL("http://*").required,
-                new Contexts.URL(testPageURI)]
-    }),
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu()),
-                     menugroup(menuseparator(),
-                               menuitem({label: "a"}),
-                               menuitem({label: "c"}),
-                               menuitem({label: "d"}),
-                               menuitem({label: "e"})),
-                     "shows only matching items");
-  });
-}, testPageURI);
-
-exports["test iframe context"] = withTab(function*(assert) {
-  yield* withItems({
-    page: new Item({
-      label: "page",
-      context: [new Contexts.Page()]
-    }),
-    iframe: new Item({
-      label: "iframe",
-      context: [new Contexts.Frame()]
-    }),
-    h2: new Item({
-      label: "element",
-      context: [new Contexts.Selector("*")]
-    })
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("iframe")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "page"}),
-                               menuitem({label: "iframe"}),
-                               menuitem({label: "element"})),
-                     "matching items are present");
-
-    assert.deepEqual((yield captureContextMenu("h1")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "page"}),
-                               menuitem({label: "element"})),
-                     "only matching items are present");
-
-  });
-
-},
-data`<h1>hello</h1>
-<iframe src='data:text/html,<body>Bye</body>' />`);
-
-exports["test link context"] = withTab(function*(assert) {
-  yield* withItems({
-    item: new Item({
-      label: "link",
-      context: [new Contexts.Link()]
-    })
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("h1")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "link"})),
-                     "matches anchor child");
-
-    assert.deepEqual((yield captureContextMenu("i")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "link"})),
-                     "matches anchor decedent");
-    assert.deepEqual((yield captureContextMenu("h2")),
-                     menugroup(),
-                     "does not match if not under anchor");
-  });
-}, data`<a href="/link"><h1>Hello <i>World</i></h1></a><h2>miss</h2>`);
-
-
-exports["test editable context"] = withTab(function*(assert) {
-  const isntEditable = function*(selector) {
-    assert.deepEqual((yield captureContextMenu(selector)),
-                     menugroup(),
-                     `${selector} isn't editable`);
-  };
-
-  const isEditable = function*(selector) {
-    assert.deepEqual((yield captureContextMenu(selector)),
-                     menugroup(menuseparator(),
-                               menuitem({label: "editable"})),
-                     `${selector} is editable`);
-  };
-
-  yield* withItems({
-    item: new Item({
-      label: "editable",
-      context: [new Contexts.Editable()]
-    })
-  }, function*(_) {
-    yield* isntEditable("h1");
-    yield* isEditable("input[id=text]");
-    yield* isntEditable("input[disabled=true]");
-    yield* isntEditable("input[readonly=true]");
-    yield* isntEditable("input[type=submit]");
-    yield* isntEditable("input[type=radio]");
-    yield* isntEditable("input[type=checkbox]");
-    yield* isEditable("input[type=foo]");
-    yield* isEditable("textarea");
-    yield* isEditable("[contenteditable=true]");
-  });
-}, data`<body>
-<h1>examles</h1>
-<pre contenteditable="true">This content is editable.</pre>
-<input type="text" readonly="true" value="readonly value">
-<input type="text" disabled="true" value="disabled value">
-<input type="text" id=text value="test value">
-<input type="submit" />
-<input type="radio" />
-<input type="foo" />
-<input type="checkbox" />
-<textarea>A text field,
-with some text.</textarea>
-</body>`);
-
-exports["test image context"] = withTab(function*(assert) {
-  yield withItems({
-    item: new Item({
-      label: "image",
-      context: [new Contexts.Image()]
-    })
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("img")),
-                     menugroup(menuseparator(), menuitem({label: "image"})),
-                     `<img/> matches image context`);
-
-    assert.deepEqual((yield captureContextMenu("p image")),
-                     menugroup(),
-                     `<image/> does not image context`);
-
-    assert.deepEqual((yield captureContextMenu("svg image")),
-                     menugroup(menuseparator(), menuitem({label: "image"})),
-                     `<svg:image/> matches image context`);
-  });
-}, data`<body>
-<p><image style="width: 50px; height: 50px" /></p>
-<img src='' />
-<div>
-<svg xmlns="http://www.w3.org/2000/svg"
-     xmlns:xlink= "http://www.w3.org/1999/xlink">
-  <image x="0" y="0" height="50px" width="50px" xlink:href=""/>
-</svg>
-<div>
-</body>`);
-
-
-exports["test audiot & video contexts"] = withTab(function*(assert) {
-  yield withItems({
-    audio: new Item({
-      label: "audio",
-      context: [new Contexts.Audio()]
-    }),
-    video: new Item({
-      label: "video",
-      context: [new Contexts.Video()]
-    }),
-    media: new Item({
-      label: "media",
-      context: [new Contexts.Audio(),
-                new Contexts.Video()]
-    })
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("img")),
-                     menugroup(),
-                     `<img/> does not match video or audio context`);
-
-    assert.deepEqual((yield captureContextMenu("audio")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "audio"}),
-                               menuitem({label: "media"})),
-                     `<audio/> matches audio context`);
-
-    assert.deepEqual((yield captureContextMenu("video")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "video"}),
-                               menuitem({label: "media"})),
-                     `<video/> matches video context`);
-  })
-}, data`<body>
-<div><video width=10 height=10 controls /></div>
-<div><audio width=10 height=10 controls /></div>
-<div><image style="width: 50px; height: 50px" /></div>
-</body>`);
-
-const predicateTestURL = data`<html>
-  <head>
-    <style>
-      p, object, embed { display: inline-block; }
-    </style>
-  </head>
-  <body>
-    <strong><p>paragraph</p></strong>
-    <p><a href=./link><span>link</span></a></p>
-    <p><h3>hi</h3></p>
-    <p><button>button</button></p>
-    <p><canvas height=50 width=50 /></p>
-    <p><img height=50 width=50 src="./no.png" /></p>
-    <p><code contenteditable="true">This content is editable.</code></p>
-    <p><input type="text" readonly="true" value="readonly value"></p>
-    <p><input type="text" disabled="true" value="disabled value"></p>
-    <p><input type="text" id=text value="test value" /></p>
-    <p><input type="submit" /></p>
-    <p><input type="radio" /></p>
-    <p><input type="foo" /></p>
-    <p><input type="checkbox" /></p>
-    <p><textarea>A text field,
-    with some text.</textarea></p>
-    <p><iframe src='data:text/html,<body style="height:100%">Bye</body>'></iframe></p>
-    <p><select><option>one</option><option>two</option></select></p>
-    <p><menu><button>item</button></menu></p>
-    <p><object width=10 height=10><param name=foo value=bar /></object></p>
-    <p><embed width=10 height=10/></p>
-    <p><video width=50 height=50 controls /></p>
-    <p><audio width=10 height=10 controls /></p>
-    <p><applet width=30 height=30 /></p>
-  </body>
-</html>`;
-exports["test predicate context"] = withTab(function*(assert) {
-  const test = function*(selector, expect) {
-    var isMatch = false;
-    test.return = (target) => {
-      return isMatch = expect(target);
-    }
-    assert.deepEqual((yield captureContextMenu(selector)),
-                     isMatch ? menugroup(menuseparator(),
-                                         menuitem({label:"predicate"})) :
-                               menugroup(),
-                     isMatch ? `predicate item matches ${selector}` :
-                     `predicate item doesn't match ${selector}`);
-  };
-  test.predicate = target => test.return(target);
-
-  yield* withItems({
-    item: new Item({
-      label: "predicate",
-      read: {
-        mediaType: new Readers.MediaType(),
-        link: new Readers.LinkURL(),
-        isPage: new Readers.isPage(),
-        isFrame: new Readers.isFrame(),
-        isEditable: new Readers.isEditable(),
-        tagName: new Readers.Query("tagName"),
-        appCodeName: new Readers.Query("ownerDocument.defaultView.navigator.appCodeName"),
-        width: new Readers.Attribute("width"),
-        src: new Readers.SrcURL(),
-        url: new Readers.PageURL(),
-        selection: new Readers.Selection()
-      },
-      context: [Contexts.Predicate(test.predicate)]
-    })
-  }, function*(items) {
-    yield* test("strong p", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: true,
-        isFrame: false,
-        isEditable: false,
-        tagName: "P",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "pagraph read test");
-      return true;
-    });
-
-    yield* test("a span", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: "./link",
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "SPAN",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "video tag test");
-      return false;
-    });
-
-    yield* test("h3", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: true,
-        isFrame: false,
-        isEditable: false,
-        tagName: "H3",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "video tag test");
-      return false;
-    });
-
-    yield select("h3");
-
-    yield* test("a span", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: "./link",
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "SPAN",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: "hi",
-      }, "test selection with link");
-      return true;
-    });
-
-    yield select(null);
-
-
-    yield* test("button", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "BUTTON",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test button");
-      return true;
-    });
-
-    yield* test("canvas", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "CANVAS",
-        appCodeName: "Mozilla",
-        width: "50",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test button");
-      return true;
-    });
-
-    yield* test("img", target => {
-      assert.deepEqual(target, {
-        mediaType: "image",
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "IMG",
-        appCodeName: "Mozilla",
-        width: "50",
-        src: "./no.png",
-        url: predicateTestURL,
-        selection: null,
-      }, "test image");
-      return true;
-    });
-
-    yield* test("code", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: true,
-        tagName: "CODE",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test content editable");
-      return false;
-    });
-
-    yield* test("input[readonly=true]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test readonly input");
-      return false;
-    });
-
-    yield* test("input[disabled=true]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test disabled input");
-      return false;
-    });
-
-    yield select({target: "input#text", start: 0, end: 5 });
-
-    yield* test("input#text", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: true,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: "test ",
-      }, "test editable input");
-      return false;
-    });
-
-    yield select({target: "input#text", start:0, end: 0});
-
-    yield* test("input[type=submit]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test submit input");
-      return false;
-    });
-
-    yield* test("input[type=radio]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test radio input");
-      return false;
-    });
-
-    yield* test("input[type=checkbox]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test checkbox input");
-      return false;
-    });
-
-    yield* test("input[type=foo]", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: true,
-        tagName: "INPUT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test unrecognized input");
-      return false;
-    });
-
-    yield* test("textarea", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: true,
-        tagName: "TEXTAREA",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test textarea");
-      return false;
-    });
-
-
-    yield* test("iframe", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: true,
-        isFrame: true,
-        isEditable: false,
-        tagName: "BODY",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: `data:text/html,<body%20style="height:100%">Bye</body>`,
-        selection: null,
-      }, "test iframe");
-      return true;
-    });
-
-    yield* test("select", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "SELECT",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test select");
-      return true;
-    });
-
-    yield* test("menu", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "MENU",
-        appCodeName: "Mozilla",
-        width: null,
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test menu");
-      return false;
-    });
-
-    yield* test("video", target => {
-      assert.deepEqual(target, {
-        mediaType: "video",
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "VIDEO",
-        appCodeName: "Mozilla",
-        width: "50",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test video");
-      return true;
-    });
-
-    yield* test("audio", target => {
-      assert.deepEqual(target, {
-        mediaType: "audio",
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "AUDIO",
-        appCodeName: "Mozilla",
-        width: "10",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test audio");
-      return true;
-    });
-
-    yield* test("object", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "OBJECT",
-        appCodeName: "Mozilla",
-        width: "10",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test object");
-      return true;
-    });
-
-    yield* test("embed", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "EMBED",
-        appCodeName: "Mozilla",
-        width: "10",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test embed");
-      return true;
-    });
-
-    yield* test("applet", target => {
-      assert.deepEqual(target, {
-        mediaType: null,
-        link: null,
-        isPage: false,
-        isFrame: false,
-        isEditable: false,
-        tagName: "APPLET",
-        appCodeName: "Mozilla",
-        width: "30",
-        src: null,
-        url: predicateTestURL,
-        selection: null,
-      }, "test applet");
-      return false;
-    });
-
-  });
-}, predicateTestURL);
-
-exports["test extractor reader"] = withTab(function*(assert) {
-  const test = function*(selector, expect) {
-    var isMatch = false;
-    test.return = (target) => {
-      return isMatch = expect(target);
-    }
-    assert.deepEqual((yield captureContextMenu(selector)),
-                     isMatch ? menugroup(menuseparator(),
-                                         menuitem({label:"extractor"})) :
-                               menugroup(),
-                     isMatch ? `predicate item matches ${selector}` :
-                     `predicate item doesn't match ${selector}`);
-  };
-  test.predicate = target => test.return(target);
-
-
-  yield* withItems({
-    item: new Item({
-      label: "extractor",
-      context: [Contexts.Predicate(test.predicate)],
-      read: {
-        tagName: Readers.Query("tagName"),
-        selector: Readers.Extractor(target => {
-          let node = target;
-          let path = [];
-          while (node) {
-            if (node.id) {
-              path.unshift(`#${node.id}`);
-              node = null;
-            }
-            else {
-              path.unshift(node.localName);
-              node = node.parentElement;
-            }
-          }
-          return path.join(" > ");
-        })
-      }
-    })
-  }, function*(_) {
-    yield* test("footer", target => {
-      assert.deepEqual(target, {
-        tagName: "FOOTER",
-        selector: "html > body > nav > footer"
-      }, "test footer");
-      return false;
-    });
-
-
-  });
-}, data`<html>
-  <body>
-    <nav>
-      <header>begin</header>
-      <footer>end</footer>
-    </nav>
-    <article data-index=1>
-      <header>First title</header>
-      <div>
-        <p>First paragraph</p>
-        <p>Second paragraph</p>
-      </div>
-    </article>
-    <article data-index=2>
-      <header>Second title</header>
-      <div>
-        <p>First <strong id=foo>paragraph</strong></p>
-        <p>Second paragraph</p>
-      </div>
-    </article>
-  </body>
-</html>`);
-
-exports["test items overflow"] = withTab(function*(assert) {
-  yield* withItems({
-    i1: new Item({label: "item-1"}),
-    i2: new Item({label: "item-2"}),
-    i3: new Item({label: "item-3"}),
-    i4: new Item({label: "item-4"}),
-    i5: new Item({label: "item-5"}),
-    i6: new Item({label: "item-6"}),
-    i7: new Item({label: "item-7"}),
-    i8: new Item({label: "item-8"}),
-    i9: new Item({label: "item-9"}),
-    i10: new Item({label: "item-10"}),
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("p")),
-                     menugroup(menu({
-                                className: "sdk-context-menu-overflow-menu",
-                                label: "Add-ons",
-                                accesskey: "A",
-                              }, menuitem({label: "item-1"}),
-                                 menuitem({label: "item-2"}),
-                                 menuitem({label: "item-3"}),
-                                 menuitem({label: "item-4"}),
-                                 menuitem({label: "item-5"}),
-                                 menuitem({label: "item-6"}),
-                                 menuitem({label: "item-7"}),
-                                 menuitem({label: "item-8"}),
-                                 menuitem({label: "item-9"}),
-                                 menuitem({label: "item-10"}))),
-                     "context menu has an overflow");
-  });
-
-  prefs.set("extensions.addon-sdk.context-menu.overflowThreshold", 3);
-
-  yield* withItems({
-    i1: new Item({label: "item-1"}),
-    i2: new Item({label: "item-2"}),
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("p")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "item-1"}),
-                               menuitem({label: "item-2"})),
-                     "two items do not overflow");
-  });
-
-  yield* withItems({
-    one: new Item({label: "one"}),
-    two: new Item({label: "two"}),
-    three: new Item({label: "three"})
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("p")),
-                     menugroup(menu({className: "sdk-context-menu-overflow-menu",
-                                     label: "Add-ons",
-                                     accesskey: "A"},
-                                     menuitem({label: "one"}),
-                                     menuitem({label: "two"}),
-                                     menuitem({label: "three"}))),
-                     "three items overflow");
-  });
-
-  prefs.reset("extensions.addon-sdk.context-menu.overflowThreshold");
-
-  yield* withItems({
-    one: new Item({label: "one"}),
-    two: new Item({label: "two"}),
-    three: new Item({label: "three"})
-  }, function*(_) {
-    assert.deepEqual((yield captureContextMenu("p")),
-                     menugroup(menuseparator(),
-                               menuitem({label: "one"}),
-                               menuitem({label: "two"}),
-                               menuitem({label: "three"})),
-                     "three items no longer overflow");
-  });
-}, data`<p>Hello</p>`);
-
-
-exports["test context menus"] = withTab(function*(assert) {
-  const one = new Item({
-    label: "one",
-    context: [Contexts.Selector("p")],
-    read: {tagName: Readers.Query("tagName")}
-  });
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                    menugroup(menuseparator(),
-                              menuitem({label: "one"})),
-                    "item is present");
-
-  const two = new Item({
-    label: "two",
-    read: {tagName: Readers.Query("tagName")}
-  });
-
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                   menugroup(menuseparator(),
-                             menuitem({label: "one"}),
-                             menuitem({label: "two"})),
-                   "both items are present");
-
-  const groupLevel1 = new Menu({label: "Level 1"},
-                          [one]);
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                   menugroup(menuseparator(),
-                             menuitem({label: "two"}),
-                             menu({label: "Level 1"},
-                                  menuitem({label: "one"}))),
-                   "first item moved to group");
-
-  assert.deepEqual((yield captureContextMenu("h1")),
-                   menugroup(menuseparator(),
-                             menuitem({label: "two"})),
-                   "menu is hidden since only item does not match");
-
-
-  const groupLevel2 = new Menu({label: "Level 2" }, [groupLevel1]);
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                   menugroup(menuseparator(),
-                             menuitem({label: "two"}),
-                             menu({label: "Level 2"},
-                                  menu({label: "Level 1"},
-                                       menuitem({label: "one"})))),
-                   "top level menu moved to submenu");
-
-  assert.deepEqual((yield captureContextMenu("h1")),
-                   menugroup(menuseparator(),
-                             menuitem({label: "two"})),
-                   "menu is hidden since only item does not match");
-
-
-  const contextGroup = new Menu({
-    label: "H1 Group",
-    context: [Contexts.Selector("h1")]
-  }, [
-    two,
-    new Separator(),
-    new Item({ label: "three" })
-  ]);
-
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                   menugroup(menuseparator(),
-                             menu({label: "Level 2"},
-                                  menu({label: "Level 1"},
-                                       menuitem({label: "one"})))),
-                   "nested menu is rendered");
-
-  assert.deepEqual((yield captureContextMenu("h1")),
-                   menugroup(menuseparator(),
-                             menu({label: "H1 Group"},
-                                  menuitem({label: "two"}),
-                                  menuseparator(),
-                                  menuitem({label: "three"}))),
-                   "new contextual menu rendered");
-
-  yield* withItems({one, two,
-                    groupLevel1, groupLevel2, contextGroup}, function*() {
-
-  });
-
-  assert.deepEqual((yield captureContextMenu("p")),
-                   menugroup(),
-                   "everyhing matching p was desposed");
-
-  assert.deepEqual((yield captureContextMenu("h1")),
-                 menugroup(),
-                 "everyhing matching h1 was desposed");
-
-}, data`<body><h1>Title</h1><p>Content</p></body>`);
-
-exports["test unloading"] = withTab(function*(assert) {
-  const { Loader } = require("sdk/test/loader");
-  const loader = Loader(module);
-
-  const {Item, Menu, Separator, Contexts, Readers } = loader.require("sdk/context-menu@2");
-
-  const item = new Item({label: "item"});
-  const group = new Menu({label: "menu"},
-                         [new Separator(),
-                          new Item({label: "sub-item"})]);
-  assert.deepEqual((yield captureContextMenu()),
-                   menugroup(menuseparator(),
-                             menuitem({label: "item"}),
-                             menu({label: "menu"},
-                                  menuseparator(),
-                                  menuitem({label: "sub-item"}))),
-                   "all items rendered");
-
-
-  loader.unload();
-
-  assert.deepEqual((yield captureContextMenu()),
-                 menugroup(),
-                 "all items disposed");
-}, data`<body></body>`);
-
-if (require("@loader/options").isNative) {
-  module.exports = {
-    "test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
-  };
-}
-
-before(exports, (name, assert) => {
-  // Make sure Java doesn't activate
-  prefs.set("plugin.state.java", 0);
-});
-
-after(exports, (name, assert) => {
-  prefs.reset("plugin.state.java");
-});
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-cuddlefish.js
+++ /dev/null
@@ -1,78 +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, CC, Cr, Cm, ChromeWorker, components } = require("chrome");
-
-const packaging = require("@loader/options");
-const app = require('sdk/system/xul-app');
-const { resolve } = require;
-
-const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
-
-function loadSandbox(uri) {
-  let proto = {
-    sandboxPrototype: {
-      loadSandbox: loadSandbox,
-      ChromeWorker: ChromeWorker
-    }
-  };
-  let sandbox = Cu.Sandbox(systemPrincipal, proto);
-  // Create a fake commonjs environnement just to enable loading loader.js
-  // correctly
-  sandbox.exports = {};
-  sandbox.module = { uri: uri, exports: sandbox.exports };
-  sandbox.require = function (id) {
-    if (id !== "chrome")
-      throw new Error("Bootstrap sandbox `require` method isn't implemented.");
-
-    return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
-      CC: CC, components: components,
-      ChromeWorker: ChromeWorker });
-  };
-  scriptLoader.loadSubScript(uri, sandbox, 'UTF-8');
-  return sandbox;
-}
-
-exports['test loader'] = function(assert) {
-  let { Loader, Require, unload, override } = loadSandbox(resolve('sdk/loader/cuddlefish.js')).exports;
-  var prints = [];
-  function print(message) {
-    prints.push(message);
-  }
-
-  let loader = Loader(override(packaging, {
-    globals: {
-      print: print,
-      foo: 1
-    }
-  }));
-  let require = Require(loader, module);
-
-  var fixture = require('./loader/fixture');
-
-  assert.equal(fixture.foo, 1, 'custom globals must work.');
-  assert.equal(fixture.bar, 2, 'exports are set');
-
-  assert.equal(prints[0], 'testing', 'global print must be injected.');
-
-  var unloadsCalled = '';
-
-  require("sdk/system/unload").when(function(reason) {
-    assert.equal(reason, 'test', 'unload reason is passed');
-    unloadsCalled += 'a';
-  });
-  require('sdk/system/unload.js').when(function() {
-    unloadsCalled += 'b';
-  });
-
-  unload(loader, 'test');
-
-  assert.equal(unloadsCalled, 'ba',
-               'loader.unload() must call listeners in LIFO order.');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-deprecate.js
+++ /dev/null
@@ -1,160 +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 deprecate = require("sdk/util/deprecate");
-const { LoaderWithHookedConsole } = require("sdk/test/loader");
-const { get, set } = require("sdk/preferences/service");
-const PREFERENCE = "devtools.errorconsole.deprecation_warnings";
-
-exports["test Deprecate Usage"] = function testDeprecateUsage(assert) {
-  set(PREFERENCE, true);
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let deprecate = loader.require("sdk/util/deprecate");
-
-  function functionIsDeprecated() {
-    deprecate.deprecateUsage("foo");
-  }
-
-  functionIsDeprecated();
-
-  assert.equal(messages.length, 1, "only one error is dispatched");
-  assert.equal(messages[0].type, "error", "the console message is an error");
-
-  let msg = messages[0].msg;
-
-  assert.ok(msg.indexOf("foo") !== -1,
-            "message contains the given message");
-  assert.ok(msg.indexOf("functionIsDeprecated") !== -1,
-            "message contains name of the caller function");
-  assert.ok(msg.indexOf(module.uri) !== -1,
-             "message contains URI of the caller module");
-
-  loader.unload();
-}
-
-exports["test Deprecate Function"] = function testDeprecateFunction(assert) {
-  set(PREFERENCE, true);
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let deprecate = loader.require("sdk/util/deprecate");
-
-  let self = {};
-  let arg1 = "foo";
-  let arg2 = {};
-
-  function originalFunction(a1, a2) {
-    assert.equal(this, self);
-    assert.equal(a1, arg1);
-    assert.equal(a2, arg2);
-  };
-
-  let deprecateFunction = deprecate.deprecateFunction(originalFunction,
-                                                       "bar");
-
-  deprecateFunction.call(self, arg1, arg2);
-
-  assert.equal(messages.length, 1, "only one error is dispatched");
-  assert.equal(messages[0].type, "error", "the console message is an error");
-
-  let msg = messages[0].msg;
-  assert.ok(msg.indexOf("bar") !== -1, "message contains the given message");
-  assert.ok(msg.indexOf("testDeprecateFunction") !== -1,
-            "message contains name of the caller function");
-  assert.ok(msg.indexOf(module.uri) !== -1,
-            "message contains URI of the caller module");
-
-  loader.unload();
-}
-
-exports.testDeprecateEvent = function(assert, done) {
-  set(PREFERENCE, true);
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let deprecate = loader.require("sdk/util/deprecate");
-
-  let { on, emit } = loader.require('sdk/event/core');
-  let testObj = {};
-  testObj.on = deprecate.deprecateEvent(on.bind(null, testObj), 'BAD', ['fire']);
-
-  testObj.on('fire', function() {
-    testObj.on('water', function() {
-      assert.equal(messages.length, 1, "only one error is dispatched");
-      loader.unload();
-      done();
-    })
-    assert.equal(messages.length, 1, "only one error is dispatched");
-    emit(testObj, 'water');
-  });
-
-  assert.equal(messages.length, 1, "only one error is dispatched");
-  assert.equal(messages[0].type, "error", "the console message is an error");
-  let msg = messages[0].msg;
-  assert.ok(msg.indexOf("BAD") !== -1, "message contains the given message");
-  assert.ok(msg.indexOf("deprecateEvent") !== -1,
-            "message contains name of the caller function");
-  assert.ok(msg.indexOf(module.uri) !== -1,
-            "message contains URI of the caller module");
-
-  emit(testObj, 'fire');
-}
-
-exports.testDeprecateSettingToggle = function (assert) {
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let deprecate = loader.require("sdk/util/deprecate");
-
-  function fn () { deprecate.deprecateUsage("foo"); }
-
-  set(PREFERENCE, false);
-  fn();
-  assert.equal(messages.length, 0, 'no deprecation warnings');
-
-  set(PREFERENCE, true);
-  fn();
-  assert.equal(messages.length, 1, 'deprecation warnings when toggled');
-
-  set(PREFERENCE, false);
-  fn();
-  assert.equal(messages.length, 1, 'no new deprecation warnings');
-};
-
-exports.testDeprecateSetting = function (assert, done) {
-  // Set devtools.errorconsole.deprecation_warnings to false
-  set(PREFERENCE, false);
-
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let deprecate = loader.require("sdk/util/deprecate");
-
-  // deprecateUsage test
-  function functionIsDeprecated() {
-    deprecate.deprecateUsage("foo");
-  }
-  functionIsDeprecated();
-
-  assert.equal(messages.length, 0,
-    "no errors dispatched on deprecateUsage");
-
-  // deprecateFunction test
-  function originalFunction() {};
-
-  let deprecateFunction = deprecate.deprecateFunction(originalFunction,
-                                                       "bar");
-  deprecateFunction();
-
-  assert.equal(messages.length, 0,
-    "no errors dispatched on deprecateFunction");
-
-  // deprecateEvent
-  let { on, emit } = loader.require('sdk/event/core');
-  let testObj = {};
-  testObj.on = deprecate.deprecateEvent(on.bind(null, testObj), 'BAD', ['fire']);
-
-  testObj.on('fire', () => {
-    assert.equal(messages.length, 0,
-      "no errors dispatched on deprecateEvent");
-    done();
-  });
-
-  emit(testObj, 'fire');
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-dev-panel.js
+++ /dev/null
@@ -1,428 +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 = {
-  "engines": {
-    "Firefox": "*"
-  }
-};
-
-const { Tool } = require("dev/toolbox");
-const { Panel } = require("dev/panel");
-const { Class } = require("sdk/core/heritage");
-const { openToolbox, closeToolbox, getCurrentPanel } = require("dev/utils");
-const { MessageChannel } = require("sdk/messaging");
-const { when } = require("sdk/dom/events-shimmed");
-const { viewFor } = require("sdk/view/core");
-const { createView } = require("dev/panel/view");
-
-const iconURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAADqmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6M0ExNEY4NjZBNkU1MTFFMTlGMkFGQ0QyNTUyN0VDRjY8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6M0ExNEY4NjNBNkU1MTFFMTlGMkFGQ0QyNTUyN0VDRjY8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6M0ExNEY4NjRBNkU1MTFFMTlGMkFGQ0QyNTUyN0VDRjY8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6M0ExNEY4NjVBNkU1MTFFMTlGMkFGQ0QyNTUyN0VDRjY8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+QWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2g8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ChetDDYAAACaSURBVEgNY2AYboAR3UNnzpx5DxQTQBP/YGJiIogmBuYSq54Ji2Z0S0BKsInBtGKTwxDDZhHMAKrSdLOIqq7GZxjj+fPnBf7+/bseqMgBn0IK5A4wMzMHMtHYEpD7HEB2gOLIAcSjMXCgW2IYtYjsqBwNutGgg4fAaGKABwWpDLoG3QFSXUeG+gNMoEoJqJGWloErPjIcR54WALqPHeiJgl15AAAAAElFTkSuQmCC";
-const makeHTML = fn =>
-  "data:text/html;charset=utf-8,<script>(" + fn + ")();</script>";
-
-
-const test = function(unit) {
-  return function*(assert) {
-    assert.isRendered = (panel, toolbox) => {
-      const doc = toolbox.doc;
-      assert.ok(Array.from(doc.querySelectorAll(".devtools-tab"))
-                     .find(el => el.textContent === panel.label),
-                "panel.label is found in the developer toolbox DOM " + panel.label);
-      if (panel.tooltip) {
-        assert.ok(doc.querySelector("[title='" + panel.tooltip + "']"),
-                  `panel.tooltip is found in the developer toolbox DOM "${panel.tooltip}"`);
-      }
-      assert.ok(doc.querySelector("#toolbox-panel-" + panel.id),
-                "toolbar panel with a matching id is present");
-    };
-
-
-    yield* unit(assert);
-  };
-};
-
-exports["test Panel API"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "test panel",
-    tooltip: "my test panel",
-    icon: iconURI,
-    url: makeHTML(() => {
-      document.documentElement.innerHTML = "hello world";
-    }),
-    setup: function({debuggee}) {
-      this.debuggee = debuggee;
-      assert.equal(this.readyState, "uninitialized",
-                   "at construction time panel document is not inited");
-    },
-    dispose: function() {
-      delete this.debuggee;
-    }
-  });
-  assert.ok(MyPanel, "panel is defined");
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-  assert.ok(myTool, "tool is defined");
-
-
-  var toolbox = yield openToolbox(MyPanel);
-  var panel = yield getCurrentPanel(toolbox);
-  assert.ok(panel instanceof MyPanel, "is instance of MyPanel");
-
-  assert.isRendered(panel, toolbox);
-
-  if (panel.readyState === "uninitialized") {
-    yield panel.ready();
-    assert.equal(panel.readyState, "interactive", "panel is ready");
-  }
-
-  yield panel.loaded();
-  assert.equal(panel.readyState, "complete", "panel is loaded");
-
-  yield closeToolbox();
-
-  assert.equal(panel.readyState, "destroyed", "panel is destroyed");
-
-  myTool.destroy();
-});
-
-exports["test forbid remote https docs"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "test https panel",
-    tooltip: "my test panel",
-    icon: iconURI,
-    url: "https://mozilla.org",
-  });
-
-  assert.throws(() => {
-    new Tool({ panels: { myPanel: MyPanel } });
-  },
-  /The `options.url` must be a valid local URI/,
-  "can't use panel with remote URI");
-});
-
-exports["test forbid remote http docs"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "test http panel",
-    tooltip: "my test panel",
-    icon: iconURI,
-    url: "http://arewefastyet.com/",
-  });
-
-  assert.throws(() => {
-    new Tool({ panels: { myPanel: MyPanel } });
-  },
-  /The `options.url` must be a valid local URI/,
-  "can't use panel with remote URI");
-});
-
-exports["test forbid remote ftp docs"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "test ftp panel",
-    tooltip: "my test panel",
-    icon: iconURI,
-    url: "ftp://ftp.mozilla.org/",
-  });
-
-  assert.throws(() => {
-    new Tool({ panels: { myPanel: MyPanel } });
-  },
-  /The `options.url` must be a valid local URI/,
-  "can't use panel with remote URI");
-});
-
-
-exports["test Panel communication"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "communication",
-    tooltip: "test palen communication",
-    icon: iconURI,
-    url: makeHTML(() => {
-      window.addEventListener("message", event => {
-        if (event.source === window) {
-          var port = event.ports[0];
-          port.start();
-          port.postMessage("ping");
-          port.onmessage = (event) => {
-            if (event.data === "pong") {
-              port.postMessage("bye");
-              port.close();
-            }
-          };
-        }
-      });
-    }),
-    dispose: function() {
-      delete this.port;
-    }
-  });
-
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-
-
-  const toolbox = yield openToolbox(MyPanel);
-  const panel = yield getCurrentPanel(toolbox);
-  assert.ok(panel instanceof MyPanel, "is instance of MyPanel");
-
-  assert.isRendered(panel, toolbox);
-
-  yield panel.ready();
-  const { port1, port2 } = new MessageChannel();
-  panel.port = port1;
-  panel.postMessage("connect", [port2]);
-  panel.port.start();
-
-  const ping = yield when(panel.port, "message");
-
-  assert.equal(ping.data, "ping", "received ping from panel doc");
-
-  panel.port.postMessage("pong");
-
-  const bye = yield when(panel.port, "message");
-
-  assert.equal(bye.data, "bye", "received bye from panel doc");
-
-  panel.port.close();
-
-  yield closeToolbox();
-
-  assert.equal(panel.readyState, "destroyed", "panel is destroyed");
-  myTool.destroy();
-});
-
-exports["test communication with debuggee"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "debuggee",
-    tooltip: "test debuggee",
-    icon: iconURI,
-    url: makeHTML(() => {
-      window.addEventListener("message", event => {
-        if (event.source === window) {
-          var debuggee = event.ports[0];
-          var port = event.ports[1];
-          debuggee.start();
-          port.start();
-
-
-          debuggee.onmessage = (event) => {
-            port.postMessage(event.data);
-          };
-          port.onmessage = (event) => {
-            debuggee.postMessage(event.data);
-          };
-        }
-      });
-    }),
-    setup: function({debuggee}) {
-      this.debuggee = debuggee;
-    },
-    onReady: function() {
-      const { port1, port2 } = new MessageChannel();
-      this.port = port1;
-      this.port.start();
-      this.debuggee.start();
-
-      this.postMessage("connect", [this.debuggee, port2]);
-    },
-    dispose: function() {
-      this.port.close();
-      this.debuggee.close();
-
-      delete this.port;
-      delete this.debuggee;
-    }
-  });
-
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-
-
-  const toolbox = yield openToolbox(MyPanel);
-  const panel = yield getCurrentPanel(toolbox);
-  assert.ok(panel instanceof MyPanel, "is instance of MyPanel");
-
-  assert.isRendered(panel, toolbox);
-
-  yield panel.ready();
-  const intro = yield when(panel.port, "message");
-
-  assert.equal(intro.data.from, "root", "intro message from root");
-
-  panel.port.postMessage({
-    to: "root",
-    type: "echo",
-    text: "ping"
-  });
-
-  const pong = yield when(panel.port, "message");
-
-  assert.deepEqual(pong.data, {
-    to: "root",
-    from: "root",
-    type: "echo",
-    text: "ping"
-  }, "received message back from root");
-
-  yield closeToolbox();
-
-  assert.equal(panel.readyState, "destroyed", "panel is destroyed");
-
-  myTool.destroy();
-});
-
-
-exports["test viewFor panel"] = test(function*(assert) {
-  const url = "data:text/html;charset=utf-8,viewFor";
-  const MyPanel = Class({
-    extends: Panel,
-    label: "view for panel",
-    tooltip: "my panel view",
-    icon: iconURI,
-    url: url
-  });
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-
-
-  const toolbox = yield openToolbox(MyPanel);
-  const panel = yield getCurrentPanel(toolbox);
-  assert.ok(panel instanceof MyPanel, "is instance of MyPanel");
-
-  const frame = viewFor(panel);
-
-  assert.equal(frame.nodeName.toLowerCase(), "iframe",
-               "viewFor(panel) returns associated iframe");
-
-  yield panel.loaded();
-
-  assert.equal(frame.contentDocument.URL, url, "is expected iframe");
-
-  yield closeToolbox();
-
-  myTool.destroy();
-});
-
-
-exports["test createView panel"] = test(function*(assert) {
-  var frame = null;
-  var panel = null;
-
-  const url = "data:text/html;charset=utf-8,createView";
-  const id = Math.random().toString(16).substr(2);
-  const MyPanel = Class({
-    extends: Panel,
-    label: "create view",
-    tooltip: "panel creator",
-    icon: iconURI,
-    url: url
-  });
-
-  createView.define(MyPanel, (instance, document) => {
-    var view = document.createElement("iframe");
-    view.setAttribute("type", "content");
-
-    // save instances for later asserts
-    frame = view;
-    panel = instance;
-
-    return view;
-  });
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-
-  const toolbox = yield openToolbox(MyPanel);
-  const myPanel = yield getCurrentPanel(toolbox);
-
-  assert.equal(myPanel, panel,
-               "panel passed to createView is one instantiated");
-  assert.equal(viewFor(panel), frame,
-               "createView has created an iframe");
-
-  yield panel.loaded();
-
-  assert.equal(frame.contentDocument.URL, url, "is expected iframe");
-
-  yield closeToolbox();
-
-  myTool.destroy();
-});
-
-
-exports["test ports is an optional"] = test(function*(assert) {
-  const MyPanel = Class({
-    extends: Panel,
-    label: "no-port",
-    icon: iconURI,
-    url: makeHTML(() => {
-      window.addEventListener("message", event => {
-        if (event.ports.length) {
-          event.ports[0].postMessage(window.firstPacket);
-        } else {
-          window.firstPacket = event.data;
-        }
-      });
-    })
-  });
-
-
-  const myTool = new Tool({
-    panels: {
-      myPanel: MyPanel
-    }
-  });
-
-
-  const toolbox = yield openToolbox(MyPanel);
-  const panel = yield getCurrentPanel(toolbox);
-  assert.ok(panel instanceof MyPanel, "is instance of MyPanel");
-
-  assert.isRendered(panel, toolbox);
-
-  yield panel.ready();
-
-  const { port1, port2 } = new MessageChannel();
-  port1.start();
-
-  panel.postMessage("hi");
-  panel.postMessage("bye", [port2]);
-
-  const packet = yield when(port1, "message");
-
-  assert.equal(packet.data, "hi", "got first packet back");
-
-  yield closeToolbox();
-
-  assert.equal(panel.readyState, "destroyed", "panel is destroyed");
-
-  myTool.destroy();
-});
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-diffpatcher.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-exports["test diffpatcher"] = require("diffpatcher/test/index");
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-dispatcher.js
+++ /dev/null
@@ -1,76 +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 { dispatcher } = require("sdk/util/dispatcher");
-
-exports["test dispatcher API"] = assert => {
-  const dispatch = dispatcher();
-
-  assert.equal(typeof(dispatch), "function",
-               "dispatch is a function");
-
-  assert.equal(typeof(dispatch.define), "function",
-               "dispatch.define is a function");
-
-  assert.equal(typeof(dispatch.implement), "function",
-               "dispatch.implement is a function");
-
-  assert.equal(typeof(dispatch.when), "function",
-               "dispatch.when is a function");
-};
-
-exports["test dispatcher"] = assert => {
-  const isDuck = dispatcher();
-
-  const quacks = x => x && typeof(x.quack) === "function";
-
-  const Duck = function() {};
-  const Goose = function() {};
-
-  const True = _ => true;
-  const False = _ => false;
-
-
-
-  isDuck.define(Goose, False);
-  isDuck.define(Duck, True);
-  isDuck.when(quacks, True);
-
-  assert.equal(isDuck(new Goose()), false,
-               "Goose ain't duck");
-
-  assert.equal(isDuck(new Duck()), true,
-               "Ducks are ducks");
-
-  assert.equal(isDuck({ quack: () => "Quaaaaaack!" }), true,
-               "It's a duck if it quacks");
-
-
-  assert.throws(() => isDuck({}), /Type does not implements method/, "not implemneted");
-
-  isDuck.define(Object, False);
-
-  assert.equal(isDuck({}), false,
-               "Ain't duck if it does not quacks!");
-};
-
-exports["test redefining fails"] = assert => {
-  const isPM = dispatcher();
-  const isAfternoon = time => time.getHours() > 12;
-
-  isPM.when(isAfternoon, _ => true);
-
-  assert.equal(isPM(new Date(Date.parse("Jan 23, 1985, 13:20:00"))), true,
-               "yeap afternoon");
-  assert.equal(isPM({ getHours: _ => 17 }), true,
-                "seems like afternoon");
-
-  assert.throws(() => isPM.when(isAfternoon, x => x > 12 && x < 24),
-                /Already implemented for the given predicate/,
-               "can't redefine on same predicate");
-
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-disposable.js
+++ /dev/null
@@ -1,393 +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 { Loader } = require("sdk/test/loader");
-const { Class } = require("sdk/core/heritage");
-const { Disposable } = require("sdk/core/disposable");
-const { Cc, Ci, Cu } = require("chrome");
-const { setTimeout } = require("sdk/timers");
-
-exports["test disposeDisposable"] = assert => {
-  let loader = Loader(module);
-
-  const { Disposable, disposeDisposable } = loader.require("sdk/core/disposable");
-  const { isWeak, WeakReference } = loader.require("sdk/core/reference");
-
-  let disposals = 0;
-
-  const Foo = Class({
-    extends: Disposable,
-    implements: [WeakReference],
-    dispose(...params) {
-      disposeDisposable(this);
-      disposals = disposals + 1;
-    }
-  });
-
-  const f1 = new Foo();
-  assert.equal(isWeak(f1), true, "f1 has WeakReference support");
-
-  f1.dispose();
-  assert.equal(disposals, 1, "disposed on dispose");
-
-  loader.unload("uninstall");
-  assert.equal(disposals, 1, "after disposeDisposable, dispose is not called anymore");
-};
-
-exports["test destroy reasons"] = assert => {
-  let disposals = 0;
-
-  const Foo = Class({
-    extends: Disposable,
-    dispose: function() {
-      disposals = disposals + 1;
-    }
-  });
-
-  const f1 = new Foo();
-
-  f1.destroy();
-  assert.equal(disposals, 1, "disposed on destroy");
-  f1.destroy();
-  assert.equal(disposals, 1, "second destroy is ignored");
-
-  disposals = 0;
-  const f2 = new Foo();
-
-  f2.destroy("uninstall");
-  assert.equal(disposals, 1, "uninstall invokes disposal");
-  f2.destroy("uninstall")
-  f2.destroy();
-  assert.equal(disposals, 1, "disposal happens just once");
-
-  disposals = 0;
-  const f3 = new Foo();
-
-  f3.destroy("shutdown");
-  assert.equal(disposals, 0, "shutdown invoke disposal");
-  f3.destroy("shutdown");
-  f3.destroy();
-  assert.equal(disposals, 0, "shutdown disposal happens just once");
-
-  disposals = 0;
-  const f4 = new Foo();
-
-  f4.destroy("disable");
-  assert.equal(disposals, 1, "disable invokes disposal");
-  f4.destroy("disable")
-  f4.destroy();
-  assert.equal(disposals, 1, "destroy happens just once");
-
-  disposals = 0;
-  const f5 = new Foo();
-
-  f5.destroy("disable");
-  assert.equal(disposals, 1, "disable invokes disposal");
-  f5.destroy("disable")
-  f5.destroy();
-  assert.equal(disposals, 1, "destroy happens just once");
-
-  disposals = 0;
-  const f6 = new Foo();
-
-  f6.destroy("upgrade");
-  assert.equal(disposals, 1, "upgrade invokes disposal");
-  f6.destroy("upgrade")
-  f6.destroy();
-  assert.equal(disposals, 1, "destroy happens just once");
-
-  disposals = 0;
-  const f7 = new Foo();
-
-  f7.destroy("downgrade");
-  assert.equal(disposals, 1, "downgrade invokes disposal");
-  f7.destroy("downgrade")
-  f7.destroy();
-  assert.equal(disposals, 1, "destroy happens just once");
-
-
-  disposals = 0;
-  const f8 = new Foo();
-
-  f8.destroy("whatever");
-  assert.equal(disposals, 1, "unrecognized reason invokes disposal");
-  f8.destroy("meh")
-  f8.destroy();
-  assert.equal(disposals, 1, "destroy happens just once");
-};
-
-exports["test different unload hooks"] = assert => {
-  const { uninstall, shutdown, disable, upgrade,
-          downgrade, dispose } = require("sdk/core/disposable");
-  const UberUnload = Class({
-    extends: Disposable,
-    setup: function() {
-      this.log = [];
-    }
-  });
-
-  uninstall.define(UberUnload, x => x.log.push("uninstall"));
-  shutdown.define(UberUnload, x => x.log.push("shutdown"));
-  disable.define(UberUnload, x => x.log.push("disable"));
-  upgrade.define(UberUnload, x => x.log.push("upgrade"));
-  downgrade.define(UberUnload, x => x.log.push("downgrade"));
-  dispose.define(UberUnload, x => x.log.push("dispose"));
-
-  const u1 = new UberUnload();
-  u1.destroy("uninstall");
-  u1.destroy();
-  u1.destroy("shutdown");
-  assert.deepEqual(u1.log, ["uninstall"], "uninstall hook invoked");
-
-  const u2 = new UberUnload();
-  u2.destroy("shutdown");
-  u2.destroy();
-  u2.destroy("uninstall");
-  assert.deepEqual(u2.log, ["shutdown"], "shutdown hook invoked");
-
-  const u3 = new UberUnload();
-  u3.destroy("disable");
-  u3.destroy();
-  u3.destroy("uninstall");
-  assert.deepEqual(u3.log, ["disable"], "disable hook invoked");
-
-  const u4 = new UberUnload();
-  u4.destroy("upgrade");
-  u4.destroy();
-  u4.destroy("uninstall");
-  assert.deepEqual(u4.log, ["upgrade"], "upgrade hook invoked");
-
-  const u5 = new UberUnload();
-  u5.destroy("downgrade");
-  u5.destroy();
-  u5.destroy("uninstall");
-  assert.deepEqual(u5.log, ["downgrade"], "downgrade hook invoked");
-
-  const u6 = new UberUnload();
-  u6.destroy();
-  u6.destroy();
-  u6.destroy("uninstall");
-  assert.deepEqual(u6.log, ["dispose"], "dispose hook invoked");
-
-  const u7 = new UberUnload();
-  u7.destroy("whatever");
-  u7.destroy();
-  u7.destroy("uninstall");
-  assert.deepEqual(u7.log, ["dispose"], "dispose hook invoked");
-};
-
-exports["test disposables are disposed on unload"] = function(assert) {
-  let loader = Loader(module);
-  let { Disposable } = loader.require("sdk/core/disposable");
-
-  let arg1 = {}
-  let arg2 = 2
-  let disposals = 0
-
-  let Foo = Class({
-    extends: Disposable,
-    setup: function setup(a, b) {
-      assert.equal(a, arg1,
-                   "arguments passed to constructur is passed to setup");
-      assert.equal(b, arg2,
-                   "second argument is also passed to a setup");
-      assert.ok(this instanceof Foo,
-                "this is an instance in the scope of the setup method");
-
-      this.fooed = true
-    },
-    dispose: function dispose() {
-      assert.equal(this.fooed, true, "attribute was set")
-      this.fooed = false
-      disposals = disposals + 1
-    }
-  })
-
-  let foo1 = Foo(arg1, arg2)
-  let foo2 = Foo(arg1, arg2)
-
-  loader.unload();
-
-  assert.equal(disposals, 2, "both instances were disposed")
-}
-
-exports["test destroyed windows dispose before unload"] = function(assert) {
-  let loader = Loader(module);
-  let { Disposable } = loader.require("sdk/core/disposable");
-
-  let arg1 = {}
-  let arg2 = 2
-  let disposals = 0
-
-  let Foo = Class({
-    extends: Disposable,
-    setup: function setup(a, b) {
-      assert.equal(a, arg1,
-                   "arguments passed to constructur is passed to setup");
-      assert.equal(b, arg2,
-                   "second argument is also passed to a setup");
-      assert.ok(this instanceof Foo,
-                "this is an instance in the scope of the setup method");
-
-      this.fooed = true
-    },
-    dispose: function dispose() {
-      assert.equal(this.fooed, true, "attribute was set")
-      this.fooed = false
-      disposals = disposals + 1
-    }
-  })
-
-  let foo1 = Foo(arg1, arg2)
-  let foo2 = Foo(arg1, arg2)
-
-  foo1.destroy();
-  assert.equal(disposals, 1, "destroy disposes instance")
-
-  loader.unload();
-
-  assert.equal(disposals, 2, "unload disposes alive instances")
-}
-
-exports["test disposables are GC-able"] = function(assert, done) {
-  let loader = Loader(module);
-  let { Disposable } = loader.require("sdk/core/disposable");
-  let { WeakReference } = loader.require("sdk/core/reference");
-
-  let arg1 = {}
-  let arg2 = 2
-  let disposals = 0
-
-  let Foo = Class({
-    extends: Disposable,
-    implements: [WeakReference],
-    setup: function setup(a, b) {
-      assert.equal(a, arg1,
-                   "arguments passed to constructur is passed to setup");
-      assert.equal(b, arg2,
-                   "second argument is also passed to a setup");
-      assert.ok(this instanceof Foo,
-                "this is an instance in the scope of the setup method");
-
-      this.fooed = true
-    },
-    dispose: function dispose() {
-      assert.equal(this.fooed, true, "attribute was set")
-      this.fooed = false
-      disposals = disposals + 1
-    }
-  });
-
-  let foo1 = Foo(arg1, arg2)
-  let foo2 = Foo(arg1, arg2)
-
-  foo1 = foo2 = null;
-
-  Cu.schedulePreciseGC(function() {
-    loader.unload();
-    assert.equal(disposals, 0, "GC removed dispose listeners");
-    done();
-  });
-}
-
-
-exports["test loader unloads do not affect other loaders"] = function(assert) {
-  let loader1 = Loader(module);
-  let loader2 = Loader(module);
-  let { Disposable: Disposable1 } = loader1.require("sdk/core/disposable");
-  let { Disposable: Disposable2 } = loader2.require("sdk/core/disposable");
-
-  let arg1 = {}
-  let arg2 = 2
-  let disposals = 0
-
-  let Foo1 = Class({
-    extends: Disposable1,
-    dispose: function dispose() {
-      disposals = disposals + 1;
-    }
-  });
-
-  let Foo2 = Class({
-    extends: Disposable2,
-    dispose: function dispose() {
-      disposals = disposals + 1;
-    }
-  });
-
-  let foo1 = Foo1(arg1, arg2);
-  let foo2 = Foo2(arg1, arg2);
-
-  assert.equal(disposals, 0, "no destroy calls");
-
-  loader1.unload();
-
-  assert.equal(disposals, 1, "1 destroy calls");
-
-  loader2.unload();
-
-  assert.equal(disposals, 2, "2 destroy calls");
-}
-
-exports["test disposables that throw"] = function(assert) {
-  let loader = Loader(module);
-  let { Disposable } = loader.require("sdk/core/disposable");
-
-  let disposals = 0
-
-  let Foo = Class({
-    extends: Disposable,
-    setup: function setup(a, b) {
-      throw Error("Boom!")
-    },
-    dispose: function dispose() {
-      disposals = disposals + 1
-    }
-  })
-
-  assert.throws(function() {
-    let foo1 = Foo()
-  }, /Boom/, "disposable constructors may throw");
-
-  loader.unload();
-
-  assert.equal(disposals, 0, "no disposal if constructor threw");
-}
-
-exports["test multiple destroy"] = function(assert) {
-  let loader = Loader(module);
-  let { Disposable } = loader.require("sdk/core/disposable");
-
-  let disposals = 0
-
-  let Foo = Class({
-    extends: Disposable,
-    dispose: function dispose() {
-      disposals = disposals + 1
-    }
-  })
-
-  let foo1 = Foo();
-  let foo2 = Foo();
-  let foo3 = Foo();
-
-  assert.equal(disposals, 0, "no disposals yet");
-
-  foo1.destroy();
-  assert.equal(disposals, 1, "disposed properly");
-  foo1.destroy();
-  assert.equal(disposals, 1, "didn't attempt to dispose twice");
-
-  foo2.destroy();
-  assert.equal(disposals, 2, "other instances still dispose fine");
-  foo2.destroy();
-  assert.equal(disposals, 2, "but not twice");
-
-  loader.unload();
-
-  assert.equal(disposals, 3, "unload only disposed the remaining instance");
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-dom.js
+++ /dev/null
@@ -1,88 +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 events = require("sdk/dom/events");
-const { activeBrowserWindow: { document } } = require("sdk/deprecated/window-utils");
-const window = document.window;
-/*
-exports["test on / emit"] = function (assert, done) {
-  let element = document.createElement("div");
-  events.on(element, "click", function listener(event) {
-    assert.equal(event.target, element, "event has correct target");
-    events.removeListener(element, "click", listener);
-    done();
-  });
-
-  events.emit(element, "click", {
-    category: "MouseEvents",
-    settings: [
-      true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
-    ]
-  });
-};
-
-exports["test remove"] = function (assert, done) {
-  let element = document.createElement("span");
-  let l1 = 0;
-  let l2 = 0;
-  let options = {
-    category: "MouseEvents",
-    settings: [
-      true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
-    ]
-  };
-
-  events.on(element, "click", function listener1(event) {
-    l1 ++;
-    assert.equal(event.target, element, "event has correct target");
-    events.removeListener(element, "click", listener1);
-  });
-
-  events.on(element, "click", function listener2(event) {
-    l2 ++;
-    if (l1 < l2) {
-      assert.equal(l1, 1, "firs listener was called and then romeved");
-      events.removeListener(element, "click", listener2);
-      done();
-    }
-    events.emit(element, "click", options);
-  });
-
-  events.emit(element, "click", options);
-};
-
-exports["test once"] = function (assert, done) {
-  let element = document.createElement("h1");
-  let l1 = 0;
-  let l2 = 0;
-  let options = {
-    category: "MouseEvents",
-    settings: [
-      true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
-    ]
-  };
-
-
-  events.once(element, "click", function listener(event) {
-    assert.equal(event.target, element, "event target is a correct element");
-    l1 ++;
-  });
-
-  events.on(element, "click", function listener(event) {
-    l2 ++;
-    if (l2 > 3) {
-      events.removeListener(element, "click", listener);
-      assert.equal(event.target, element, "event has correct target");
-      assert.equal(l1, 1, "once was called only once");
-      done();
-    }
-    events.emit(element, "click", options);
-  });
-
-  events.emit(element, "click", options);
-}
-*/
-require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-environment.js
+++ /dev/null
@@ -1,49 +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 { env } = require('sdk/system/environment');
-const { Cc, Ci } = require('chrome');
-const { get, set, exists } = Cc['@mozilla.org/process/environment;1'].
-                             getService(Ci.nsIEnvironment);
-
-exports['test exists'] = function(assert) {
-  assert.equal('PATH' in env, exists('PATH'),
-               'PATH environment variable is defined');
-  assert.equal('FOO1' in env, exists('FOO1'),
-               'FOO1 environment variable is not defined');
-  set('FOO1', 'foo');
-  assert.equal('FOO1' in env, true,
-               'FOO1 environment variable was set');
-  set('FOO1', null);
-  assert.equal('FOO1' in env, false,
-               'FOO1 environment variable was unset');
-};
-
-exports['test get'] = function(assert) {
-  assert.equal(env.PATH, get('PATH'), 'PATH env variable matches');
-  assert.equal(env.BAR2, undefined, 'BAR2 env variable is not defined');
-  set('BAR2', 'bar');
-  assert.equal(env.BAR2, 'bar', 'BAR2 env variable was set');
-  set('BAR2', null);
-  assert.equal(env.BAR2, undefined, 'BAR2 env variable was unset');
-};
-
-exports['test set'] = function(assert) {
-  assert.equal(get('BAZ3'), '', 'BAZ3 env variable is not set');
-  assert.equal(env.BAZ3, undefined, 'BAZ3 is not set');
-  env.BAZ3 = 'baz';
-  assert.equal(env.BAZ3, get('BAZ3'), 'BAZ3 env variable is set');
-  assert.equal(get('BAZ3'), 'baz', 'BAZ3 env variable was set to "baz"');
-};
-
-exports['test unset'] = function(assert) {
-  env.BLA4 = 'bla';
-  assert.equal(env.BLA4, 'bla', 'BLA4 env variable is set');
-  assert.equal(delete env.BLA4, true, 'BLA4 env variable is removed');
-  assert.equal(env.BLA4, undefined, 'BLA4 env variable is unset');
-  assert.equal('BLA4' in env, false, 'BLA4 env variable no longer exists' );
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-event-core.js
+++ /dev/null
@@ -1,347 +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 { on, once, off, emit, count } = require('sdk/event/core');
-const { LoaderWithHookedConsole } = require("sdk/test/loader");
-const { defer } = require("sdk/core/promise");
-const { gc } = require("sdk/test/memory");
-
-exports['test add a listener'] = function(assert) {
-  let events = [ { name: 'event#1' }, 'event#2' ];
-  let target = { name: 'target' };
-
-  on(target, 'message', function(message) {
-    assert.equal(this, target, 'this is a target object');
-    assert.equal(message, events.shift(), 'message is emitted event');
-  });
-  emit(target, 'message', events[0]);
-  emit(target, 'message', events[0]);
-};
-
-exports['test that listener is unique per type'] = function(assert) {
-  let actual = []
-  let target = {}
-  function listener() { actual.push(1) }
-  on(target, 'message', listener);
-  on(target, 'message', listener);
-  on(target, 'message', listener);
-  on(target, 'foo', listener);
-  on(target, 'foo', listener);
-
-  emit(target, 'message');
-  assert.deepEqual([ 1 ], actual, 'only one message listener added');
-  emit(target, 'foo');
-  assert.deepEqual([ 1, 1 ], actual, 'same listener added for other event');
-};
-
-exports['test event type matters'] = function(assert) {
-  let target = { name: 'target' }
-  on(target, 'message', function() {
-    assert.fail('no event is expected');
-  });
-  on(target, 'done', function() {
-    assert.pass('event is emitted');
-  });
-  emit(target, 'foo')
-  emit(target, 'done');
-};
-
-exports['test all arguments are pasesd'] = function(assert) {
-  let foo = { name: 'foo' }, bar = 'bar';
-  let target = { name: 'target' };
-  on(target, 'message', function(a, b) {
-    assert.equal(a, foo, 'first argument passed');
-    assert.equal(b, bar, 'second argument passed');
-  });
-  emit(target, 'message', foo, bar);
-};
-
-exports['test no side-effects in emit'] = function(assert) {
-  let target = { name: 'target' };
-  on(target, 'message', function() {
-    assert.pass('first listener is called');
-    on(target, 'message', function() {
-      assert.fail('second listener is called');
-    });
-  });
-  emit(target, 'message');
-};
-
-exports['test can remove next listener'] = function(assert) {
-  let target = { name: 'target' };
-  function fail() {
-    return assert.fail('Listener should be removed');
-  };
-
-  on(target, 'data', function() {
-    assert.pass('first litener called');
-    off(target, 'data', fail);
-  });
-  on(target, 'data', fail);
-
-  emit(target, 'data', 'hello');
-};
-
-exports['test order of propagation'] = function(assert) {
-  let actual = [];
-  let target = { name: 'target' };
-  on(target, 'message', function() { actual.push(1); });
-  on(target, 'message', function() { actual.push(2); });
-  on(target, 'message', function() { actual.push(3); });
-  emit(target, 'message');
-  assert.deepEqual([ 1, 2, 3 ], actual, 'called in order they were added');
-};
-
-exports['test remove a listener'] = function(assert) {
-  let target = { name: 'target' };
-  let actual = [];
-  on(target, 'message', function listener() {
-    actual.push(1);
-    on(target, 'message', function() {
-      off(target, 'message', listener);
-      actual.push(2);
-    })
-  });
-
-  emit(target, 'message');
-  assert.deepEqual([ 1 ], actual, 'first listener called');
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called');
-
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2, 2, 2 ], actual, 'first listener removed');
-};
-
-exports['test remove all listeners for type'] = function(assert) {
-  let actual = [];
-  let target = { name: 'target' }
-  on(target, 'message', function() { actual.push(1); });
-  on(target, 'message', function() { actual.push(2); });
-  on(target, 'message', function() { actual.push(3); });
-  on(target, 'bar', function() { actual.push('b') });
-  off(target, 'message');
-
-  emit(target, 'message');
-  emit(target, 'bar');
-
-  assert.deepEqual([ 'b' ], actual, 'all message listeners were removed');
-};
-
-exports['test remove all listeners'] = function(assert) {
-  let actual = [];
-  let target = { name: 'target' }
-  on(target, 'message', function() { actual.push(1); });
-  on(target, 'message', function() { actual.push(2); });
-  on(target, 'message', function() { actual.push(3); });
-  on(target, 'bar', function() { actual.push('b') });
-  off(target);
-
-  emit(target, 'message');
-  emit(target, 'bar');
-
-  assert.deepEqual([], actual, 'all listeners events were removed');
-};
-
-exports['test falsy arguments are fine'] = function(assert) {
-  let type, listener, actual = [];
-  let target = { name: 'target' }
-  on(target, 'bar', function() { actual.push(0) });
-
-  off(target, 'bar', listener);
-  emit(target, 'bar');
-  assert.deepEqual([ 0 ], actual, '3rd bad ard will keep listeners');
-
-  off(target, type);
-  emit(target, 'bar');
-  assert.deepEqual([ 0, 0 ], actual, '2nd bad arg will keep listener');
-
-  off(target, type, listener);
-  emit(target, 'bar');
-  assert.deepEqual([ 0, 0, 0 ], actual, '2nd&3rd bad args will keep listener');
-};
-
-exports['test error handling'] = function(assert) {
-  let target = Object.create(null);
-  let error = Error('boom!');
-
-  on(target, 'message', function() { throw error; })
-  on(target, 'error', function(boom) {
-    assert.equal(boom, error, 'thrown exception causes error event');
-  });
-  emit(target, 'message');
-};
-
-exports['test unhandled exceptions'] = function(assert) {
-  let exceptions = [];
-  let { loader, messages } = LoaderWithHookedConsole(module);
-
-  let { emit, on } = loader.require('sdk/event/core');
-  let target = {};
-  let boom = Error('Boom!');
-  let drax = Error('Draax!!');
-
-  on(target, 'message', function() { throw boom; });
-
-  emit(target, 'message');
-  assert.equal(messages.length, 1, 'Got the first exception');
-  assert.equal(messages[0].type, 'exception', 'The console message is exception');
-  assert.ok(~String(messages[0].msg).indexOf('Boom!'),
-            'unhandled exception is logged');
-
-  on(target, 'error', function() { throw drax; });
-  emit(target, 'message');
-  assert.equal(messages.length, 2, 'Got the second exception');
-  assert.equal(messages[1].type, 'exception', 'The console message is exception');
-  assert.ok(~String(messages[1].msg).indexOf('Draax!'),
-            'error in error handler is logged');
-};
-
-exports['test unhandled errors'] = function(assert) {
-  let exceptions = [];
-  let { loader, messages } = LoaderWithHookedConsole(module);
-
-  let { emit } = loader.require('sdk/event/core');
-  let target = {};
-  let boom = Error('Boom!');
-
-  emit(target, 'error', boom);
-  assert.equal(messages.length, 1, 'Error was logged');
-  assert.equal(messages[0].type, 'exception', 'The console message is exception');
-  assert.ok(~String(messages[0].msg).indexOf('Boom!'),
-            'unhandled exception is logged');
-};
-
-exports['test piped errors'] = function(assert) {
-  let exceptions = [];
-  let { loader, messages } = LoaderWithHookedConsole(module);
-
-  let { emit } = loader.require('sdk/event/core');
-  let { pipe } = loader.require('sdk/event/utils');
-  let target = {};
-  let second = {};
-
-  pipe(target, second);
-  emit(target, 'error', 'piped!');
-
-  assert.equal(messages.length, 1, 'error logged only once, ' +
-               'considered "handled" on `target` by the catch-all pipe');
-  assert.equal(messages[0].type, 'exception', 'The console message is exception');
-  assert.ok(~String(messages[0].msg).indexOf('piped!'),
-            'unhandled (piped) exception is logged on `second` target');
-};
-
-exports['test count'] = function(assert) {
-  let target = {};
-
-  assert.equal(count(target, 'foo'), 0, 'no listeners for "foo" events');
-  on(target, 'foo', function() {});
-  assert.equal(count(target, 'foo'), 1, 'listener registered');
-  on(target, 'foo', function() {}, 2, 'another listener registered');
-  off(target)
-  assert.equal(count(target, 'foo'), 0, 'listeners unregistered');
-};
-
-exports['test listen to all events'] = function(assert) {
-  let actual = [];
-  let target = {};
-
-  on(target, 'foo', message => actual.push(message));
-  on(target, '*', (type, ...message) => {
-    actual.push([type].concat(message));
-  });
-
-  emit(target, 'foo', 'hello');
-  assert.equal(actual[0], 'hello',
-    'non-wildcard listeners still work');
-  assert.deepEqual(actual[1], ['foo', 'hello'],
-    'wildcard listener called');
-
-  emit(target, 'bar', 'goodbye');
-  assert.deepEqual(actual[2], ['bar', 'goodbye'],
-    'wildcard listener called for unbound event name');
-};
-
-exports['test once'] = function*(assert, done) {
-  let target = {};
-  let called = false;
-  let { resolve, promise } = defer();
-
-  once(target, 'foo', function(value) {
-    assert.ok(!called, "listener called only once");
-    assert.equal(value, "bar", "correct argument was passed");
-  });
-  once(target, 'done', resolve);
-
-  emit(target, 'foo', 'bar');
-  emit(target, 'foo', 'baz');
-  emit(target, 'done', "");
-
-  yield promise;
-};
-
-exports['test once with gc'] = function*(assert) {
-  let target = {};
-  let called = false;
-  let { resolve, promise } = defer();
-
-  once(target, 'foo', function(value) {
-    assert.ok(!called, "listener called only once");
-    assert.equal(value, "bar", "correct argument was passed");
-  });
-  once(target, 'done', resolve);
-
-  yield gc();
-
-  emit(target, 'foo', 'bar');
-  emit(target, 'foo', 'baz');
-  emit(target, 'done', "");
-
-  yield promise;
-};
-
-exports["test removing once"] = function(assert, done) {
-  let target = {};
-
-  function test() {
-    assert.fail("listener was called");
-  }
-
-  once(target, "foo", test);
-  once(target, "done", done);
-
-  off(target, "foo", test);
-
-  assert.pass("emit foo");
-  emit(target, "foo", "bar");
-
-  assert.pass("emit done");
-  emit(target, "done", "");
-};
-
-exports["test removing once with gc"] = function*(assert) {
-  let target = {};
-  let { resolve, promise } = defer();
-
-  function test() {
-    assert.fail("listener was called");
-  }
-
-  once(target, "foo", test);
-  once(target, "done", resolve);
-
-  yield gc();
-
-  off(target, "foo", test);
-
-  assert.pass("emit foo");
-  emit(target, "foo", "bar");
-
-  assert.pass("emit done");
-  emit(target, "done", "");
-
-  yield promise;
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-event-dom.js
+++ /dev/null
@@ -1,92 +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 { openWindow, closeWindow } = require('./util');
-const { Loader } = require('sdk/test/loader');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { Cc, Ci } = require('chrome');
-const els = Cc["@mozilla.org/eventlistenerservice;1"].
-            getService(Ci.nsIEventListenerService);
-
-function countListeners(target, type) {
-  let listeners = els.getListenerInfoFor(target, {});
-  return listeners.filter(listener => listener.type == type).length;
-}
-
-exports['test window close clears listeners'] = function*(assert) {
-  let window = yield openWindow();
-  let loader = Loader(module);
-
-  // Any element will do here
-  let gBrowser = window.gBrowser;
-
-  // Other parts of the app may be listening for this
-  let windowListeners = countListeners(window, "DOMWindowClose");
-
-  // We can assume we're the only ones using the test events
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 0, "Should be no listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-
-  let { open } = loader.require('sdk/event/dom');
-
-  open(gBrowser, "TestEvent1");
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners + 1,
-               "Should have added a DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 1, "Should be a listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-
-  open(gBrowser, "TestEvent2");
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners + 1,
-               "Should not have added another DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 1, "Should be a listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 1, "Should be a listener for test event 2");
-
-  window = yield closeWindow(window);
-
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners,
-               "Should have removed a DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 0, "Should be no listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-
-  loader.unload();
-};
-
-exports['test unload clears listeners'] = function(assert) {
-  let window = getMostRecentBrowserWindow();
-  let loader = Loader(module);
-
-  // Any element will do here
-  let gBrowser = window.gBrowser;
-
-  // Other parts of the app may be listening for this
-  let windowListeners = countListeners(window, "DOMWindowClose");
-
-  // We can assume we're the only ones using the test events
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 0, "Should be no listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-
-  let { open } = loader.require('sdk/event/dom');
-
-  open(gBrowser, "TestEvent1");
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners + 1,
-               "Should have added a DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 1, "Should be a listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-
-  open(gBrowser, "TestEvent2");
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners + 1,
-               "Should not have added another DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 1, "Should be a listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 1, "Should be a listener for test event 2");
-
-  loader.unload();
-
-  assert.equal(countListeners(window, "DOMWindowClose"), windowListeners,
-               "Should have removed a DOMWindowClose listener");
-  assert.equal(countListeners(gBrowser, "TestEvent1"), 0, "Should be no listener for test event 1");
-  assert.equal(countListeners(gBrowser, "TestEvent2"), 0, "Should be no listener for test event 2");
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-event-target.js
+++ /dev/null
@@ -1,222 +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 { emit } = require('sdk/event/core');
-const { EventTarget } = require('sdk/event/target');
-const { Loader } = require('sdk/test/loader');
-
-exports['test add a listener'] = function(assert) {
-  let events = [ { name: 'event#1' }, 'event#2' ];
-  let target = EventTarget();
-
-  target.on('message', function(message) {
-    assert.equal(this, target, 'this is a target object');
-    assert.equal(message, events.shift(), 'message is emitted event');
-  });
-
-  emit(target, 'message', events[0]);
-  emit(target, 'message', events[0]);
-};
-
-exports['test pass in listeners'] = function(assert) {
-  let actual = [ ];
-  let target = EventTarget({
-    onMessage: function onMessage(message) {
-      assert.equal(this, target, 'this is an event target');
-      actual.push(1);
-    },
-    onFoo: null,
-    onbla: function() {
-      assert.fail('`onbla` is not supposed to be called');
-    }
-  });
-  target.on('message', function(message) {
-    assert.equal(this, target, 'this is an event target');
-    actual.push(2);
-  });
-
-  emit(target, 'message');
-  emit(target, 'missing');
-
-  assert.deepEqual([ 1, 2 ], actual, 'all listeners trigerred in right order');
-};
-
-exports['test that listener is unique per type'] = function(assert) {
-  let actual = []
-  let target = EventTarget();
-  function listener() { actual.push(1) }
-  target.on('message', listener);
-  target.on('message', listener);
-  target.on('message', listener);
-  target.on('foo', listener);
-  target.on('foo', listener);
-
-  emit(target, 'message');
-  assert.deepEqual([ 1 ], actual, 'only one message listener added');
-  emit(target, 'foo');
-  assert.deepEqual([ 1, 1 ], actual, 'same listener added for other event');
-};
-
-exports['test event type matters'] = function(assert) {
-  let target = EventTarget();
-  target.on('message', function() {
-    assert.fail('no event is expected');
-  });
-  target.on('done', function() {
-    assert.pass('event is emitted');
-  });
-
-  emit(target, 'foo');
-  emit(target, 'done');
-};
-
-exports['test all arguments are pasesd'] = function(assert) {
-  let foo = { name: 'foo' }, bar = 'bar';
-  let target = EventTarget();
-  target.on('message', function(a, b) {
-    assert.equal(a, foo, 'first argument passed');
-    assert.equal(b, bar, 'second argument passed');
-  });
-  emit(target, 'message', foo, bar);
-};
-
-exports['test no side-effects in emit'] = function(assert) {
-  let target = EventTarget();
-  target.on('message', function() {
-    assert.pass('first listener is called');
-    target.on('message', function() {
-      assert.fail('second listener is called');
-    });
-  });
-  emit(target, 'message');
-};
-
-exports['test order of propagation'] = function(assert) {
-  let actual = [];
-  let target = EventTarget();
-  target.on('message', function() { actual.push(1); });
-  target.on('message', function() { actual.push(2); });
-  target.on('message', function() { actual.push(3); });
-  emit(target, 'message');
-  assert.deepEqual([ 1, 2, 3 ], actual, 'called in order they were added');
-};
-
-exports['test remove a listener'] = function(assert) {
-  let target = EventTarget();
-  let actual = [];
-  target.on('message', function listener() {
-    actual.push(1);
-    target.on('message', function() {
-      target.removeListener('message', listener);
-      actual.push(2);
-    })
-  });
-
-  emit(target, 'message');
-  assert.deepEqual([ 1 ], actual, 'first listener called');
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called');
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2, 2, 2 ], actual, 'first listener removed');
-};
-
-exports['test .off() removes all listeners'] = function(assert) {
-  let target = EventTarget();
-  let actual = [];
-  target.on('message', function listener() {
-    actual.push(1);
-    target.on('message', function() {
-      target.removeListener('message', listener);
-      actual.push(2);
-    })
-  });
-
-  emit(target, 'message');
-  assert.deepEqual([ 1 ], actual, 'first listener called');
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called');
-  target.off();
-  emit(target, 'message');
-  assert.deepEqual([ 1, 1, 2 ], actual, 'target.off() removed all listeners');
-};
-
-exports['test error handling'] = function(assert) {
-  let target = EventTarget();
-  let error = Error('boom!');
-
-  target.on('message', function() { throw error; })
-  target.on('error', function(boom) {
-    assert.equal(boom, error, 'thrown exception causes error event');
-  });
-  emit(target, 'message');
-};
-
-exports['test unhandled errors'] = function(assert) {
-  let exceptions = [];
-  let loader = Loader(module);
-  let { emit } = loader.require('sdk/event/core');
-  let { EventTarget } = loader.require('sdk/event/target');
-  Object.defineProperties(loader.sandbox('sdk/event/core'), {
-    console: { value: {
-      exception: function(e) {
-        exceptions.push(e);
-      }
-    }}
-  });
-  let target = EventTarget();
-  let boom = Error('Boom!');
-  let drax = Error('Draax!!');
-
-  target.on('message', function() { throw boom; });
-
-  emit(target, 'message');
-  assert.ok(~String(exceptions[0]).indexOf('Boom!'),
-            'unhandled exception is logged');
-
-  target.on('error', function() { throw drax; });
-  emit(target, 'message');
-  assert.ok(~String(exceptions[1]).indexOf('Draax!'),
-            'error in error handler is logged');
-};
-
-exports['test target is chainable'] = function (assert, done) {
-  let loader = Loader(module);
-  let exceptions = [];
-  let { EventTarget } = loader.require('sdk/event/target');
-  let { emit } = loader.require('sdk/event/core');
-  Object.defineProperties(loader.sandbox('sdk/event/core'), {
-    console: { value: {
-      exception: function(e) {
-        exceptions.push(e);
-      }
-    }}
-  });
-
-  let emitter = EventTarget();
-  let boom = Error('Boom');
-  let onceCalled = 0;
-  
-  emitter.once('oneTime', function () {
-    assert.equal(++onceCalled, 1, 'once event called only once');
-  }).on('data', function (message) {
-    assert.equal(message, 'message', 'handles event');
-    emit(emitter, 'oneTime');
-    emit(emitter, 'data2', 'message2');
-  }).on('phony', function () {
-    assert.fail('removeListener does not remove chained event');
-  }).removeListener('phony')
-  .on('data2', function (message) {
-    assert.equal(message, 'message2', 'handle chained event');
-    emit(emitter, 'oneTime');
-    throw boom;
-  }).on('error', function (error) {
-    assert.equal(error, boom, 'error handled in chained event');
-    done();
-  });
-
-  emit(emitter, 'data', 'message');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-event-utils.js
+++ /dev/null
@@ -1,285 +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 { on, emit } = require("sdk/event/core");
-const { filter, map, merge, expand, pipe, stripListeners } = require("sdk/event/utils");
-const $ = require("./event/helpers");
-
-function isEven(x) {
-  return !(x % 2);
-}
-function inc(x) {
-  return x + 1;
-}
-
-exports["test filter events"] = function(assert) {
-  let input = {};
-  let evens = filter(input, isEven);
-  let actual = [];
-  on(evens, "data", e => actual.push(e));
-
-  [1, 2, 3, 4, 5, 6, 7].forEach(x => emit(input, "data", x));
-
-  assert.deepEqual(actual, [2, 4, 6], "only even numbers passed through");
-};
-
-exports["test filter emits"] = $.emits(function(input, assert) {
-  let output = filter(input, isEven);
-  assert(output,  [1, 2, 3, 4, 5], [2, 4], "this is `output` & evens passed");
-});;
-
-exports["test filter reg once"] = $.registerOnce(function(input, assert) {
-  assert(filter(input, isEven),  [1, 2, 3, 4, 5, 6], [2, 4, 6],
-         "listener can be registered only once");
-});
-
-exports["test filter ignores new"] = $.ignoreNew(function(input, assert) {
-  assert(filter(input, isEven), [1, 2, 3], [2],
-         "new listener is ignored")
-});
-
-exports["test filter is FIFO"] = $.FIFO(function(input, assert) {
-  assert(filter(input, isEven), [1, 2, 3, 4], [2, 4],
-         "listeners are invoked in fifo order")
-});
-
-exports["test map events"] = function(assert) {
-  let input = {};
-  let incs = map(input, inc);
-  let actual = [];
-  on(incs, "data", e => actual.push(e));
-
-  [1, 2, 3, 4].forEach(x => emit(input, "data", x));
-
-  assert.deepEqual(actual, [2, 3, 4, 5], "all numbers were incremented");
-};
-
-exports["test map emits"] = $.emits(function(input, assert) {
-  let output = map(input, inc);
-  assert(output,  [1, 2, 3], [2, 3, 4], "this is `output` & evens passed");
-});
-
-exports["test map reg once"] = $.registerOnce(function(input, assert) {
-  assert(map(input, inc),  [1, 2, 3], [2, 3, 4],
-         "listener can be registered only once");
-});
-
-exports["test map ignores new"] = $.ignoreNew(function(input, assert) {
-  assert(map(input, inc), [1], [2],
-         "new listener is ignored")
-});
-
-exports["test map is FIFO"] = $.FIFO(function(input, assert) {
-  assert(map(input, inc), [1, 2, 3, 4], [2, 3, 4, 5],
-         "listeners are invoked in fifo order")
-});
-
-exports["test merge stream[stream]"] = function(assert) {
-  let a = {}, b = {}, c = {};
-  let inputs = {};
-  let actual = [];
-
-  on(merge(inputs), "data", $ => actual.push($))
-
-  emit(inputs, "data", a);
-  emit(a, "data", "a1");
-  emit(inputs, "data", b);
-  emit(b, "data", "b1");
-  emit(a, "data", "a2");
-  emit(inputs, "data", c);
-  emit(c, "data", "c1");
-  emit(c, "data", "c2");
-  emit(b, "data", "b2");
-  emit(a, "data", "a3");
-
-  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
-                   "all inputs data merged into one");
-};
-
-exports["test merge array[stream]"] = function(assert) {
-  let a = {}, b = {}, c = {};
-  let inputs = {};
-  let actual = [];
-
-  on(merge([a, b, c]), "data", $ => actual.push($))
-
-  emit(a, "data", "a1");
-  emit(b, "data", "b1");
-  emit(a, "data", "a2");
-  emit(c, "data", "c1");
-  emit(c, "data", "c2");
-  emit(b, "data", "b2");
-  emit(a, "data", "a3");
-
-  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
-                   "all inputs data merged into one");
-};
-
-exports["test merge emits"] = $.emits(function(input, assert) {
-  let evens = filter(input, isEven)
-  let output = merge([evens, input]);
-  assert(output, [1, 2, 3], [1, 2, 2, 3], "this is `output` & evens passed");
-});
-
-
-exports["test merge reg once"] = $.registerOnce(function(input, assert) {
-  let evens = filter(input, isEven)
-  let output = merge([input, evens]);
-  assert(output,  [1, 2, 3, 4], [1, 2, 2, 3, 4, 4],
-         "listener can be registered only once");
-});
-
-exports["test merge ignores new"] = $.ignoreNew(function(input, assert) {
-  let evens = filter(input, isEven)
-  let output = merge([input, evens])
-  assert(output, [1], [1],
-         "new listener is ignored")
-});
-
-exports["test marge is FIFO"] = $.FIFO(function(input, assert) {
-  let evens = filter(input, isEven)
-  let output = merge([input, evens])
-
-  assert(output, [1, 2, 3, 4], [1, 2, 2, 3, 4, 4],
-         "listeners are invoked in fifo order")
-});
-
-exports["test expand"] = function(assert) {
-  let a = {}, b = {}, c = {};
-  let inputs = {};
-  let actual = [];
-
-  on(expand(inputs, $ => $()), "data", $ => actual.push($))
-
-  emit(inputs, "data", () => a);
-  emit(a, "data", "a1");
-  emit(inputs, "data", () => b);
-  emit(b, "data", "b1");
-  emit(a, "data", "a2");
-  emit(inputs, "data", () => c);
-  emit(c, "data", "c1");
-  emit(c, "data", "c2");
-  emit(b, "data", "b2");
-  emit(a, "data", "a3");
-
-  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
-                   "all inputs data merged into one");
-};
-
-exports["test pipe"] = function (assert, done) {
-  let src = {};
-  let dest = {};
-
-  let aneventCount = 0, multiargsCount = 0;
-  let wildcardCount = {};
-
-  on(dest, 'an-event', arg => {
-    assert.equal(arg, 'my-arg', 'piped argument to event');
-    ++aneventCount;
-    check();
-  });
-  on(dest, 'multiargs', (...data) => {
-    assert.equal(data[0], 'a', 'multiple arguments passed via pipe');
-    assert.equal(data[1], 'b', 'multiple arguments passed via pipe');
-    assert.equal(data[2], 'c', 'multiple arguments passed via pipe');
-    ++multiargsCount;
-    check();
-  });
-
-  on(dest, '*', (name, ...data) => {
-    wildcardCount[name] = (wildcardCount[name] || 0) + 1;
-    if (name === 'multiargs') {
-      assert.equal(data[0], 'a', 'multiple arguments passed via pipe, wildcard');
-      assert.equal(data[1], 'b', 'multiple arguments passed via pipe, wildcard');
-      assert.equal(data[2], 'c', 'multiple arguments passed via pipe, wildcard');
-    }
-    if (name === 'an-event')
-      assert.equal(data[0], 'my-arg', 'argument passed via pipe, wildcard');
-    check();
-  });
-
-  pipe(src, dest);
-
-  for (let i = 0; i < 3; i++)
-    emit(src, 'an-event', 'my-arg');
-
-  emit(src, 'multiargs', 'a', 'b', 'c');
-
-  function check () {
-    if (aneventCount === 3 && multiargsCount === 1 &&
-        wildcardCount['an-event'] === 3 &&
-        wildcardCount['multiargs'] === 1)
-      done();
-  }
-};
-
-exports["test pipe multiple targets"] = function (assert) {
-  let src1 = {};
-  let src2 = {};
-  let middle = {};
-  let dest = {};
-
-  pipe(src1, middle);
-  pipe(src2, middle);
-  pipe(middle, dest);
-
-  let middleFired = 0;
-  let destFired = 0;
-  let src1Fired = 0;
-  let src2Fired = 0;
-
-  on(src1, '*', () => src1Fired++);
-  on(src2, '*', () => src2Fired++);
-  on(middle, '*', () => middleFired++);
-  on(dest, '*', () => destFired++);
-
-  emit(src1, 'ev');
-  assert.equal(src1Fired, 1, 'event triggers in source in pipe chain');
-  assert.equal(middleFired, 1, 'event passes through the middle of pipe chain');
-  assert.equal(destFired, 1, 'event propagates to end of pipe chain');
-  assert.equal(src2Fired, 0, 'event does not fire on alternative chain routes');
-
-  emit(src2, 'ev');
-  assert.equal(src2Fired, 1, 'event triggers in source in pipe chain');
-  assert.equal(middleFired, 2,
-    'event passes through the middle of pipe chain from different src');
-  assert.equal(destFired, 2,
-    'event propagates to end of pipe chain from different src');
-  assert.equal(src1Fired, 1, 'event does not fire on alternative chain routes');
-
-  emit(middle, 'ev');
-  assert.equal(middleFired, 3,
-    'event triggers in source of pipe chain');
-  assert.equal(destFired, 3,
-    'event propagates to end of pipe chain from middle src');
-  assert.equal(src1Fired, 1, 'event does not fire on alternative chain routes');
-  assert.equal(src2Fired, 1, 'event does not fire on alternative chain routes');
-};
-
-exports['test stripListeners'] = function (assert) {
-  var options = {
-    onAnEvent: noop1,
-    onMessage: noop2,
-    verb: noop1,
-    value: 100
-  };
-
-  var stripped = stripListeners(options);
-  assert.ok(stripped !== options, 'stripListeners should return a new object');
-  assert.equal(options.onAnEvent, noop1, 'stripListeners does not affect original');
-  assert.equal(options.onMessage, noop2, 'stripListeners does not affect original');
-  assert.equal(options.verb, noop1, 'stripListeners does not affect original');
-  assert.equal(options.value, 100, 'stripListeners does not affect original');
-
-  assert.ok(!stripped.onAnEvent, 'stripListeners removes `on*` values');
-  assert.ok(!stripped.onMessage, 'stripListeners removes `on*` values');
-  assert.equal(stripped.verb, noop1, 'stripListeners leaves not `on*` values');
-  assert.equal(stripped.value, 100, 'stripListeners leaves not `on*` values');
-
-  function noop1 () {}
-  function noop2 () {}
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-file.js
+++ /dev/null
@@ -1,271 +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 { pathFor } = require('sdk/system');
-const file = require("sdk/io/file");
-const url = require("sdk/url");
-
-const byteStreams = require("sdk/io/byte-streams");
-const textStreams = require("sdk/io/text-streams");
-
-const ERRORS = {
-  FILE_NOT_FOUND: /^path does not exist: .+$/,
-  NOT_A_DIRECTORY: /^path is not a directory: .+$/,
-  NOT_A_FILE: /^path is not a file: .+$/,
-};
-
-// Use profile directory to list / read / write files.
-const profilePath = pathFor('ProfD');
-const fileNameInProfile = 'compatibility.ini';
-const dirNameInProfile = 'extensions';
-const filePathInProfile = file.join(profilePath, fileNameInProfile);
-const dirPathInProfile = file.join(profilePath, dirNameInProfile);
-
-exports.testDirName = function(assert) {
-  assert.equal(file.dirname(dirPathInProfile), profilePath,
-                   "file.dirname() of dir should return parent dir");
-
-  assert.equal(file.dirname(filePathInProfile), profilePath,
-                   "file.dirname() of file should return its dir");
-
-  let dir = profilePath;
-  while (dir)
-    dir = file.dirname(dir);
-
-  assert.equal(dir, "",
-                   "dirname should return empty string when dir has no parent");
-};
-
-exports.testBasename = function(assert) {
-  // Get the top-most path -- the path with no basename.  E.g., on Unix-like
-  // systems this will be /.  We'll use it below to build up some test paths.
-  // We have to go to this trouble because file.join() needs a legal path as a
-  // base case; join("foo", "bar") doesn't work unfortunately.
-  let topPath = profilePath;
-  let parentPath = file.dirname(topPath);
-  while (parentPath) {
-    topPath = parentPath;
-    parentPath = file.dirname(topPath);
-  }
-
-  let path = topPath;
-  assert.equal(file.basename(path), "",
-                   "basename should work on paths with no components");
-
-  path = file.join(path, "foo");
-  assert.equal(file.basename(path), "foo",
-                   "basename should work on paths with a single component");
-
-  path = file.join(path, "bar");
-  assert.equal(file.basename(path), "bar",
-                   "basename should work on paths with multiple components");
-};
-
-exports.testList = function(assert) {
-  let list = file.list(profilePath);
-  let found = list.filter(name => name === fileNameInProfile);
-
-  assert.equal(found.length, 1, "file.list() should work");
-
-  assert.throws(function() {
-    file.list(filePathInProfile);
-  }, ERRORS.NOT_A_DIRECTORY, "file.list() on non-dir should raise error");
-
-  assert.throws(function() {
-    file.list(file.join(dirPathInProfile, "does-not-exist"));
-  }, ERRORS.FILE_NOT_FOUND, "file.list() on nonexistent should raise error");
-};
-
-exports.testRead = function(assert) {
-  let contents = file.read(filePathInProfile);
-  assert.ok(/Compatibility/.test(contents),
-                     "file.read() should work");
-
-  assert.throws(function() {
-    file.read(file.join(dirPathInProfile, "does-not-exists"));
-  }, ERRORS.FILE_NOT_FOUND, "file.read() on nonexistent file should throw");
-
-  assert.throws(function() {
-    file.read(dirPathInProfile);
-  }, ERRORS.NOT_A_FILE, "file.read() on dir should throw");
-};
-
-exports.testJoin = function(assert) {
-  let baseDir = file.dirname(filePathInProfile);
-
-  assert.equal(file.join(baseDir, fileNameInProfile),
-                   filePathInProfile, "file.join() should work");
-};
-
-exports.testOpenNonexistentForRead = function (assert) {
-  var filename = file.join(profilePath, 'does-not-exists');
-  assert.throws(function() {
-    file.open(filename);
-  }, ERRORS.FILE_NOT_FOUND, "file.open() on nonexistent file should throw");
-
-  assert.throws(function() {
-    file.open(filename, "r");
-  }, ERRORS.FILE_NOT_FOUND, "file.open('r') on nonexistent file should throw");
-
-  assert.throws(function() {
-    file.open(filename, "zz");
-  }, ERRORS.FILE_NOT_FOUND, "file.open('zz') on nonexistent file should throw");
-};
-
-exports.testOpenNonexistentForWrite = function (assert) {
-  let filename = file.join(profilePath, 'open.txt');
-
-  let stream = file.open(filename, "w");
-  stream.close();
-
-  assert.ok(file.exists(filename),
-              "file.exists() should return true after file.open('w')");
-  file.remove(filename);
-  assert.ok(!file.exists(filename),
-              "file.exists() should return false after file.remove()");
-
-  stream = file.open(filename, "rw");
-  stream.close();
-
-  assert.ok(file.exists(filename),
-              "file.exists() should return true after file.open('rw')");
-  file.remove(filename);
-  assert.ok(!file.exists(filename),
-              "file.exists() should return false after file.remove()");
-};
-
-exports.testOpenDirectory = function (assert) {
-  let dir = dirPathInProfile;
-  assert.throws(function() {
-    file.open(dir);
-  }, ERRORS.NOT_A_FILE, "file.open() on directory should throw");
-
-  assert.throws(function() {
-    file.open(dir, "w");
-  }, ERRORS.NOT_A_FILE, "file.open('w') on directory should throw");
-};
-
-exports.testOpenTypes = function (assert) {
-  let filename = file.join(profilePath, 'open-types.txt');
-
-
-  // Do the opens first to create the data file.
-  var stream = file.open(filename, "w");
-  assert.ok(stream instanceof textStreams.TextWriter,
-              "open(w) should return a TextWriter");
-  stream.close();
-
-  stream = file.open(filename, "wb");
-  assert.ok(stream instanceof byteStreams.ByteWriter,
-              "open(wb) should return a ByteWriter");
-  stream.close();
-
-  stream = file.open(filename);
-  assert.ok(stream instanceof textStreams.TextReader,
-              "open() should return a TextReader");
-  stream.close();
-
-  stream = file.open(filename, "r");
-  assert.ok(stream instanceof textStreams.TextReader,
-              "open(r) should return a TextReader");
-  stream.close();
-
-  stream = file.open(filename, "b");
-  assert.ok(stream instanceof byteStreams.ByteReader,
-              "open(b) should return a ByteReader");
-  stream.close();
-
-  stream = file.open(filename, "rb");
-  assert.ok(stream instanceof byteStreams.ByteReader,
-              "open(rb) should return a ByteReader");
-  stream.close();
-
-  file.remove(filename);
-};
-
-exports.testMkpathRmdir = function (assert) {
-  let basePath = profilePath;
-  let dirs = [];
-  for (let i = 0; i < 3; i++)
-    dirs.push("test-file-dir");
-
-  let paths = [];
-  for (let i = 0; i < dirs.length; i++) {
-    let args = [basePath].concat(dirs.slice(0, i + 1));
-    paths.unshift(file.join.apply(null, args));
-  }
-
-  for (let i = 0; i < paths.length; i++) {
-    assert.ok(!file.exists(paths[i]),
-                "Sanity check: path should not exist: " + paths[i]);
-  }
-
-  file.mkpath(paths[0]);
-  assert.ok(file.exists(paths[0]), "mkpath should create path: " + paths[0]);
-
-  for (let i = 0; i < paths.length; i++) {
-    file.rmdir(paths[i]);
-    assert.ok(!file.exists(paths[i]),
-                "rmdir should remove path: " + paths[i]);
-  }
-};
-
-exports.testMkpathTwice = function (assert) {
-  let dir = profilePath;
-  let path = file.join(dir, "test-file-dir");
-  assert.ok(!file.exists(path),
-              "Sanity check: path should not exist: " + path);
-  file.mkpath(path);
-  assert.ok(file.exists(path), "mkpath should create path: " + path);
-  file.mkpath(path);
-  assert.ok(file.exists(path),
-              "After second mkpath, path should still exist: " + path);
-  file.rmdir(path);
-  assert.ok(!file.exists(path), "rmdir should remove path: " + path);
-};
-
-exports.testMkpathExistingNondirectory = function (assert) {
-  var fname = file.join(profilePath, 'conflict.txt');
-  file.open(fname, "w").close();
-  assert.ok(file.exists(fname), "File should exist");
-  assert.throws(() => file.mkpath(fname),
-                    /^The path already exists and is not a directory: .+$/,
-                    "mkpath on file should raise error");
-  file.remove(fname);
-};
-
-exports.testRmdirNondirectory = function (assert) {
-  var fname = file.join(profilePath, 'not-a-dir')
-  file.open(fname, "w").close();
-  assert.ok(file.exists(fname), "File should exist");
-  assert.throws(function() {
-    file.rmdir(fname);
-  }, ERRORS.NOT_A_DIRECTORY, "rmdir on file should raise error");
-  file.remove(fname);
-  assert.ok(!file.exists(fname), "File should not exist");
-  assert.throws(() => file.rmdir(fname),
-                    ERRORS.FILE_NOT_FOUND,
-                    "rmdir on non-existing file should raise error");
-};
-
-exports.testRmdirNonempty = function (assert) {
-  let dir = profilePath;
-  let path = file.join(dir, "test-file-dir");
-  assert.ok(!file.exists(path),
-              "Sanity check: path should not exist: " + path);
-  file.mkpath(path);
-  let filePath = file.join(path, "file");
-  file.open(filePath, "w").close();
-  assert.ok(file.exists(filePath),
-              "Sanity check: path should exist: " + filePath);
-  assert.throws(() => file.rmdir(path),
-                    /^The directory is not empty: .+$/,
-                    "rmdir on non-empty directory should raise error");
-  file.remove(filePath);
-  file.rmdir(path);
-  assert.ok(!file.exists(path), "Path should not exist");
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-frame-utils.js
+++ /dev/null
@@ -1,57 +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 { create } = require('sdk/frame/utils');
-const { open, close } = require('sdk/window/helpers');
-
-exports['test frame creation'] = function(assert, done) {
-  open('data:text/html;charset=utf-8,Window').then(function (window) {
-    let frame = create(window.document);
-
-    assert.equal(frame.getAttribute('type'), 'content',
-                 'frame type is content');
-    assert.ok(frame.contentWindow, 'frame has contentWindow');
-    assert.equal(frame.contentWindow.location.href, 'about:blank',
-                 'by default "about:blank" is loaded');
-    assert.equal(frame.docShell.allowAuth, false, 'auth disabled by default');
-    assert.equal(frame.docShell.allowJavascript, false, 'js disabled by default');
-    assert.equal(frame.docShell.allowPlugins, false,
-                 'plugins disabled by default');
-    close(window).then(done);
-  });
-};
-
-exports['test fram has js disabled by default'] = function(assert, done) {
-  open('data:text/html;charset=utf-8,window').then(function (window) {
-    let frame = create(window.document, {
-      uri: 'data:text/html;charset=utf-8,<script>document.documentElement.innerHTML' +
-           '= "J" + "S"</script>',
-    });
-    frame.contentWindow.addEventListener('DOMContentLoaded', function() {
-      assert.ok(!~frame.contentDocument.documentElement.innerHTML.indexOf('JS'),
-                'JS was executed');
-
-      close(window).then(done);
-    }, {once: true});
-  });
-};
-
-exports['test frame with js enabled'] = function(assert, done) {
-  open('data:text/html;charset=utf-8,window').then(function (window) {
-    let frame = create(window.document, {
-      uri: 'data:text/html;charset=utf-8,<script>document.documentElement.innerHTML' +
-           '= "J" + "S"</script>',
-      allowJavascript: true
-    });
-    frame.contentWindow.addEventListener('DOMContentLoaded', function() {
-      assert.ok(~frame.contentDocument.documentElement.innerHTML.indexOf('JS'),
-                'JS was executed');
-
-      close(window).then(done);
-    }, {once: true});
-  });
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-framescript-manager.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const {loadModule} = require("framescript/manager");
-const {withTab, receiveMessage} = require("./util");
-const {getBrowserForTab} = require("sdk/tabs/utils");
-
-exports.testLoadModule = withTab(function*(assert, tab) {
-  const {messageManager} = getBrowserForTab(tab);
-
-  loadModule(messageManager,
-             require.resolve("./framescript-manager/frame-script"),
-             true,
-             "onInit");
-
-  const message = yield receiveMessage(messageManager, "framescript-manager/ready");
-
-  assert.deepEqual(message.data, {state: "ready"},
-                   "received ready message from the loaded module");
-
-  messageManager.sendAsyncMessage("framescript-manager/ping", {x: 1});
-
-  const pong = yield receiveMessage(messageManager, "framescript-manager/pong");
-
-  assert.deepEqual(pong.data, {x: 1},
-                    "received pong back");
-}, "data:text/html,<h1>Message Manager</h1>");
-
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-framescript-util.js
+++ /dev/null
@@ -1,45 +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 {loadModule} = require("framescript/manager");
-const {withTab, receiveMessage} = require("./util");
-const {getBrowserForTab} = require("sdk/tabs/utils");
-
-exports["test windowToMessageManager"] = withTab(function*(assert, tab) {
-  const {messageManager} = getBrowserForTab(tab);
-
-  loadModule(messageManager,
-             require.resolve("./framescript-util/frame-script"),
-             true,
-             "onInit");
-
-  messageManager.sendAsyncMessage("framescript-util/window/request");
-
-  const response = yield receiveMessage(messageManager,
-                                        "framescript-util/window/response");
-
-  assert.deepEqual(response.data, {window: true},
-                   "got response");
-}, "data:text/html,<h1>Window to Message Manager</h1>");
-
-
-exports["test nodeToMessageManager"] = withTab(function*(assert, tab) {
-  const {messageManager} = getBrowserForTab(tab);
-
-  loadModule(messageManager,
-             require.resolve("./framescript-util/frame-script"),
-             true,
-             "onInit");
-
-  messageManager.sendAsyncMessage("framescript-util/node/request", "h1");
-
-  const response = yield receiveMessage(messageManager,
-                                        "framescript-util/node/response");
-
-  assert.deepEqual(response.data, {node: true},
-                   "got response");
-}, "data:text/html,<h1>Node to Message Manager</h1>");
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-fs.js
+++ /dev/null
@@ -1,621 +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 { pathFor, platform } = require("sdk/system");
-const fs = require("sdk/io/fs");
-const url = require("sdk/url");
-const path = require("sdk/fs/path");
-const { defer } = require("sdk/core/promise");
-const { Buffer } = require("sdk/io/buffer");
-const { is } = require("sdk/system/xul-app");
-
-// Use profile directory to list / read / write files.
-const profilePath = pathFor("ProfD");
-const fileNameInProfile = "compatibility.ini";
-const dirNameInProfile = "extensions";
-const filePathInProfile = path.join(profilePath, fileNameInProfile);
-const dirPathInProfile = path.join(profilePath, dirNameInProfile);
-const mkdirPath = path.join(profilePath, "sdk-fixture-mkdir");
-const writePath = path.join(profilePath, "sdk-fixture-writeFile");
-const unlinkPath = path.join(profilePath, "sdk-fixture-unlink");
-const truncatePath = path.join(profilePath, "sdk-fixture-truncate");
-const renameFromPath = path.join(profilePath, "sdk-fixture-rename-from");
-const renameToPath = path.join(profilePath, "sdk-fixture-rename-to");
-const chmodPath = path.join(profilePath, "sdk-fixture-chmod");
-
-const profileEntries = [
-  "compatibility.ini",
-  "extensions",
-  "prefs.js"
-  // There are likely to be a lot more files but we can"t really
-  // on consistent list so we limit to this.
-];
-
-const isWindows = platform.indexOf('win') === 0;
-
-exports["test readdir"] = function(assert, end) {
-  var async = false;
-  fs.readdir(profilePath, function(error, entries) {
-    assert.ok(async, "readdir is async");
-    assert.ok(!error, "there is no error when reading directory");
-    assert.ok(profileEntries.length <= entries.length,
-              "got at least number of entries we expect");
-    assert.ok(profileEntries.every(function(entry) {
-                return entries.indexOf(entry) >= 0;
-              }), "all profiles are present");
-    end();
-  });
-
-  async = true;
-};
-
-exports["test readdir error"] = function(assert, end) {
-  var async = false;
-  var path = profilePath + "-does-not-exists";
-  fs.readdir(path, function(error, entries) {
-    assert.ok(async, "readdir is async");
-    assert.equal(error.message, "ENOENT, readdir " + path);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-    end();
-  });
-
-  async = true;
-};
-
-exports["test readdirSync"] = function(assert) {
-  var async = false;
-  var entries = fs.readdirSync(profilePath);
-  assert.ok(profileEntries.length <= entries.length,
-            "got at least number of entries we expect");
-  assert.ok(profileEntries.every(function(entry) {
-    return entries.indexOf(entry) >= 0;
-  }), "all profiles are present");
-};
-
-exports["test readdirSync error"] = function(assert) {
-  var async = false;
-  var path = profilePath + "-does-not-exists";
-  try {
-    fs.readdirSync(path);
-    assert.fail(Error("No error was thrown"));
-  } catch (error) {
-    assert.equal(error.message, "ENOENT, readdir " + path);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-  }
-};
-
-exports["test readFile"] = function(assert, end) {
-  let async = false;
-  fs.readFile(filePathInProfile, function(error, content) {
-    assert.ok(async, "readFile is async");
-    assert.ok(!error, "error is falsy");
-
-    assert.ok(Buffer.isBuffer(content), "readFile returns buffer");
-    assert.ok(typeof(content.length) === "number", "buffer has length");
-    assert.ok(content.toString().indexOf("[Compatibility]") >= 0,
-              "content contains expected data");
-    end();
-  });
-  async = true;
-};
-
-exports["test readFile error"] = function(assert, end) {
-  let async = false;
-  let path = filePathInProfile + "-does-not-exists";
-  fs.readFile(path, function(error, content) {
-    assert.ok(async, "readFile is async");
-    assert.equal(error.message, "ENOENT, open " + path);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-
-    end();
-  });
-  async = true;
-};
-
-exports["test readFileSync not implemented"] = function(assert) {
-  let buffer = fs.readFileSync(filePathInProfile);
-  assert.ok(buffer.toString().indexOf("[Compatibility]") >= 0,
-            "read content");
-};
-
-exports["test fs.stat file"] = function(assert, end) {
-  let async = false;
-  let path = filePathInProfile;
-  fs.stat(path, function(error, stat) {
-    assert.ok(async, "fs.stat is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!stat.isDirectory(), "not a dir");
-    assert.ok(stat.isFile(), "is a file");
-    assert.ok(!stat.isSymbolicLink(), "isn't a symlink");
-    assert.ok(typeof(stat.size) === "number", "size is a number");
-    assert.ok(stat.exists === true, "file exists");
-    assert.ok(typeof(stat.isBlockDevice()) === "boolean");
-    assert.ok(typeof(stat.isCharacterDevice()) === "boolean");
-    assert.ok(typeof(stat.isFIFO()) === "boolean");
-    assert.ok(typeof(stat.isSocket()) === "boolean");
-    assert.ok(typeof(stat.hidden) === "boolean");
-    assert.ok(typeof(stat.writable) === "boolean")
-    assert.ok(stat.readable === true);
-
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.stat dir"] = function(assert, end) {
-  let async = false;
-  let path = dirPathInProfile;
-  fs.stat(path, function(error, stat) {
-    assert.ok(async, "fs.stat is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(stat.isDirectory(), "is a dir");
-    assert.ok(!stat.isFile(), "not a file");
-    assert.ok(!stat.isSymbolicLink(), "isn't a symlink");
-    assert.ok(typeof(stat.size) === "number", "size is a number");
-    assert.ok(stat.exists === true, "file exists");
-    assert.ok(typeof(stat.isBlockDevice()) === "boolean");
-    assert.ok(typeof(stat.isCharacterDevice()) === "boolean");
-    assert.ok(typeof(stat.isFIFO()) === "boolean");
-    assert.ok(typeof(stat.isSocket()) === "boolean");
-    assert.ok(typeof(stat.hidden) === "boolean");
-    assert.ok(typeof(stat.writable) === "boolean")
-    assert.ok(typeof(stat.readable) === "boolean");
-
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.stat error"] = function(assert, end) {
-  let async = false;
-  let path = filePathInProfile + "-does-not-exists";
-  fs.stat(path, function(error, stat) {
-    assert.ok(async, "fs.stat is async");
-    assert.equal(error.message, "ENOENT, stat " + path);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.exists NO"] = function(assert, end) {
-  let async = false
-  let path = filePathInProfile + "-does-not-exists";
-  fs.exists(path, function(error, value) {
-    assert.ok(async, "fs.exists is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!value, "file does not exists");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.exists YES"] = function(assert, end) {
-  let async = false
-  let path = filePathInProfile
-  fs.exists(path, function(error, value) {
-    assert.ok(async, "fs.exists is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(value, "file exists");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.exists NO"] = function(assert, end) {
-  let async = false
-  let path = filePathInProfile + "-does-not-exists";
-  fs.exists(path, function(error, value) {
-    assert.ok(async, "fs.exists is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!value, "file does not exists");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.existsSync"] = function(assert) {
-  let path = filePathInProfile
-  assert.equal(fs.existsSync(path), true, "exists");
-  assert.equal(fs.existsSync(path + "-does-not-exists"), false, "exists");
-};
-
-exports["test fs.mkdirSync fs.rmdirSync"] = function(assert) {
-  let path = mkdirPath;
-
-  assert.equal(fs.existsSync(path), false, "does not exists");
-  fs.mkdirSync(path);
-  assert.equal(fs.existsSync(path), true, "dir was created");
-  try {
-    fs.mkdirSync(path);
-    assert.fail(Error("mkdir on existing should throw"));
-  } catch (error) {
-    assert.equal(error.message, "EEXIST, mkdir " + path);
-    assert.equal(error.code, "EEXIST", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 47, "error has a errno");
-  }
-  fs.rmdirSync(path);
-  assert.equal(fs.existsSync(path), false, "dir was removed");
-};
-
-exports["test fs.mkdir"] = function(assert, end) {
-  let path = mkdirPath;
-
-  if (!fs.existsSync(path)) {
-    let async = false;
-    fs.mkdir(path, function(error) {
-      assert.ok(async, "mkdir is async");
-      assert.ok(!error, "no error");
-      assert.equal(fs.existsSync(path), true, "dir was created");
-      fs.rmdirSync(path);
-      assert.equal(fs.existsSync(path), false, "dir was removed");
-      end();
-    });
-    async = true;
-  }
-};
-
-exports["test fs.mkdir error"] = function(assert, end) {
-  let path = mkdirPath;
-
-  if (!fs.existsSync(path)) {
-    fs.mkdirSync(path);
-    let async = false;
-    fs.mkdir(path, function(error) {
-      assert.ok(async, "mkdir is async");
-      assert.equal(error.message, "EEXIST, mkdir " + path);
-      assert.equal(error.code, "EEXIST", "error has a code");
-      assert.equal(error.path, path, "error has a path");
-      assert.equal(error.errno, 47, "error has a errno");
-      fs.rmdirSync(path);
-      assert.equal(fs.existsSync(path), false, "dir was removed");
-      end();
-    });
-    async = true;
-  }
-};
-
-exports["test fs.rmdir"] = function(assert, end) {
-  let path = mkdirPath;
-
-  if (!fs.existsSync(path)) {
-    fs.mkdirSync(path);
-    assert.equal(fs.existsSync(path), true, "dir exists");
-    let async = false;
-    fs.rmdir(path, function(error) {
-      assert.ok(async, "mkdir is async");
-      assert.ok(!error, "no error");
-      assert.equal(fs.existsSync(path), false, "dir was removed");
-      end();
-    });
-    async = true;
-  }
-};
-
-
-exports["test fs.rmdir error"] = function(assert, end) {
-  let path = mkdirPath;
-
-  if (!fs.existsSync(path)) {
-    assert.equal(fs.existsSync(path), false, "dir doesn't exists");
-    let async = false;
-    fs.rmdir(path, function(error) {
-      assert.ok(async, "mkdir is async");
-      assert.equal(error.message, "ENOENT, remove " + path);
-      assert.equal(error.code, "ENOENT", "error has a code");
-      assert.equal(error.path, path, "error has a path");
-      assert.equal(error.errno, 34, "error has a errno");
-      assert.equal(fs.existsSync(path), false, "dir is removed");
-      end();
-    });
-    async = true;
-  }
-};
-
-exports["test fs.truncateSync fs.unlinkSync"] = function(assert) {
-  let path = truncatePath;
-
-  assert.equal(fs.existsSync(path), false, "does not exists");
-  fs.truncateSync(path);
-  assert.equal(fs.existsSync(path), true, "file was created");
-  fs.truncateSync(path);
-  fs.unlinkSync(path);
-  assert.equal(fs.existsSync(path), false, "file was removed");
-};
-
-
-exports["test fs.truncate"] = function(assert, end) {
-  let path = truncatePath;
-  if (!fs.existsSync(path)) {
-    let async = false;
-    fs.truncate(path, 0, function(error) {
-      assert.ok(async, "truncate is async");
-      assert.ok(!error, "no error");
-      assert.equal(fs.existsSync(path), true, "file was created");
-      fs.unlinkSync(path);
-      assert.equal(fs.existsSync(path), false, "file was removed");
-      end();
-    })
-    async = true;
-  }
-};
-
-exports["test fs.unlink"] = function(assert, end) {
-  let path = unlinkPath;
-  let async = false;
-  assert.ok(!fs.existsSync(path), "file doesn't exists yet");
-  fs.truncateSync(path, 0);
-  assert.ok(fs.existsSync(path), "file was created");
-  fs.unlink(path, function(error) {
-    assert.ok(async, "fs.unlink is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!fs.existsSync(path), "file was removed");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.unlink error"] = function(assert, end) {
-  let path = unlinkPath;
-  let async = false;
-  assert.ok(!fs.existsSync(path), "file doesn't exists yet");
-  fs.unlink(path, function(error) {
-    assert.ok(async, "fs.unlink is async");
-    assert.equal(error.message, "ENOENT, remove " + path);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, path, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.rename"] = function(assert, end) {
-  let fromPath = renameFromPath;
-  let toPath = renameToPath;
-
-  fs.truncateSync(fromPath);
-  assert.ok(fs.existsSync(fromPath), "source file exists");
-  assert.ok(!fs.existsSync(toPath), "destination doesn't exists");
-  var async = false;
-  fs.rename(fromPath, toPath, function(error) {
-    assert.ok(async, "fs.rename is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!fs.existsSync(fromPath), "source path no longer exists");
-    assert.ok(fs.existsSync(toPath), "destination file exists");
-    fs.unlinkSync(toPath);
-    assert.ok(!fs.existsSync(toPath), "cleaned up properly");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.rename (missing source file)"] = function(assert, end) {
-  let fromPath = renameFromPath;
-  let toPath = renameToPath;
-
-  assert.ok(!fs.existsSync(fromPath), "source file doesn't exists");
-  assert.ok(!fs.existsSync(toPath), "destination doesn't exists");
-  var async = false;
-  fs.rename(fromPath, toPath, function(error) {
-    assert.ok(async, "fs.rename is async");
-    assert.equal(error.message, "ENOENT, rename " + fromPath);
-    assert.equal(error.code, "ENOENT", "error has a code");
-    assert.equal(error.path, fromPath, "error has a path");
-    assert.equal(error.errno, 34, "error has a errno");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.rename (existing target file)"] = function(assert, end) {
-  let fromPath = renameFromPath;
-  let toPath = renameToPath;
-
-  fs.truncateSync(fromPath);
-  fs.truncateSync(toPath);
-  assert.ok(fs.existsSync(fromPath), "source file exists");
-  assert.ok(fs.existsSync(toPath), "destination file exists");
-  var async = false;
-  fs.rename(fromPath, toPath, function(error) {
-    assert.ok(async, "fs.rename is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(!fs.existsSync(fromPath), "source path no longer exists");
-    assert.ok(fs.existsSync(toPath), "destination file exists");
-    fs.unlinkSync(toPath);
-    assert.ok(!fs.existsSync(toPath), "cleaned up properly");
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.writeFile"] = function(assert, end) {
-  let path = writePath;
-  let content = ["hello world",
-                 "this is some text"].join("\n");
-
-  var async = false;
-  fs.writeFile(path, content, function(error) {
-    assert.ok(async, "fs write is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(fs.existsSync(path), "file was created");
-    assert.equal(fs.readFileSync(path).toString(),
-                 content,
-                 "contet was written");
-    fs.unlinkSync(path);
-    assert.ok(!fs.exists(path), "file was removed");
-
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.writeFile (with large files)"] = function(assert, end) {
-  let path = writePath;
-  let content = "";
-
-  for (var i = 0; i < 100000; i++) {
-    content += "buffer\n";
-  }
-
-  var async = false;
-  fs.writeFile(path, content, function(error) {
-    assert.ok(async, "fs write is async");
-    assert.ok(!error, "error is falsy");
-    assert.ok(fs.existsSync(path), "file was created");
-    assert.equal(fs.readFileSync(path).toString(),
-                 content,
-                 "contet was written");
-    fs.unlinkSync(path);
-    assert.ok(!fs.exists(path), "file was removed");
-
-    end();
-  });
-  async = true;
-};
-
-exports["test fs.writeFile error"] = function (assert, done) {
-  try {
-    fs.writeFile({}, 'content', function (err) {
-      assert.fail('Error thrown from TypeError should not be caught');
-    });
-  } catch (e) {
-    assert.ok(e,
-      'writeFile with a non-string error should not be caught');
-    assert.equal(e.name, 'TypeError', 'error should be TypeError');
-  }
-  fs.writeFile('not/a/valid/path', 'content', function (err) {
-    assert.ok(err, 'error caught and handled in callback');
-    done();
-  });
-};
-
-exports["test fs.chmod"] = function (assert, done) {
-  let content = ["hej från sverige"];
-
-  fs.writeFile(chmodPath, content, function (err) {
-    testPerm("0755")()
-      .then(testPerm("0777"))
-      .then(testPerm("0666"))
-      .then(testPerm(0o511))
-      .then(testPerm(0o200))
-      .then(testPerm("0040"))
-      .then(testPerm("0000"))
-      .then(testPermSync(0o777))
-      .then(testPermSync(0o666))
-      .then(testPermSync("0511"))
-      .then(testPermSync("0200"))
-      .then(testPermSync("0040"))
-      .then(testPermSync("0000"))
-      .then(() => {
-        assert.pass("Successful chmod passes");
-      }, assert.fail)
-      // Test invalid paths
-      .then(() => chmod("not-a-valid-file", 0o755))
-      .then(assert.fail, (err) => {
-        checkPermError(err, "not-a-valid-file");
-      })
-      .then(() => chmod("not-a-valid-file", 0o755, "sync"))
-      .then(assert.fail, (err) => {
-        checkPermError(err, "not-a-valid-file");
-      })
-      // Test invalid files
-      .then(() => chmod("resource://not-a-real-file", 0o755))
-      .then(assert.fail, (err) => {
-        checkPermError(err, "resource://not-a-real-file");
-      })
-      .then(() => chmod("resource://not-a-real-file", 0o755, 'sync'))
-      .then(assert.fail, (err) => {
-        checkPermError(err, "resource://not-a-real-file");
-      })
-      .then(done, assert.fail);
-  });
-
-  function checkPermError (err, path) {
-    assert.equal(err.message, "ENOENT, chmod " + path);
-    assert.equal(err.code, "ENOENT", "error has a code");
-    assert.equal(err.path, path, "error has a path");
-    assert.equal(err.errno, 34, "error has a errno");
-  }
-
-  function chmod (path, mode, sync) {
-    let { promise, resolve, reject } = defer();
-    if (!sync) {
-      fs.chmod(path, mode, (err) => {
-        if (err) reject(err);
-        else resolve();
-      });
-    } else {
-      fs.chmodSync(path, mode);
-      resolve();
-    }
-    return promise;
-  }
-
-  function testPerm (mode, sync) {
-    return function () {
-      return chmod(chmodPath, mode, sync)
-        .then(() => getPerm(chmodPath))
-        .then(perm => {
-          let nMode = normalizeMode(mode);
-          if (isWindows)
-            assert.equal(perm, nMode,
-              "mode correctly set to " + mode + " (" + nMode + " on windows)");
-          else
-            assert.equal(perm, nMode, "mode correctly set to " + nMode);
-        });
-    };
-  }
-
-  function testPermSync (mode) {
-    return testPerm(mode, true);
-  }
-
-  function getPerm (path) {
-    let { promise, resolve, reject } = defer();
-    fs.stat(path, function (err, stat) {
-      if (err) reject(err);
-      else resolve(stat.mode);
-    });
-    return promise;
-  }
-
-  /*
-   * Converts a unix mode `0755` into a Windows version of unix permissions
-   */
-  function normalizeMode (mode) {
-    if (typeof mode === "string")
-      mode = parseInt(mode, 8);
-
-    if (!isWindows)
-      return mode;
-
-    var ANY_READ = 0o444;
-    var ANY_WRITE = 0o222;
-    var winMode = 0;
-
-    // On Windows, if WRITE is true, then READ is also true
-    if (mode & ANY_WRITE)
-      winMode |= ANY_WRITE | ANY_READ;
-    // Minimum permissions are READ for Windows
-    else
-      winMode |= ANY_READ;
-
-    return winMode;
-  }
-};
-
-require("test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-functional.js
+++ /dev/null
@@ -1,463 +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 { setTimeout } = require('sdk/timers');
-const utils = require('sdk/lang/functional');
-const { invoke, defer, partial, compose, memoize, once, is, isnt,
-  delay, wrap, curry, chainable, field, query, isInstance, debounce, throttle
-} = utils;
-const { LoaderWithHookedConsole } = require('sdk/test/loader');
-
-exports['test forwardApply'] = function(assert) {
-  function sum(b, c) { return this.a + b + c; }
-  assert.equal(invoke(sum, [2, 3], { a: 1 }), 6,
-               'passed arguments and pseoude-variable are used');
-
-  assert.equal(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7,
-               'bounded `this` pseoudo variable is used');
-};
-
-exports['test deferred function'] = function(assert, done) {
-  let nextTurn = false;
-  function sum(b, c) {
-    assert.ok(nextTurn, 'enqueued is called in next turn of event loop');
-    assert.equal(this.a + b + c, 6,
-                 'passed arguments an pseoude-variable are used');
-    done();
-  }
-
-  let fixture = { a: 1, method: defer(sum) };
-  fixture.method(2, 3);
-  nextTurn = true;
-};
-
-exports['test partial function'] = function(assert) {
-  function sum(b, c) { return this.a + b + c; }
-
-  let foo = { a : 5 };
-
-  foo.sum7 = partial(sum, 7);
-  foo.sum8and4 = partial(sum, 8, 4);
-
-  assert.equal(foo.sum7(2), 14, 'partial one arguments works');
-
-  assert.equal(foo.sum8and4(), 17, 'partial both arguments works');
-};
-
-exports["test curry defined numeber of arguments"] = function(assert) {
-  var sum = curry(function(a, b, c) {
-    return a + b + c;
-  });
-
-  assert.equal(sum(2, 2, 1), 5, "sum(2, 2, 1) => 5");
-  assert.equal(sum(2, 4)(1), 7, "sum(2, 4)(1) => 7");
-  assert.equal(sum(2)(4, 2), 8, "sum(2)(4, 2) => 8");
-  assert.equal(sum(2)(4)(3), 9, "sum(2)(4)(3) => 9");
-};
-
-exports['test compose'] = function(assert) {
-  let greet = function(name) { return 'hi: ' + name; };
-  let exclaim = function(sentence) { return sentence + '!'; };
-
-  assert.equal(compose(exclaim, greet)('moe'), 'hi: moe!',
-               'can compose a function that takes another');
-
-  assert.equal(compose(greet, exclaim)('moe'), 'hi: moe!',
-               'in this case, the functions are also commutative');
-
-  let target = {
-    name: 'Joe',
-    greet: compose(function exclaim(sentence) {
-      return sentence + '!';
-    }, function(title) {
-      return 'hi : ' + title + ' ' + this.name;
-    })
-  };
-
-  assert.equal(target.greet('Mr'), 'hi : Mr Joe!',
-               'this can be passed in');
-  assert.equal(target.greet.call({ name: 'Alex' }, 'Dr'), 'hi : Dr Alex!',
-               'this can be applied');
-
-  let single = compose(function(value) {
-    return value + ':suffix';
-  });
-
-  assert.equal(single('text'), 'text:suffix', 'works with single function');
-
-  let identity = compose();
-  assert.equal(identity('bla'), 'bla', 'works with zero functions');
-};
-
-exports['test wrap'] = function(assert) {
-  let greet = function(name) { return 'hi: ' + name; };
-  let backwards = wrap(greet, function(f, name) {
-    return f(name) + ' ' + name.split('').reverse().join('');
-  });
-
-  assert.equal(backwards('moe'), 'hi: moe eom',
-               'wrapped the saluation function');
-
-  let inner = function () { return 'Hello '; };
-  let target = {
-    name: 'Matteo',
-    hi: wrap(inner, function(f) { return f() + this.name; })
-  };
-
-  assert.equal(target.hi(), 'Hello Matteo', 'works with this');
-
-  function noop() { }
-  let wrapped = wrap(noop, function(f) {
-    return Array.slice(arguments);
-  });
-
-  let actual = wrapped([ 'whats', 'your' ], 'vector', 'victor');
-  assert.deepEqual(actual, [ noop, ['whats', 'your'], 'vector', 'victor' ],
-                   'works with fancy stuff');
-};
-
-exports['test memoize'] = function(assert) {
-  const fib = n => n < 2 ? n : fib(n - 1) + fib(n - 2);
-  let fibnitro = memoize(fib);
-
-  assert.equal(fib(10), 55,
-        'a memoized version of fibonacci produces identical results');
-  assert.equal(fibnitro(10), 55,
-        'a memoized version of fibonacci produces identical results');
-
-  function o(key, value) { return value; }
-  let oo = memoize(o), v1 = {}, v2 = {};
-
-
-  assert.equal(oo(1, v1), v1, 'returns value back');
-  assert.equal(oo(1, v2), v1, 'memoized by a first argument');
-  assert.equal(oo(2, v2), v2, 'returns back value if not memoized');
-  assert.equal(oo(2), v2, 'memoized new value');
-  assert.notEqual(oo(1), oo(2), 'values do not override');
-  assert.equal(o(3, v2), oo(2, 3), 'returns same value as un-memoized');
-
-  let get = memoize(function(attribute) { return this[attribute]; });
-  let target = { name: 'Bob', get: get };
-
-  assert.equal(target.get('name'), 'Bob', 'has correct `this`');
-  assert.equal(target.get.call({ name: 'Jack' }, 'name'), 'Bob',
-               'name is memoized');
-  assert.equal(get('name'), 'Bob', 'once memoized can be called without this');
-};
-
-exports['test delay'] = function(assert, done) {
-  let delayed = false;
-  delay(function() {
-    assert.ok(delayed, 'delayed the function');
-    done();
-  }, 1);
-  delayed = true;
-};
-
-exports['test delay with this'] = function(assert, done) {
-  let context = {};
-  delay.call(context, function(name) {
-    assert.equal(this, context, 'this was passed in');
-    assert.equal(name, 'Tom', 'argument was passed in');
-    done();
-  }, 10, 'Tom');
-};
-
-exports['test once'] = function(assert) {
-  let n = 0;
-  let increment = once(function() { n ++; });
-
-  increment();
-  increment();
-
-  assert.equal(n, 1, 'only incremented once');
-
-  let target = {
-    state: 0,
-    update: once(function() {
-      return this.state ++;
-    })
-  };
-
-  target.update();
-  target.update();
-
-  assert.equal(target.state, 1, 'this was passed in and called only once');
-};
-
-exports['test once with argument'] = function(assert) {
-  let n = 0;
-  let increment = once(a => n++);
-
-  increment();
-  increment('foo');
-
-  assert.equal(n, 1, 'only incremented once');
-
-  increment();
-  increment('foo');
-
-  assert.equal(n, 1, 'only incremented once');
-};
-
-exports['test complement'] = assert => {
-  let { complement } = require("sdk/lang/functional");
-
-  let isOdd = x => Boolean(x % 2);
-
-  assert.equal(isOdd(1), true);
-  assert.equal(isOdd(2), false);
-
-  let isEven = complement(isOdd);
-
-  assert.equal(isEven(1), false);
-  assert.equal(isEven(2), true);
-
-  let foo = {};
-  let isFoo = function() { return this === foo; };
-  let insntFoo = complement(isFoo);
-
-  assert.equal(insntFoo.call(foo), false);
-  assert.equal(insntFoo.call({}), true);
-};
-
-exports['test constant'] = assert => {
-  let { constant } = require("sdk/lang/functional");
-
-  let one = constant(1);
-
-  assert.equal(one(1), 1);
-  assert.equal(one(2), 1);
-};
-
-exports['test apply'] = assert => {
-  let { apply } = require("sdk/lang/functional");
-
-  let dashify = (...args) => args.join("-");
-
-  assert.equal(apply(dashify, 1, [2, 3]), "1-2-3");
-  assert.equal(apply(dashify, "a"), "a");
-  assert.equal(apply(dashify, ["a", "b"]), "a-b");
-  assert.equal(apply(dashify, ["a", "b"], "c"), "a,b-c");
-  assert.equal(apply(dashify, [1, 2], [3, 4]), "1,2-3-4");
-};
-
-exports['test flip'] = assert => {
-  let { flip } = require("sdk/lang/functional");
-
-  let append = (left, right) => left + " " + right;
-  let prepend = flip(append);
-
-  assert.equal(append("hello", "world"), "hello world");
-  assert.equal(prepend("hello", "world"), "world hello");
-
-  let wrap = function(left, right) {
-    return left + " " + this + " " + right;
-  };
-  let invertWrap = flip(wrap);
-
-  assert.equal(wrap.call("@", "hello", "world"), "hello @ world");
-  assert.equal(invertWrap.call("@", "hello", "world"), "world @ hello");
-
-  let reverse = flip((...args) => args);
-
-  assert.deepEqual(reverse(1, 2, 3, 4), [4, 3, 2, 1]);
-  assert.deepEqual(reverse(1), [1]);
-  assert.deepEqual(reverse(), []);
-
-  // currying still works
-  let prependr = curry(prepend);
-
-  assert.equal(prependr("hello", "world"), "world hello");
-  assert.equal(prependr("hello")("world"), "world hello");
-};
-
-exports["test when"] = assert => {
-  let { when } = require("sdk/lang/functional");
-
-  let areNums = (...xs) => xs.every(x => typeof(x) === "number");
-
-  let sum = when(areNums, (...xs) => xs.reduce((y, x) => x + y, 0));
-
-  assert.equal(sum(1, 2, 3), 6);
-  assert.equal(sum(1, 2, "3"), undefined);
-
-  let multiply = when(areNums,
-                      (...xs) => xs.reduce((y, x) => x * y, 1),
-                      (...xs) => xs);
-
-  assert.equal(multiply(2), 2);
-  assert.equal(multiply(2, 3), 6);
-  assert.deepEqual(multiply(2, "4"), [2, "4"]);
-
-  function Point(x, y) {
-    this.x = x;
-    this.y = y;
-  }
-
-  let isPoint = x => x instanceof Point;
-
-  let inc = when(isPoint, ({x, y}) => new Point(x + 1, y + 1));
-
-  assert.equal(inc({}), undefined);
-  assert.deepEqual(inc(new Point(0, 0)), { x: 1, y: 1 });
-
-  let axis = when(isPoint,
-                  ({ x, y }) => [x, y],
-                  _ => [0, 0]);
-
-  assert.deepEqual(axis(new Point(1, 4)), [1, 4]);
-  assert.deepEqual(axis({ foo: "bar" }), [0, 0]);
-};
-
-exports["test chainable"] = function(assert) {
-  let Player = function () { this.volume = 5; };
-  Player.prototype = {
-    setBand: chainable(function (band) { return (this.band = band); }),
-    incVolume: chainable(function () { return this.volume++; })
-  };
-  let player = new Player();
-  player
-    .setBand('Animals As Leaders')
-    .incVolume().incVolume().incVolume().incVolume().incVolume().incVolume();
-
-  assert.equal(player.band, 'Animals As Leaders', 'passes arguments into chained');
-  assert.equal(player.volume, 11, 'accepts no arguments in chain');
-};
-
-exports["test field"] = assert => {
-  let Num = field("constructor", 0);
-  assert.equal(Num.name, Number.name);
-  assert.ok(typeof(Num), "function");
-
-  let x = field("x");
-
-  [
-    [field("foo", { foo: 1 }), 1],
-    [field("foo")({ foo: 1 }), 1],
-    [field("bar", {}), undefined],
-    [field("bar")({}), undefined],
-    [field("hey", undefined), undefined],
-    [field("hey")(undefined), undefined],
-    [field("how", null), null],
-    [field("how")(null), null],
-    [x(1), undefined],
-    [x(undefined), undefined],
-    [x(null), null],
-    [x({ x: 1 }), 1],
-    [x({ x: 2 }), 2],
-  ].forEach(([actual, expected]) => assert.equal(actual, expected));
-};
-
-exports["test query"] = assert => {
-  let Num = query("constructor", 0);
-  assert.equal(Num.name, Number.name);
-  assert.ok(typeof(Num), "function");
-
-  let x = query("x");
-  let xy = query("x.y");
-
-  [
-    [query("foo", { foo: 1 }), 1],
-    [query("foo")({ foo: 1 }), 1],
-    [query("foo.bar", { foo: { bar: 2 } }), 2],
-    [query("foo.bar")({ foo: { bar: 2 } }), 2],
-    [query("foo.bar", { foo: 1 }), undefined],
-    [query("foo.bar")({ foo: 1 }), undefined],
-    [x(1), undefined],
-    [x(undefined), undefined],
-    [x(null), null],
-    [x({ x: 1 }), 1],
-    [x({ x: 2 }), 2],
-    [xy(1), undefined],
-    [xy(undefined), undefined],
-    [xy(null), null],
-    [xy({ x: 1 }), undefined],
-    [xy({ x: 2 }), undefined],
-    [xy({ x: { y: 1 } }), 1],
-    [xy({ x: { y: 2 } }), 2]
-  ].forEach(([actual, expected]) => assert.equal(actual, expected));
-};
-
-exports["test isInstance"] = assert => {
-  function X() {}
-  function Y() {}
-  let isX = isInstance(X);
-
-  [
-    isInstance(X, new X()),
-    isInstance(X)(new X()),
-    !isInstance(X, new Y()),
-    !isInstance(X)(new Y()),
-    isX(new X()),
-    !isX(new Y())
-  ].forEach(x => assert.ok(x));
-};
-
-exports["test is"] = assert => {
-
-  assert.deepEqual([ 1, 0, 1, 0, 1 ].map(is(1)),
-                   [ true, false, true, false, true ],
-                   "is can be partially applied");
-
-  assert.ok(is(1, 1));
-  assert.ok(!is({}, {}));
-  assert.ok(is()(1)()(1), "is is curried");
-  assert.ok(!is()(1)()(2));
-};
-
-exports["test isnt"] = assert => {
-
-  assert.deepEqual([ 1, 0, 1, 0, 1 ].map(isnt(0)),
-                   [ true, false, true, false, true ],
-                   "is can be partially applied");
-
-  assert.ok(!isnt(1, 1));
-  assert.ok(isnt({}, {}));
-  assert.ok(!isnt()(1)()(1));
-  assert.ok(isnt()(1)()(2));
-};
-
-exports["test debounce"] = (assert, done) => {
-  let counter = 0;
-  let fn = debounce(() => counter++, 100);
-
-  new Array(10).join(0).split("").forEach(fn);
-
-  assert.equal(counter, 0, "debounce does not fire immediately");
-  setTimeout(() => {
-    assert.equal(counter, 1, "function called after wait time");
-    fn();
-    setTimeout(() => {
-      assert.equal(counter, 2, "function able to be called again after wait");
-      done();
-    }, 150);
-  }, 200);
-};
-
-exports["test throttle"] = (assert, done) => {
-  let called = 0;
-  let attempt = 0;
-  let atleast100ms = false;
-  let throttledFn = throttle(() => {
-    called++;
-    if (called === 2) {
-      assert.equal(attempt, 10, "called twice, but attempted 10 times");
-      fn();
-    }
-    if (called === 3) {
-      assert.ok(atleast100ms, "atleast 100ms have passed");
-      assert.equal(attempt, 11, "called third, waits for delay to happen");
-      done();
-    }
-  }, 200);
-  let fn = () => ++attempt && throttledFn();
-
-  setTimeout(() => atleast100ms = true, 100);
-
-  new Array(11).join(0).split("").forEach(fn);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-globals.js
+++ /dev/null
@@ -1,30 +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';
-
-Object.defineProperty(this, 'global', { value: this });
-
-exports.testGlobals = function(assert) {
-  // the only globals in module scope should be:
-  //   module, exports, require, dump, console
-  assert.equal(typeof module, 'object', 'have "module", good');
-  assert.equal(typeof exports, 'object', 'have "exports", good');
-  assert.equal(typeof require, 'function', 'have "require", good');
-  assert.equal(typeof dump, 'function', 'have "dump", good');
-  assert.equal(typeof console, 'object', 'have "console", good');
-
-  // in particular, these old globals should no longer be present
-  assert.ok(!('packaging' in global), "no 'packaging', good");
-  assert.ok(!('memory' in global), "no 'memory', good");
-  assert.ok(/test-globals\.js$/.test(module.uri),
-     'should contain filename');
-};
-
-exports.testComponent = function (assert) {
-  assert.throws(() => {
-    Components;
-  }, /`Components` is not available/, 'using `Components` throws');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-heritage.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Class, extend, mix, obscure } = require('sdk/core/heritage');
-
-exports['test extend'] = function(assert) {
-  let ancestor = { a: 1 };
-  let descendant = extend(ancestor, {
-    b: 2,
-    get c() { return 3 },
-    d: function() { return 4 }
-  });
-
-  assert.ok(ancestor.isPrototypeOf(descendant),
-            'descendant inherits from ancestor');
-  assert.ok(descendant.b, 2, 'proprety was implemented');
-  assert.ok(descendant.c, 3, 'getter was implemented');
-  assert.ok(descendant.d(), 4, 'method was implemented');
-
-  /* Will be fixed once Bug 674195 is shipped.
-  assert.ok(Object.isFrozen(descendant),
-            'extend returns frozen objects');
-  */
-};
-
-exports['test mix'] = function(assert) {
-  let ancestor = { a: 1 }
-  let mixed = mix(extend(ancestor, { b: 1, c: 1 }), { c: 2 }, { d: 3 });
-
-  assert.deepEqual(JSON.parse(JSON.stringify(mixed)), { b: 1, c: 2, d: 3 },
-                   'properties mixed as expected');
-  assert.ok(ancestor.isPrototypeOf(mixed),
-            'first arguments ancestor is ancestor of result');
-};
-
-exports['test obscure'] = function(assert) {
-  let fixture = mix({ a: 1 }, obscure({ b: 2 }));
-
-  assert.equal(fixture.a, 1, 'a property is included');
-  assert.equal(fixture.b, 2, 'b proprety is included');
-  assert.ok(!Object.getOwnPropertyDescriptor(fixture, 'b').enumerable,
-            'obscured properties are non-enumerable');
-};
-
-exports['test inheritance'] = function(assert) {
-  let Ancestor = Class({
-    name: 'ancestor',
-    method: function () {
-      return 'hello ' + this.name;
-    }
-  });
-
-  assert.ok(Ancestor() instanceof Ancestor,
-            'can be instantiated without new');
-  assert.ok(new Ancestor() instanceof Ancestor,
-            'can also be instantiated with new');
-  assert.ok(Ancestor() instanceof Class,
-            'if ancestor not specified than defaults to Class');
-  assert.ok(Ancestor.prototype.extends, Class.prototype,
-            'extends of prototype points to ancestors prototype');
-
-
-  assert.equal(Ancestor().method(), 'hello ancestor',
-               'instance inherits defined properties');
-
-  let Descendant = Class({
-    extends: Ancestor,
-    name: 'descendant'
-  });
-
-  assert.ok(Descendant() instanceof Descendant,
-            'instantiates correctly');
-  assert.ok(Descendant() instanceof Ancestor,
-            'Inherits for passed `extends`');
-  assert.equal(Descendant().method(), 'hello descendant',
-               'propreties inherited');
-};
-
-exports['test immunity against __proto__'] = function(assert) {
-  let Foo = Class({ name: 'foo', hacked: false });
-
-  let Bar = Class({ extends: Foo, name: 'bar' });
-
-  assert.throws(function() {
-    Foo.prototype.__proto__ = { hacked: true };
-    if (Foo() instanceof Base && !Foo().hacked)
-      throw Error('can not change prototype chain');
-  }, 'prototype chain is immune to __proto__ hacks');
-
-  assert.throws(function() {
-    Foo.prototype.__proto__ = { hacked: true };
-    if (Bar() instanceof Foo && !Bar().hacked)
-      throw Error('can not change prototype chain');
-  }, 'prototype chain of decedants immune to __proto__ hacks');
-};
-
-exports['test super'] = function(assert) {
-  var Foo = Class({
-    initialize: function initialize(options) {
-      this.name = options.name;
-    }
-  });
-
-  var Bar = Class({
-    extends: Foo,
-    initialize: function Bar(options) {
-      Foo.prototype.initialize.call(this, options);
-      this.type = 'bar';
-    }
-  });
-
-  var bar = Bar({ name: 'test' });
-
-  assert.equal(bar.type, 'bar', 'bar initializer was called');
-  assert.equal(bar.name, 'test', 'bar initializer called Foo initializer');
-};
-
-exports['test initialize'] = function(assert) {
-  var Dog = Class({
-    initialize: function initialize(name) {
-      this.name = name;
-    },
-    type: 'dog',
-    bark: function bark() {
-      return 'Ruff! Ruff!'
-    }
-  });
-
-  var fluffy = Dog('Fluffy');   // instatiation
-  assert.ok(fluffy instanceof Dog,
-            'instanceof works as expected');
-  assert.ok(fluffy instanceof Class,
-            'inherits form Class if not specified otherwise');
-  assert.ok(fluffy.name, 'fluffy',
-            'initialize unless specified otherwise');
-};
-
-exports['test complements regular inheritace'] = function(assert) {
-  let Base = Class({ name: 'base' });
-
-  function Type() {
-      // ...
-  }
-  Type.prototype = Object.create(Base.prototype);
-  Type.prototype.run = function() {
-    // ...
-  };
-
-  let value = new Type();
-
-  assert.ok(value instanceof Type, 'creates instance of Type');
-  assert.ok(value instanceof Base, 'inherits from Base');
-  assert.equal(value.name, 'base', 'inherits properties from Base');
-
-
-  let SubType = Class({
-    extends: Type,
-    sub: 'type'
-  });
-
-  let fixture = SubType();
-
-  assert.ok(fixture instanceof Base, 'is instance of Base');
-  assert.ok(fixture instanceof Type, 'is instance of Type');
-  assert.ok(fixture instanceof SubType, 'is instance of SubType');
-
-  assert.equal(fixture.sub, 'type', 'proprety is defined');
-  assert.equal(fixture.run, Type.prototype.run, 'proprety is inherited');
-  assert.equal(fixture.name, 'base', 'inherits base properties');
-};
-
-exports['test extends object'] = function(assert) {
-  let prototype = { constructor: function() { return this; }, name: 'me' };
-  let Foo = Class({
-    extends: prototype,
-    value: 2
-  });
-  let foo = new Foo();
-
-  assert.ok(foo instanceof Foo, 'instance of Foo');
-  assert.ok(!(foo instanceof Class), 'is not instance of Class');
-  assert.ok(prototype.isPrototypeOf(foo), 'inherits from given prototype');
-  assert.equal(Object.getPrototypeOf(Foo.prototype), prototype,
-               'contsructor prototype inherits from extends option');
-  assert.equal(foo.value, 2, 'property is defined');
-  assert.equal(foo.name, 'me', 'prototype proprety is inherited');
-};
-
-
-var HEX = Class({
-  hex: function hex() {
-    return '#' + this.color;
-  }
-});
-
-var RGB = Class({
-  red: function red() {
-    return parseInt(this.color.substr(0, 2), 16);
-  },
-  green: function green() {
-    return parseInt(this.color.substr(2, 2), 16);
-  },
-  blue: function blue() {
-    return parseInt(this.color.substr(4, 2), 16);
-  }
-});
-
-var CMYK = Class({
-  black: function black() {
-    var color = Math.max(Math.max(this.red(), this.green()), this.blue());
-    return (1 - color / 255).toFixed(4);
-  },
-  magenta: function magenta() {
-    var K = this.black();
-    return (((1 - this.green() / 255).toFixed(4) - K) / (1 - K)).toFixed(4);
-  },
-  yellow: function yellow() {
-    var K = this.black();
-    return (((1 - this.blue() / 255).toFixed(4) - K) / (1 - K)).toFixed(4);
-  },
-  cyan: function cyan() {
-    var K = this.black();
-    return (((1 - this.red() / 255).toFixed(4) - K) / (1 - K)).toFixed(4);
-  }
-});
-
-var Color = Class({
-  implements: [ HEX, RGB, CMYK ],
-  initialize: function initialize(color) {
-    this.color = color;
-  }
-});
-
-exports['test composition'] = function(assert) {
-  var pink = Color('FFC0CB');
-
-  assert.equal(pink.red(), 255, 'red() works');
-  assert.equal(pink.green(), 192, 'green() works');
-  assert.equal(pink.blue(), 203, 'blue() works');
-
-  assert.equal(pink.magenta(), 0.2471, 'magenta() works');
-  assert.equal(pink.yellow(), 0.2039, 'yellow() works');
-  assert.equal(pink.cyan(), 0.0000, 'cyan() works');
-
-  assert.ok(pink instanceof Color, 'is instance of Color');
-  assert.ok(pink instanceof Class, 'is instance of Class');
-};
-
-var Point = Class({
-  initialize: function initialize(x, y) {
-    this.x = x;
-    this.y = y;
-  },
-  toString: function toString() {
-    return this.x + ':' + this.y;
-  }
-})
-
-var Pixel = Class({
-  extends: Point,
-  implements: [ Color ],
-  initialize: function initialize(x, y, color) {
-    Color.prototype.initialize.call(this, color);
-    Point.prototype.initialize.call(this, x, y);
-  },
-  toString: function toString() {
-    return this.hex() + '@' + Point.prototype.toString.call(this)
-  }
-});
-
-exports['test compostion with inheritance'] = function(assert) {
-  var pixel = Pixel(11, 23, 'CC3399');
-
-  assert.equal(pixel.toString(), '#CC3399@11:23', 'stringifies correctly');
-  assert.ok(pixel instanceof Pixel, 'instance of Pixel');
-  assert.ok(pixel instanceof Point, 'instance of Point');
-};
-
-exports['test composition with objects'] = function(assert) {
-  var A = { a: 1, b: 1 };
-  var B = Class({ b: 2, c: 2 });
-  var C = { c: 3 };
-  var D = { d: 4 };
-
-  var ABCD = Class({
-    implements: [ A, B, C, D ],
-    e: 5
-  });
-
-  var f = ABCD();
-
-  assert.equal(f.a, 1, 'inherits A.a');
-  assert.equal(f.b, 2, 'inherits B.b overrides A.b');
-  assert.equal(f.c, 3, 'inherits C.c overrides B.c');
-  assert.equal(f.d, 4, 'inherits D.d');
-  assert.equal(f.e, 5, 'implements e');
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-hidden-frame.js
+++ /dev/null
@@ -1,70 +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 { Loader } = require("sdk/test/loader");
-const hiddenFrames = require("sdk/frame/hidden-frame");
-const { HiddenFrame } = hiddenFrames;
-
-exports["test Frame"] = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,<!DOCTYPE%20html>";
-
-  let hiddenFrame = hiddenFrames.add(HiddenFrame({
-    onReady: function () {
-      assert.equal(this.element.contentWindow.location, "about:blank",
-                       "HiddenFrame loads about:blank by default.");
-
-      function onDOMReady() {
-        hiddenFrame.element.removeEventListener("DOMContentLoaded", onDOMReady);
-        assert.equal(hiddenFrame.element.contentWindow.location, url,
-                         "HiddenFrame loads the specified content.");
-        done();
-      }
-
-      this.element.addEventListener("DOMContentLoaded", onDOMReady);
-      this.element.setAttribute("src", url);
-    }
-  }));
-};
-
-exports["test frame removed properly"] = function(assert, done) {
-  let url = "data:text/html;charset=utf-8,<!DOCTYPE%20html>";
-
-  let hiddenFrame = hiddenFrames.add(HiddenFrame({
-    onReady: function () {
-      let frame = this.element;
-      assert.ok(frame.parentNode, "frame has a parent node");
-      hiddenFrames.remove(hiddenFrame);
-      assert.ok(!frame.parentNode, "frame no longer has a parent node");
-      done();
-    }
-  }));
-};
-
-exports["test unload detaches panels"] = function(assert, done) {
-  let loader = Loader(module);
-  let { add, remove, HiddenFrame } = loader.require("sdk/frame/hidden-frame");
-  let frames = []
-
-  function ready() {
-    frames.push(this.element);
-    if (frames.length === 2) complete();
-  }
-
-  add(HiddenFrame({ onReady: ready }));
-  add(HiddenFrame({ onReady: ready }));
-
-  function complete() {
-    frames.forEach(function(frame) {
-      assert.ok(frame.parentNode, "frame is in the document");
-    })
-    loader.unload();
-    frames.forEach(function(frame) {
-      assert.ok(!frame.parentNode, "frame isn't in the document'");
-    });
-    done();
-  }
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-host-events.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { defer, all } = require('sdk/core/promise');
-const { setTimeout } = require('sdk/timers');
-const { request, response } = require('sdk/addon/host');
-const { send } = require('sdk/addon/events');
-const { filter } = require('sdk/event/utils');
-const { on, emit, off } = require('sdk/event/core');
-
-var stream = filter(request, (data) => /sdk-x-test/.test(data.event));
-
-exports.testSend = function (assert, done) {
-  on(stream, 'data', handle);
-  send('sdk-x-test-simple', { title: 'my test data' }).then((data) => {
-    assert.equal(data.title, 'my response', 'response is handled');
-    off(stream, 'data', handle);
-    done();
-  }, (reason) => {
-    assert.fail('should not call reject');
-  });
-  function handle (e) {
-    assert.equal(e.event, 'sdk-x-test-simple', 'correct event name');
-    assert.ok(e.id != null, 'message has an ID');
-    assert.equal(e.data.title, 'my test data', 'serialized data passes');
-    e.data.title = 'my response';
-    emit(response, 'data', e);
-  }
-};
-
-exports.testSendError = function (assert, done) {
-  on(stream, 'data', handle);
-  send('sdk-x-test-error', { title: 'my test data' }).then((data) => {
-    assert.fail('should not call success');
-  }, (reason) => {
-    assert.equal(reason, 'ErrorInfo', 'should reject with error/reason');
-    off(stream, 'data', handle);
-    done();
-  });
-  function handle (e) {
-    e.error = 'ErrorInfo';
-    emit(response, 'data', e);
-  }
-};
-
-exports.testMultipleSends = function (assert, done) {
-  let count = 0;
-  let ids = [];
-  on(stream, 'data', handle);
-  ['firefox', 'thunderbird', 'rust'].map(data =>
-    send('sdk-x-test-multi', { data: data }).then(val => {
-    assert.ok(val === 'firefox' || val === 'rust', 'successful calls resolve correctly');
-    if (++count === 3) {
-      off(stream, 'data', handle);
-      done();
-    }
-  }, reason => {
-    assert.equal(reason.error, 'too blue', 'rejected calls are rejected');
-    if (++count === 3) {
-      off(stream, 'data', handle);
-      done();
-    }
-  }));
-
-  function handle (e) {
-    if (e.data !== 'firefox' || e.data !== 'rust')
-      e.error = { data: e.data, error: 'too blue' };
-    assert.ok(!~ids.indexOf(e.id), 'ID should be unique');
-    assert.equal(e.event, 'sdk-x-test-multi', 'has event name');
-    ids.push(e.id);
-    emit(response, 'data', e);
-  }
-};
-
-exports.testSerialization = function (assert, done) {
-  on(stream, 'data', handle);
-  let object = { title: 'my test data' };
-  let resObject;
-  send('sdk-x-test-serialize', object).then(data => {
-    data.title = 'another title';
-    assert.equal(object.title, 'my test data', 'original object not modified');
-    assert.equal(resObject.title, 'new title', 'object passed by value from host');
-    off(stream, 'data', handle);
-    done();
-  }, (reason) => {
-    assert.fail('should not call reject');
-  });
-  function handle (e) {
-    e.data.title = 'new title';
-    assert.equal(object.title, 'my test data', 'object passed by value to host');
-    resObject = e.data;
-    emit(response, 'data', e);
-  }
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-hotkeys.js
+++ /dev/null
@@ -1,183 +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 { Hotkey } = require("sdk/hotkeys");
-const { keyDown } = require("sdk/dom/events/keys");
-const { Loader } = require('sdk/test/loader');
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-
-const element = getMostRecentBrowserWindow().document.documentElement;
-
-exports["test hotkey: function key"] = function(assert, done) {
-  var showHotKey = Hotkey({
-    combo: "f1",
-    onPress: function() {
-      assert.pass("first callback is called");
-      assert.equal(this, showHotKey,
-        'Context `this` in `onPress` should be the hotkey object');
-      keyDown(element, "f2");
-      showHotKey.destroy();
-    }
-  });
-
-  var hideHotKey = Hotkey({
-    combo: "f2",
-    onPress: function() {
-      assert.pass("second callback is called");
-      hideHotKey.destroy();
-      done();
-    }
-  });
-
-  keyDown(element, "f1");
-};
-
-exports["test hotkey: accel alt shift"] = function(assert, done) {
-  var showHotKey = Hotkey({
-    combo: "accel-shift-6",
-    onPress: function() {
-      assert.pass("first callback is called");
-      keyDown(element, "accel-alt-shift-6");
-      showHotKey.destroy();
-    }
-  });
-
-  var hideHotKey = Hotkey({
-    combo: "accel-alt-shift-6",
-    onPress: function() {
-      assert.pass("second callback is called");
-      hideHotKey.destroy();
-      done();
-    }
-  });
-
-  keyDown(element, "accel-shift-6");
-};
-
-exports["test hotkey meta & control"] = function(assert, done) {
-  var showHotKey = Hotkey({
-    combo: "meta-3",
-    onPress: function() {
-      assert.pass("first callback is called");
-      keyDown(element, "alt-control-shift-b");
-      showHotKey.destroy();
-    }
-  });
-
-  var hideHotKey = Hotkey({
-    combo: "Ctrl-Alt-Shift-B",
-    onPress: function() {
-      assert.pass("second callback is called");
-      hideHotKey.destroy();
-      done();
-    }
-  });
-
-  keyDown(element, "meta-3");
-};
-
-exports["test hotkey: control-1 / meta--"] = function(assert, done) {
-  var showHotKey = Hotkey({
-    combo: "control-1",
-    onPress: function() {
-      assert.pass("first callback is called");
-      keyDown(element, "meta--");
-      showHotKey.destroy();
-    }
-  });
-
-  var hideHotKey = Hotkey({
-    combo: "meta--",
-    onPress: function() {
-      assert.pass("second callback is called");
-      hideHotKey.destroy();
-      done();
-    }
-  });
-
-  keyDown(element, "control-1");
-};
-
-exports["test invalid combos"] = function(assert) {
-  assert.throws(function() {
-    Hotkey({
-      combo: "d",
-      onPress: function() {}
-    });
-  }, "throws if no modifier is present");
-  assert.throws(function() {
-    Hotkey({
-      combo: "alt",
-      onPress: function() {}
-    });
-  }, "throws if no key is present");
-  assert.throws(function() {
-    Hotkey({
-      combo: "alt p b",
-      onPress: function() {}
-    });
-  }, "throws if more then one key is present");
-};
-
-exports["test no exception on unmodified keypress"] = function(assert) {
-  var someHotkey = Hotkey({
-    combo: "control-alt-1",
-    onPress: () => {}
-  });
-  keyDown(element, "a");
-  assert.pass("No exception throw, unmodified keypress passed");
-  someHotkey.destroy();
-};
-
-exports["test hotkey: automatic destroy"] = function*(assert) {
-  // Hacky way to be able to create unloadable modules via makeSandboxedLoader.
-  let loader = Loader(module);
-
-  var called = false;
-  var hotkey = loader.require("sdk/hotkeys").Hotkey({
-    combo: "accel-shift-x",
-    onPress: () => called = true
-  });
-
-  // Unload the module so that previous hotkey is automatically destroyed
-  loader.unload();
-
-  // Ensure that the hotkey is really destroyed
-  keyDown(element, "accel-shift-x");
-
-  assert.ok(!called, "Hotkey is destroyed and not called.");
-
-  // create a new hotkey for a different set
-  yield new Promise(resolve => {
-    let key = Hotkey({
-      combo: "accel-shift-y",
-      onPress: () => {
-        key.destroy();
-        assert.pass("accel-shift-y was pressed.");
-        resolve();
-      }
-    });
-    keyDown(element, "accel-shift-y");
-  });
-
-  assert.ok(!called, "Hotkey is still not called, in time it would take.");
-
-  // create a new hotkey for the same set
-  yield new Promise(resolve => {
-    let key = Hotkey({
-      combo: "accel-shift-x",
-      onPress: () => {
-        key.destroy();
-        assert.pass("accel-shift-x was pressed.");
-        resolve();
-      }
-    });
-    keyDown(element, "accel-shift-x");
-  });
-
-  assert.ok(!called, "Hotkey is still not called, and reusing is ok.");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-httpd.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/. */
-
-const port = 8099;
-const file = require("sdk/io/file");
-const { pathFor } = require("sdk/system");
-const { Loader } = require("sdk/test/loader");
-const options = require("sdk/test/options");
-
-const loader = Loader(module);
-const httpd = loader.require("./lib/httpd");
-if (options.parseable || options.verbose)
-  loader.sandbox("./lib/httpd").DEBUG = true;
-
-exports.testBasicHTTPServer = function(assert, done) {
-  // Use the profile directory for the temporary file as that will be deleted
-  // when tests are complete
-  let basePath = pathFor("ProfD");
-  let filePath = file.join(basePath, 'test-httpd.txt');
-  let content = "This is the HTTPD test file.\n";
-  let fileStream = file.open(filePath, 'w');
-  fileStream.write(content);
-  fileStream.close();
-
-  let srv = httpd.startServerAsync(port, basePath);
-
-  // Request this very file.
-  let Request = require('sdk/request').Request;
-  Request({
-    url: "http://localhost:" + port + "/test-httpd.txt",
-    onComplete: function (response) {
-      assert.equal(response.text, content);
-      srv.stop(done);
-    }
-  }).get();
-};
-
-exports.testDynamicServer = function (assert, done) {
-  let content = "This is the HTTPD test file.\n";
-
-  let srv = httpd.startServerAsync(port);
-
-  // See documentation here:
-  //http://doxygen.db48x.net/mozilla/html/interfacensIHttpServer.html#a81fc7e7e29d82aac5ce7d56d0bedfb3a
-  //http://doxygen.db48x.net/mozilla/html/interfacensIHttpRequestHandler.html
-  srv.registerPathHandler("/test-httpd.txt", function handle(request, response) {
-    // Add text content type, only to avoid error in `Request` API
-    response.setHeader("Content-Type", "text/plain", false);
-    response.write(content);
-  });
-
-  // Request this very file.
-  let Request = require('sdk/request').Request;
-  Request({
-    url: "http://localhost:" + port + "/test-httpd.txt",
-    onComplete: function (response) {
-      assert.equal(response.text, content);
-      srv.stop(done);
-    }
-  }).get();
-};
-
-exports.testAutomaticPortSelection = function (assert, done) {
-  const srv = httpd.startServerAsync(-1);
-
-  const port = srv.identity.primaryPort;
-  assert.ok(0 <= port && port <= 65535);
-
-  srv.stop(done);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-indexed-db.js
+++ /dev/null
@@ -1,182 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { indexedDB, IDBKeyRange, DOMException
-      } = require("sdk/indexed-db");
-
-exports["test indexedDB is frozen"] = function(assert){
-  let original = indexedDB.open;
-  let f = function(){};
-  assert.throws(function(){indexedDB.open = f});
-  assert.equal(indexedDB.open,original);
-  assert.notEqual(indexedDB.open,f);
-
-};
-
-exports["test db variables"] = function(assert) {
-  [ indexedDB, IDBKeyRange, DOMException
-  ].forEach(function(value) {
-    assert.notEqual(typeof(value), "undefined", "variable is defined");
-  });
-}
-
-exports["test open"] = function(assert, done) {
-  testOpen(0, assert, done);
-}
-
-function testOpen(step, assert, done) {
-  const dbName = "MyTestDatabase";
-  const openParams = [
-    { dbName: "MyTestDatabase", dbVersion: 10 },
-    { dbName: "MyTestDatabase" },
-    { dbName: "MyTestDatabase", dbOptions: { storage: "temporary" } },
-    { dbName: "MyTestDatabase", dbOptions: { version: 20, storage: "default" } }
-  ];
-
-  let params = openParams[step];
-
-  let request;
-  let expectedStorage;
-  let expectedVersion;
-  let upgradeNeededCalled = false;
-  if ("dbVersion" in params) {
-    request = indexedDB.open(params.dbName, params.dbVersion);
-    expectedVersion = params.dbVersion;
-    expectedStorage = "persistent";
-  } else if ("dbOptions" in params) {
-    request = indexedDB.open(params.dbName, params.dbOptions);
-    if ("version" in params.dbOptions) {
-      expectedVersion = params.dbOptions.version;
-    } else {
-      expectedVersion = 1;
-    }
-    if ("storage" in params.dbOptions) {
-      expectedStorage = params.dbOptions.storage;
-    } else {
-      expectedStorage = "persistent";
-    }
-  } else {
-    request = indexedDB.open(params.dbName);
-    expectedVersion = 1;
-    expectedStorage = "persistent";
-  }
-  request.onerror = function(event) {
-    assert.fail("Failed to open indexedDB")
-    done();
-  }
-  request.onupgradeneeded = function(event) {
-    upgradeNeededCalled = true;
-    assert.equal(event.oldVersion, 0, "Correct old version");
-  }
-  request.onsuccess = function(event) {
-    assert.pass("IndexedDB was open");
-    assert.equal(upgradeNeededCalled, true, "Upgrade needed called");
-    let db = request.result;
-    assert.equal(db.storage, expectedStorage, "Storage is correct");
-    db.onversionchange = function(event) {
-      assert.equal(event.oldVersion, expectedVersion, "Old version is correct");
-      db.close();
-    }
-    if ("dbOptions" in params) {
-      request = indexedDB.deleteDatabase(params.dbName, params.dbOptions);
-    } else {
-      request = indexedDB.deleteDatabase(params.dbName);
-    }
-    request.onerror = function(event) {
-      assert.fail("Failed to delete indexedDB")
-      done();
-    }
-    request.onsuccess = function(event) {
-      assert.pass("IndexedDB was deleted");
-
-      if (++step == openParams.length) {
-        done();
-      } else {
-        testOpen(step, assert, done);
-      }
-    }
-  }
-}
-
-exports["test dbname is unprefixed"] = function(assert, done) {
-  // verify fixes in https://bugzilla.mozilla.org/show_bug.cgi?id=786688
-  let dbName = "dbname-unprefixed";
-  let request = indexedDB.open(dbName);
-  request.onerror = function(event) {
-    assert.fail("Failed to open db");
-    done();
-  };
-  request.onsuccess = function(event) {
-    assert.equal(request.result.name, dbName);
-    done();
-  };
-};
-
-exports["test structuring the database"] = function(assert, done) {
-  // This is what our customer data looks like.
-  let customerData = [
-    { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
-    { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
-  ];
-  let dbName = "the_name";
-  let request = indexedDB.open(dbName, 2);
-  request.onerror = function(event) {
-    assert.fail("Failed to open db");
-    done();
-  };
-  request.onsuccess = function(event) {
-    assert.pass("transaction is complete");
-    testRead(assert, done);
-  }
-  request.onupgradeneeded = function(event) {
-    assert.pass("data base upgrade")
-
-    var db = event.target.result;
-
-    // Create an objectStore to hold information about our customers. We"re
-    // going to use "ssn" as our key path because it"s guaranteed to be
-    // unique.
-    var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
-
-    // Create an index to search customers by name. We may have duplicates
-    // so we can"t use a unique index.
-    objectStore.createIndex("name", "name", { unique: false });
-
-    // Create an index to search customers by email. We want to ensure that
-    // no two customers have the same email, so use a unique index.
-    objectStore.createIndex("email", "email", { unique: true });
-
-    // Store values in the newly created objectStore.
-    customerData.forEach(function(data) {
-      objectStore.add(data);
-    });
-    assert.pass("data added to object store");
-  };
-};
-
-function testRead(assert, done) {
-  let dbName = "the_name";
-  let request = indexedDB.open(dbName, 2);
-  request.onsuccess = function(event) {
-    assert.pass("data opened")
-    var db = event.target.result;
-    let transaction = db.transaction(["customers"]);
-    var objectStore = transaction.objectStore("customers");
-    var request = objectStore.get("444-44-4444");
-    request.onerror = function(event) {
-      assert.fail("Failed to retrive data")
-    };
-    request.onsuccess = function(event) {
-      // Do something with the request.result!
-      assert.equal(request.result.name, "Bill", "Name is correct");
-      done();
-    };
-  };
-  request.onerror = function() {
-    assert.fail("failed to open db");
-  };
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-jetpack-id.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";
-
-var getID = require("jetpack-id/index");
-
-exports["test Returns GUID when `id` GUID"] = assert => {
-  var guid = "{8490ae4f-93bc-13af-80b3-39adf9e7b243}";
-  assert.equal(getID({ id: guid }), guid);
-};
-
-exports["test Returns domain id when `id` domain id"] = assert => {
-  var id = "my-addon@jetpack";
-  assert.equal(getID({ id: id }), id);
-};
-
-exports["test allows underscores in name"] = assert => {
-  var name = "my_addon";
-  assert.equal(getID({ name: name }), `@${name}`);
-};
-
-exports["test allows underscores in id"] = assert => {
-  var id = "my_addon@jetpack";
-  assert.equal(getID({ id: id }), id);
-};
-
-exports["test Returns valid name when `name` exists"] = assert => {
-  var id = "my-addon";
-  assert.equal(getID({ name: id }), `@${id}`);
-};
-
-
-exports["test Returns null when `id` and `name` do not exist"] = assert => {
-  assert.equal(getID({}), null)
-}
-
-exports["test Returns null when no object passed in"] = assert => {
-  assert.equal(getID(), null)
-}
-
-exports["test Returns null when `id` exists but not GUID/domain"] = assert => {
-  var id = "my-addon";
-  assert.equal(getID({ id: id }), null);
-}
-
-exports["test Returns null when `id` contains multiple @"] = assert => {
-  assert.equal(getID({ id: "my@addon@yeah" }), null);
-};
-
-exports["test Returns null when `id` or `name` specified in domain format but has invalid characters"] = assert => {
-  [" ", "!", "/", "$", "  ", "~", "("].forEach(sym => {
-    assert.equal(getID({ id: "my" + sym + "addon@domain" }), null);
-    assert.equal(getID({ name: "my" + sym + "addon" }), null);
-  });
-};
-
-exports["test Returns null, does not crash, when providing non-string properties for `name` and `id`"] = assert => {
-  assert.equal(getID({ id: 5 }), null);
-  assert.equal(getID({ name: 5 }), null);
-  assert.equal(getID({ name: {} }), null);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-keyboard-observer.js
+++ /dev/null
@@ -1,36 +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 { keyPress } = require("sdk/dom/events/keys");
-const { Loader } = require("sdk/test/loader");
-const timer = require("sdk/timers");
-
-exports["test unload keyboard observer"] = function(assert, done) {
-  let loader = Loader(module);
-  let element = loader.require("sdk/deprecated/window-utils").
-                       activeBrowserWindow.document.documentElement;
-  let observer = loader.require("sdk/keyboard/observer").
-                        observer;
-  let called = 0;
-
-  observer.on("keypress", function () { called++; });
-
-  // dispatching "keypress" event to trigger observer listeners.
-  keyPress(element, "accel-%");
-
-  // Unload the module.
-  loader.unload();
-
-  // dispatching "keypress" even once again.
-  keyPress(element, "accel-%");
-
-  // Enqueuing asserts to make sure that assertion is not performed early.
-  timer.setTimeout(function () {
-    assert.equal(called, 1, "observer was called before unload only.");
-    done();
-  }, 0);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-keyboard-utils.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const utils = require("sdk/keyboard/utils");
-const runtime = require("sdk/system/runtime");
-
-const isMac = runtime.OS === "Darwin";
-
-exports["test toString"] = function(assert) {
-  assert.equal(utils.toString({
-    key: "B",
-    modifiers: [ "Shift", "Ctrl" ]
-  }), "Shift-Ctrl-B", "toString does not normalizes JSON");
-
-  assert.equal(utils.toString({
-    key: "C",
-    modifiers: [],
-  }), "C", "Works with objects with empty array of modifiers");
-
-  assert.equal(utils.toString(Object.create((function Type() {}).prototype, {
-    key: { value: "d" },
-    modifiers: { value: [ "alt" ] },
-    method: { value: function() {} }
-  })), "alt-d", "Works with non-json objects");
-
-  assert.equal(utils.toString({
-    modifiers: [ "shift", "alt" ]
-  }), "shift-alt-", "works with only modifiers");
-};
-
-exports["test toJSON"] = function(assert) {
-  assert.deepEqual(utils.toJSON("Shift-Ctrl-B"), {
-    key: "b",
-    modifiers: [ "control", "shift" ]
-  }, "toJSON normalizes input");
-
-  assert.deepEqual(utils.toJSON("Meta-Alt-option-C"), {
-    key: "c",
-    modifiers: [ "alt", "meta" ]
-  }, "removes dublicates");
-
-  assert.deepEqual(utils.toJSON("AccEl+sHiFt+Z", "+"), {
-    key: "z",
-    modifiers: isMac ? [ "meta", "shift" ] : [ "control", "shift" ]
-  }, "normalizes OS specific keys and adjustes seperator");
-};
-
-exports["test normalize"] = function assert(assert) {
-  assert.equal(utils.normalize("Shift Ctrl A control ctrl", " "),
-               "control shift a", "removes reapeted modifiers");
-  assert.equal(utils.normalize("shift-ctrl-left"), "control-shift-left",
-               "normilizes non printed characters");
-
-  assert.throws(function() {
-    utils.normalize("shift-alt-b-z");
-  }, "throws if contains more then on non-modifier key");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-l10n-locale.js
+++ /dev/null
@@ -1,60 +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 { Cu, Cc, Ci } = require("chrome");
-const { Services } = Cu.import('resource://gre/modules/Services.jsm');
-const { findClosestLocale,
-        getPreferedLocales } = require("sdk/l10n/locale");
-
-exports.testFindClosestLocale = function(assert) {
-  // Second param of findClosestLocale (aMatchLocales) have to be in lowercase
-  assert.equal(findClosestLocale([], []), null,
-                   "When everything is empty we get null");
-
-  assert.equal(findClosestLocale(["en", "en-US"], ["en"]),
-                   "en", "We always accept exact match first 1/5");
-  assert.equal(findClosestLocale(["en-US", "en"], ["en"]),
-                   "en", "We always accept exact match first 2/5");
-  assert.equal(findClosestLocale(["en", "en-US"], ["en-us"]),
-                   "en-US", "We always accept exact match first 3/5");
-  assert.equal(findClosestLocale(["ja-JP-mac", "ja", "ja-JP"], ["ja-jp"]),
-                   "ja-JP", "We always accept exact match first 4/5");
-  assert.equal(findClosestLocale(["ja-JP-mac", "ja", "ja-JP"], ["ja-jp-mac"]),
-                   "ja-JP-mac", "We always accept exact match first 5/5");
-
-  assert.equal(findClosestLocale(["en", "en-GB"], ["en-us"]),
-                   "en", "We accept more generic locale, when there is no exact match 1/2");
-  assert.equal(findClosestLocale(["en-ZA", "en"], ["en-gb"]),
-                   "en", "We accept more generic locale, when there is no exact match 2/2");
-
-  assert.equal(findClosestLocale(["ja-JP"], ["ja"]),
-                   "ja-JP", "We accept more specialized locale, when there is no exact match 1/2");
-  // Better to select "ja" in this case but behave same as current AddonManager
-  assert.equal(findClosestLocale(["ja-JP-mac", "ja"], ["ja-jp"]),
-                   "ja-JP-mac", "We accept more specialized locale, when there is no exact match 2/2");
-
-  assert.equal(findClosestLocale(["en-US"], ["en-us"]),
-                   "en-US", "We keep the original one as result 1/2");
-  assert.equal(findClosestLocale(["en-us"], ["en-us"]),
-                   "en-us", "We keep the original one as result 2/2");
-
-  assert.equal(findClosestLocale(["ja-JP-mac"], ["ja-jp-mac"]),
-                   "ja-JP-mac", "We accept locale with 3 parts");
-  assert.equal(findClosestLocale(["ja-JP"], ["ja-jp-mac"]),
-                   "ja-JP", "We accept locale with 2 parts from locale with 3 parts");
-  assert.equal(findClosestLocale(["ja"], ["ja-jp-mac"]),
-                   "ja", "We accept locale with 1 part from locale with 3 parts");
-};
-
-exports.testGetPreferedLocales = function(assert) {
-  let currentLocales = Services.locale.getRequestedLocales();
-
-  Services.locale.setRequestedLocales(['pl']);
-
-  assert.equal(getPreferedLocales().includes('en-US'), true, "en-US should always be in the list");
-
-  Services.locale.setRequestedLocales(currentLocales);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-l10n-plural-rules.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-const { getRulesForLocale } = require("sdk/l10n/plural-rules");
-
-// For more information, please visit unicode website:
-// http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
-
-function map(assert, f, n, form) {
-  assert.equal(f(n), form, n + " maps to '" + form + "'");
-}
-
-exports.testFrench = function(assert) {
-  let f = getRulesForLocale("fr");
-  map(assert, f, -1, "other");
-  map(assert, f, 0, "one");
-  map(assert, f, 1, "one");
-  map(assert, f, 1.5, "one");
-  map(assert, f, 2, "other");
-  map(assert, f, 100, "other");
-}
-
-exports.testEnglish = function(assert) {
-  let f = getRulesForLocale("en");
-  map(assert, f, -1, "other");
-  map(assert, f, 0, "other");
-  map(assert, f, 1, "one");
-  map(assert, f, 1.5, "other");
-  map(assert, f, 2, "other");
-  map(assert, f, 100, "other");
-}
-
-exports.testArabic = function(assert) {
-  let f = getRulesForLocale("ar");
-  map(assert, f, -1, "other");
-  map(assert, f, 0, "zero");
-  map(assert, f, 0.5, "other");
-
-  map(assert, f, 1, "one");
-  map(assert, f, 1.5, "other");
-
-  map(assert, f, 2, "two");
-  map(assert, f, 2.5, "other");
-
-  map(assert, f, 3, "few");
-  map(assert, f, 3.5, "few"); // I'd expect it to be 'other', but the unicode.org
-                            // algorithm computes 'few'.
-  map(assert, f, 5, "few");
-  map(assert, f, 10, "few");
-  map(assert, f, 103, "few");
-  map(assert, f, 105, "few");
-  map(assert, f, 110, "few");
-  map(assert, f, 203, "few");
-  map(assert, f, 205, "few");
-  map(assert, f, 210, "few");
-
-  map(assert, f, 11, "many");
-  map(assert, f, 50, "many");
-  map(assert, f, 99, "many");
-  map(assert, f, 111, "many");
-  map(assert, f, 150, "many");
-  map(assert, f, 199, "many");
-
-  map(assert, f, 100, "other");
-  map(assert, f, 101, "other");
-  map(assert, f, 102, "other");
-  map(assert, f, 200, "other");
-  map(assert, f, 201, "other");
-  map(assert, f, 202, "other");
-}
-
-exports.testJapanese = function(assert) {
-  // Japanese doesn't have plural forms.
-  let f = getRulesForLocale("ja");
-  map(assert, f, -1, "other");
-  map(assert, f, 0, "other");
-  map(assert, f, 1, "other");
-  map(assert, f, 1.5, "other");
-  map(assert, f, 2, "other");
-  map(assert, f, 100, "other");
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-lang-type.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict"
-
-var utils = require("sdk/lang/type");
-
-exports["test function"] = function (assert) {
-  assert.equal(utils.isFunction(function(){}), true, "value is a function");
-  assert.equal(utils.isFunction(Object), true, "Object is a function");
-  assert.equal(utils.isFunction(new Function("")), true, "Genertaed value is a function");
-  assert.equal(utils.isFunction({}), false, "object is not a function");
-  assert.equal(utils.isFunction(4), false, "number is not a function");
-};
-
-exports["test atoms"] = function (assert) {
-  assert.equal(utils.isPrimitive(2), true, "number is a primitive");
-  assert.equal(utils.isPrimitive(NaN), true, "`NaN` is a primitve");
-  assert.equal(utils.isPrimitive(undefined), true, "`undefined` is a primitive");
-  assert.equal(utils.isPrimitive(null), true, "`null` is a primitive");
-  assert.equal(utils.isPrimitive(Infinity), true, "`Infinity` is a primitive");
-  assert.equal(utils.isPrimitive("foo"), true, "strings are a primitive");
-  assert.ok(utils.isPrimitive(true) && utils.isPrimitive(false),
-            "booleans are primitive");
-};
-
-exports["test object"] = function (assert) {
-  assert.equal(utils.isObject({}), true, "`{}` is an object");
-  assert.ok(!utils.isObject(null), "`null` is not an object");
-  assert.ok(!utils.isObject(Object), "functions is not an object");
-};
-
-exports["test generator"] = function (assert) {
-  assert.equal(utils.isGenerator(function*(){}), true, "`function*(){}` is a generator");
-  assert.equal(utils.isGenerator(function(){}), false, "`function(){}` is not a generator");
-  assert.equal(utils.isGenerator(() => {}), false, "`() => {}` is not a generator");
-  assert.equal(utils.isGenerator({}), false, "`{}` is not a generator");
-  assert.equal(utils.isGenerator(1), false, "`1` is not a generator");
-  assert.equal(utils.isGenerator([]), false, "`[]` is not a generator");
-  assert.equal(utils.isGenerator(null), false, "`null` is not a generator");
-  assert.equal(utils.isGenerator(undefined), false, "`undefined` is not a generator");
-};
-
-exports["test array"] = function (assert) {
-  assert.equal(utils.isArray([]), true, "[] is an array");
-  assert.equal(utils.isArray([1]), true, "[1] is an array");
-  assert.equal(utils.isArray(new Array()), true, "new Array() is an array");
-  assert.equal(utils.isArray(new Array(10)), true, "new Array(10) is an array");
-  assert.equal(utils.isArray(Array.prototype), true, "Array.prototype is an array");
-
-  assert.equal(utils.isArray(), false, "implicit undefined is not an array");
-  assert.equal(utils.isArray(null), false, "null is not an array");
-  assert.equal(utils.isArray(undefined), false, "undefined is not an array");
-  assert.equal(utils.isArray(1), false, "1 is not an array");
-  assert.equal(utils.isArray(true), false, "true is not an array");
-  assert.equal(utils.isArray('foo'), false, "'foo' is not an array");
-  assert.equal(utils.isArray({}), false, "{} is not an array");
-  assert.equal(utils.isArray(Symbol.iterator), false, "Symbol.iterator is not an array");
-};
-
-exports["test arguments"] = function (assert) {
-  assert.equal(utils.isArguments(arguments), true, "arguments is an arguments");
-  (function() {
-    assert.equal(utils.isArguments(arguments), true, "arguments in nested function is an arguments");
-  })();
-  (function*() {
-    assert.equal(utils.isArguments(arguments), true, "arguments in nested generator is an arguments");
-  })();
-  (() => {
-    assert.equal(utils.isArguments(arguments), true, "arguments in arrow function is an arguments");
-  })();
-
-  assert.equal(utils.isArguments(), false, "implicit undefined is not an arguments");
-  assert.equal(utils.isArguments(null), false, "null is not an arguments");
-  assert.equal(utils.isArguments(undefined), false, "undefined is not an arguments");
-  assert.equal(utils.isArguments(1), false, "1 is not an arguments");
-  assert.equal(utils.isArguments(true), false, "true is not an arguments");
-  assert.equal(utils.isArguments('foo'), false, "'foo' is not an arguments");
-  assert.equal(utils.isArguments([]), false, "[] is not an arguments");
-  assert.equal(utils.isArguments({}), false, "{} is not an arguments");
-  assert.equal(utils.isArguments(Symbol.iterator), false, "Symbol.iterator is not an arguments");
-  (function(...args) {
-    assert.equal(utils.isArguments(args), false, "rest arguments is not an arguments");
-  })();
-};
-
-exports["test flat objects"] = function (assert) {
-  assert.ok(utils.isFlat({}), "`{}` is a flat object");
-  assert.ok(!utils.isFlat([]), "`[]` is not a flat object");
-  assert.ok(!utils.isFlat(new function() {}), "derived objects are not flat");
-  assert.ok(utils.isFlat(Object.prototype), "Object.prototype is flat");
-};
-
-exports["test json atoms"] = function (assert) {
-  assert.ok(utils.isJSON(null), "`null` is JSON");
-  assert.ok(utils.isJSON(undefined), "`undefined` is JSON");
-  assert.ok(utils.isJSON(NaN), "`NaN` is JSON");
-  assert.ok(utils.isJSON(Infinity), "`Infinity` is JSON");
-  assert.ok(utils.isJSON(true) && utils.isJSON(false), "booleans are JSON");
-  assert.ok(utils.isJSON(4), utils.isJSON(0), "numbers are JSON");
-  assert.ok(utils.isJSON("foo bar"), "strings are JSON");
-};
-
-exports["test jsonable values"] = function (assert) {
-  assert.ok(utils.isJSONable(null), "`null` is JSONable");
-  assert.ok(!utils.isJSONable(undefined), "`undefined` is not JSONable");
-  assert.ok(utils.isJSONable(NaN), "`NaN` is JSONable");
-  assert.ok(utils.isJSONable(Infinity), "`Infinity` is JSONable");
-  assert.ok(utils.isJSONable(true) && utils.isJSONable(false), "booleans are JSONable");
-  assert.ok(utils.isJSONable(0), "numbers are JSONable");
-  assert.ok(utils.isJSONable("foo bar"), "strings are JSONable");
-  assert.ok(!utils.isJSONable(function(){}), "functions are not JSONable");
-
-  const functionWithToJSON = function(){};
-  functionWithToJSON.toJSON = function() { return "foo bar"; };
-  assert.ok(utils.isJSONable(functionWithToJSON), "functions with toJSON() are JSONable");
-
-  assert.ok(utils.isJSONable({}), "`{}` is JSONable");
-
-  const foo = {};
-  foo.bar = foo;
-  assert.ok(!utils.isJSONable(foo), "recursive objects are not JSONable");
-};
-
-exports["test instanceOf"] = function (assert) {
-  assert.ok(utils.instanceOf(assert, Object),
-            "assert is object from other sandbox");
-  assert.ok(utils.instanceOf(new Date(), Date), "instance of date");
-  assert.ok(!utils.instanceOf(null, Object), "null is not an instance");
-};
-
-exports["test json"] = function (assert) {
-  assert.ok(!utils.isJSON(function(){}), "functions are not json");
-  assert.ok(utils.isJSON({}), "`{}` is JSON");
-  assert.ok(utils.isJSON({
-              a: "foo",
-              b: 3,
-              c: undefined,
-              d: null,
-              e: {
-                f: {
-                  g: "bar",
-                  p: [{}, "oueou", 56]
-                },
-                q: { nan: NaN, infinity: Infinity },
-                "non standard name": "still works"
-              }
-            }), "JSON can contain nested objects");
-
-  var foo = {};
-  var bar = { foo: foo };
-  foo.bar = bar;
-  assert.ok(!utils.isJSON(foo), "recursive objects are not json");
-
-
-  assert.ok(!utils.isJSON({ get foo() { return 5 } }),
-            "json can not have getter");
-
-  assert.ok(!utils.isJSON({ foo: "bar", baz: function () {} }),
-            "json can not contain functions");
-
-  assert.ok(!utils.isJSON(Object.create({})),
-            "json must be direct descendant of `Object.prototype`");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-libxul.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Test that we can link with libxul using js-ctypes
-
-const {Cu} = require("chrome");
-const {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm", {});
-const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
-
-exports.test = function(assert) {
-  let path = OS.Constants.Path.libxul;
-  assert.pass("libxul is at " + path);
-  let lib = ctypes.open(path);
-  assert.ok(lib != null, "linked to libxul successfully");
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-list.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { List, addListItem, removeListItem } = require('sdk/util/list');
-const { Class } = require('sdk/core/heritage');
-
-exports.testList = function(assert) {
-  let list = List();
-  addListItem(list, 1);
-
-  for (let key in list) {
-    assert.equal(key, 0, 'key is correct');
-    assert.equal(list[key], 1, 'value is correct');
-  }
-
-  let count = 0;
-  for (let ele of list) {
-    assert.equal(ele, 1, 'ele is correct');
-    assert.equal(++count, 1, 'count is correct');
-  }
-
-  count = 0;
-  for (let ele of list) {
-    assert.equal(ele, 1, 'ele is correct');
-    assert.equal(++count, 1, 'count is correct');
-  }
-
-  removeListItem(list, 1);
-  assert.equal(list.length, 0, 'remove worked');
-};
-
-exports.testImplementsList = function(assert) {
-  let List2 = Class({
-    implements: [List],
-    initialize: function() {
-      List.prototype.initialize.apply(this, [0, 1, 2]);
-    }
-  });
-  let list2 = List2();
-  let count = 0;
-
-  for (let ele of list2) {
-    assert.equal(ele, count++, 'ele is correct');
-  }
-
-  count = 0;
-  for (let ele of list2) {
-    assert.equal(ele, count++, 'ele is correct');
-  }
-
-  addListItem(list2, 3);
-  assert.equal(list2.length, 4, '3 was added');
-  assert.equal(list2[list2.length-1], 3, '3 was added');
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-loader.js
+++ /dev/null
@@ -1,655 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-var {
-  Loader, main, unload, parseStack, resolve, join,
-  Require, Module
-} = require('toolkit/loader');
-var { readURI } = require('sdk/net/url');
-
-var root = module.uri.substr(0, module.uri.lastIndexOf('/'));
-
-const app = require('sdk/system/xul-app');
-
-// The following adds Debugger constructor to the global namespace.
-const { Cu } = require('chrome');
-const { addDebuggerToGlobal } = Cu.import('resource://gre/modules/jsdebugger.jsm', {});
-addDebuggerToGlobal(this);
-
-exports['test resolve'] = function (assert) {
-  let cuddlefish_id = 'sdk/loader/cuddlefish';
-  assert.equal(resolve('../index.js', './dir/c.js'), './index.js');
-  assert.equal(resolve('./index.js', './dir/c.js'), './dir/index.js');
-  assert.equal(resolve('./dir/c.js', './index.js'), './dir/c.js');
-  assert.equal(resolve('../utils/file.js', './dir/b.js'), './utils/file.js');
-
-  assert.equal(resolve('../utils/./file.js', './dir/b.js'), './utils/file.js');
-  assert.equal(resolve('../utils/file.js', './'), './../utils/file.js');
-  assert.equal(resolve('./utils/file.js', './'), './utils/file.js');
-  assert.equal(resolve('./utils/file.js', './index.js'), './utils/file.js');
-
-  assert.equal(resolve('../utils/./file.js', cuddlefish_id), 'sdk/utils/file.js');
-  assert.equal(resolve('../utils/file.js', cuddlefish_id), 'sdk/utils/file.js');
-  assert.equal(resolve('./utils/file.js', cuddlefish_id), 'sdk/loader/utils/file.js');
-
-  assert.equal(resolve('..//index.js', './dir/c.js'), './index.js');
-  assert.equal(resolve('../modules/XPCOMUtils.jsm', 'resource://gre/utils/file.js'), 'resource://gre/modules/XPCOMUtils.jsm');
-  assert.equal(resolve('../modules/XPCOMUtils.jsm', 'chrome://gre/utils/file.js'), 'chrome://gre/modules/XPCOMUtils.jsm');
-  assert.equal(resolve('../../a/b/c.json', 'file:///thing/utils/file.js'), 'file:///a/b/c.json');
-
-  // Does not change absolute paths
-  assert.equal(resolve('resource://gre/modules/file.js', './dir/b.js'),
-    'resource://gre/modules/file.js');
-  assert.equal(resolve('file:///gre/modules/file.js', './dir/b.js'),
-    'file:///gre/modules/file.js');
-  assert.equal(resolve('/root.js', './dir/b.js'),
-    '/root.js');
-};
-
-exports['test join'] = function (assert) {
-  assert.equal(join('a/path', '../../../module'), '../module');
-  assert.equal(join('a/path/to', '../module'), 'a/path/module');
-  assert.equal(join('a/path/to', './module'), 'a/path/to/module');
-  assert.equal(join('a/path/to', '././../module'), 'a/path/module');
-  assert.equal(join('resource://my/path/yeah/yuh', '../whoa'),
-    'resource://my/path/yeah/whoa');
-  assert.equal(join('resource://my/path/yeah/yuh', './whoa'),
-    'resource://my/path/yeah/yuh/whoa');
-  assert.equal(join('resource:///my/path/yeah/yuh', '../whoa'),
-    'resource:///my/path/yeah/whoa');
-  assert.equal(join('resource:///my/path/yeah/yuh', './whoa'),
-    'resource:///my/path/yeah/yuh/whoa');
-  assert.equal(join('file:///my/path/yeah/yuh', '../whoa'),
-    'file:///my/path/yeah/whoa');
-  assert.equal(join('file:///my/path/yeah/yuh', './whoa'),
-    'file:///my/path/yeah/yuh/whoa');
-  assert.equal(join('a/path/to', '..//module'), 'a/path/module');
-};
-
-exports['test dependency cycles'] = function(assert) {
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri } });
-
-  let program = main(loader, 'main');
-
-  assert.equal(program.a.b, program.b, 'module `a` gets correct `b`');
-  assert.equal(program.b.a, program.a, 'module `b` gets correct `a`');
-  assert.equal(program.c.main, program, 'module `c` gets correct `main`');
-
-  unload(loader);
-}
-
-exports['test syntax errors'] = function(assert) {
-  let uri = root + '/fixtures/loader/syntax-error/';
-  let loader = Loader({ paths: { '': uri } });
-
-  try {
-    let program = main(loader, 'main');
-  } catch (error) {
-    assert.equal(error.name, "SyntaxError", "throws syntax error");
-    assert.equal(error.fileName.split("/").pop(), "error.js",
-              "Error contains filename");
-    assert.equal(error.lineNumber, 11, "error is on line 11");
-    let stack = parseStack(error.stack);
-
-    assert.equal(stack.pop().fileName, uri + "error.js",
-                 "last frame file containing syntax error");
-    assert.equal(stack.pop().fileName, uri + "main.js",
-                 "previous frame is a requirer module");
-    assert.equal(stack.pop().fileName, module.uri,
-                 "previous to it is a test module");
-
-  } finally {
-    unload(loader);
-  }
-}
-
-exports['test sandboxes are not added if error'] = function (assert) {
-  let uri = root + '/fixtures/loader/missing-twice/';
-  let loader = Loader({ paths: { '': uri } });
-  let program = main(loader, 'main');
-  assert.ok(!(uri + 'not-found.js' in loader.sandboxes), 'not-found.js not in loader.sandboxes');
-}
-
-exports['test missing module'] = function(assert) {
-  let uri = root + '/fixtures/loader/missing/'
-  let loader = Loader({ paths: { '': uri } });
-
-  try {
-    let program = main(loader, 'main')
-  } catch (error) {
-    assert.equal(error.message, "Module `not-found` is not found at " +
-                uri + "not-found.js", "throws if error not found");
-
-    assert.equal(error.fileName.split("/").pop(), "main.js",
-                 "Error fileName is requirer module");
-
-    assert.equal(error.lineNumber, 7, "error is on line 7");
-
-    let stack = parseStack(error.stack);
-
-    assert.equal(stack.pop().fileName, uri + "main.js",
-                 "loader stack is omitted");
-
-    assert.equal(stack.pop().fileName, module.uri,
-                 "previous in the stack is test module");
-  } finally {
-    unload(loader);
-  }
-}
-
-exports["test invalid module not cached and throws everytime"] = function(assert) {
-  let uri = root + "/fixtures/loader/missing-twice/";
-  let loader = Loader({ paths: { "": uri } });
-
-  let { firstError, secondError, invalidJSON1, invalidJSON2 } = main(loader, "main");
-  assert.equal(firstError.message, "Module `not-found` is not found at " +
-    uri + "not-found.js", "throws on first invalid require");
-  assert.equal(firstError.lineNumber, 8, "first error is on line 7");
-  assert.equal(secondError.message, "Module `not-found` is not found at " +
-    uri + "not-found.js", "throws on second invalid require");
-  assert.equal(secondError.lineNumber, 14, "second error is on line 14");
-
-  assert.equal(invalidJSON1.message,
-    "JSON.parse: unexpected character at line 1 column 1 of the JSON data",
-    "throws on invalid JSON");
-  assert.equal(invalidJSON2.message,
-    "JSON.parse: unexpected character at line 1 column 1 of the JSON data",
-    "throws on invalid JSON second time");
-};
-
-exports['test exceptions in modules'] = function(assert) {
-  let uri = root + '/fixtures/loader/exceptions/'
-
-  let loader = Loader({ paths: { '': uri } });
-
-  try {
-    let program = main(loader, 'main')
-  } catch (error) {
-    assert.equal(error.message, "Boom!", "thrown errors propagate");
-
-    assert.equal(error.fileName.split("/").pop(), "boomer.js",
-                 "Error comes from the module that threw it");
-
-    assert.equal(error.lineNumber, 8, "error is on line 8");
-
-    let stack = parseStack(error.stack);
-
-    let frame = stack.pop()
-    assert.equal(frame.fileName, uri + "boomer.js",
-                 "module that threw is first in the stack");
-    assert.equal(frame.name, "exports.boom",
-                 "name is in the stack");
-
-    frame = stack.pop()
-    assert.equal(frame.fileName, uri + "main.js",
-                 "module that called it is next in the stack");
-    assert.equal(frame.lineNumber, 9, "caller line is in the stack");
-
-
-    assert.equal(stack.pop().fileName, module.uri,
-                 "this test module is next in the stack");
-  } finally {
-    unload(loader);
-  }
-}
-
-exports['test early errors in module'] = function(assert) {
-  let uri = root + '/fixtures/loader/errors/';
-  let loader = Loader({ paths: { '': uri } });
-
-  try {
-    let program = main(loader, 'main')
-  } catch (error) {
-    assert.equal(String(error),
-                 "Error: opening input stream (invalid filename?)",
-                 "thrown errors propagate");
-
-    assert.equal(error.fileName.split("/").pop(), "boomer.js",
-                 "Error comes from the module that threw it");
-
-    assert.equal(error.lineNumber, 7, "error is on line 7");
-
-    let stack = parseStack(error.stack);
-
-    let frame = stack.pop()
-    assert.equal(frame.fileName, uri + "boomer.js",
-                 "module that threw is first in the stack");
-
-    frame = stack.pop()
-    assert.equal(frame.fileName, uri + "main.js",
-                 "module that called it is next in the stack");
-    assert.equal(frame.lineNumber, 7, "caller line is in the stack");
-
-
-    assert.equal(stack.pop().fileName, module.uri,
-                 "this test module is next in the stack");
-  } finally {
-    unload(loader);
-  }
-};
-
-exports['test require json'] = function (assert) {
-  let data = require('./fixtures/loader/json/manifest.json');
-  assert.equal(data.name, 'Jetpack Loader Test', 'loads json with strings');
-  assert.equal(data.version, '1.0.1', 'loads json with strings');
-  assert.equal(data.dependencies.async, '*', 'loads json with objects');
-  assert.equal(data.dependencies.underscore, '*', 'loads json with objects');
-  assert.equal(data.contributors.length, 4, 'loads json with arrays');
-  assert.ok(Array.isArray(data.contributors), 'loads json with arrays');
-  data.version = '2.0.0';
-  let newdata = require('./fixtures/loader/json/manifest.json');
-  assert.equal(newdata.version, '2.0.0',
-    'JSON objects returned should be cached and the same instance');
-
-  try {
-    require('./fixtures/loader/json/invalid.json');
-    assert.fail('Error not thrown when loading invalid json');
-  } catch (err) {
-    assert.ok(err, 'error thrown when loading invalid json');
-    assert.ok(/JSON\.parse/.test(err.message),
-      'should thrown an error from JSON.parse, not attempt to load .json.js');
-  }
-
-  // Try again to ensure an empty module isn't loaded from cache
-  try {
-    require('./fixtures/loader/json/invalid.json');
-    assert.fail('Error not thrown when loading invalid json a second time');
-  } catch (err) {
-    assert.ok(err,
-      'error thrown when loading invalid json a second time');
-    assert.ok(/JSON\.parse/.test(err.message),
-      'should thrown an error from JSON.parse a second time, not attempt to load .json.js');
-  }
-};
-
-exports['test setting metadata for newly created sandboxes'] = function(assert) {
-  let addonID = 'random-addon-id';
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri }, id: addonID });
-
-  let dbg = new Debugger();
-  dbg.onNewGlobalObject = function(global) {
-    dbg.onNewGlobalObject = undefined;
-
-    let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
-    assert.ok(metadata, 'this global has attached metadata');
-    assert.equal(metadata.URI, uri + 'main.js', 'URI is set properly');
-    assert.equal(metadata.addonID, addonID, 'addon ID is set');
-  }
-
-  let program = main(loader, 'main');
-};
-
-exports['test require .json, .json.js'] = function (assert) {
-  let testjson = require('./fixtures/loader/json/test.json');
-  assert.equal(testjson.filename, 'test.json',
-    'require("./x.json") should load x.json, not x.json.js');
-
-  let nodotjson = require('./fixtures/loader/json/nodotjson.json');
-  assert.equal(nodotjson.filename, 'nodotjson.json.js',
-    'require("./x.json") should load x.json.js when x.json does not exist');
-  nodotjson.data.prop = 'hydralisk';
-
-  // require('nodotjson.json') and require('nodotjson.json.js')
-  // should resolve to the same file
-  let nodotjsonjs = require('./fixtures/loader/json/nodotjson.json.js');
-  assert.equal(nodotjsonjs.data.prop, 'hydralisk',
-    'js modules are cached whether access via .json.js or .json');
-};
-
-exports['test invisibleToDebugger: false'] = function (assert) {
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri } });
-  main(loader, 'main');
-
-  let dbg = new Debugger();
-  let sandbox = loader.sandboxes[uri + 'main.js'];
-
-  try {
-    dbg.addDebuggee(sandbox);
-    assert.ok(true, 'debugger added visible value');
-  } catch(e) {
-    assert.fail('debugger could not add visible value');
-  }
-};
-
-exports['test invisibleToDebugger: true'] = function (assert) {
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri }, invisibleToDebugger: true });
-  main(loader, 'main');
-
-  let dbg = new Debugger();
-  let sandbox = loader.sandboxes[uri + 'main.js'];
-
-  try {
-    dbg.addDebuggee(sandbox);
-    assert.fail('debugger added invisible value');
-  } catch(e) {
-    assert.ok(true, 'debugger did not add invisible value');
-  }
-};
-
-exports['test console global by default'] = function (assert) {
-  let uri = root + '/fixtures/loader/globals/';
-  let loader = Loader({ paths: { '': uri }});
-  let program = main(loader, 'main');
-
-  assert.ok(typeof program.console === 'object', 'global `console` exists');
-  assert.ok(typeof program.console.log === 'function', 'global `console.log` exists');
-
-  let loader2 = Loader({ paths: { '': uri }, globals: { console: fakeConsole }});
-  let program2 = main(loader2, 'main');
-
-  assert.equal(program2.console, fakeConsole,
-    'global console can be overridden with Loader options');
-  function fakeConsole () {};
-};
-
-exports['test shared globals'] = function(assert) {
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
-                        sharedGlobalBlocklist: ['b'] });
-
-  let program = main(loader, 'main');
-
-  // As it is hard to verify what is the global of an object
-  // (due to wrappers) we check that we see the `foo` symbol
-  // being manually injected into the shared global object
-  loader.sharedGlobalSandbox.foo = true;
-
-  let m = loader.sandboxes[uri + 'main.js'];
-  let a = loader.sandboxes[uri + 'a.js'];
-  let b = loader.sandboxes[uri + 'b.js'];
-
-  assert.ok(Cu.getGlobalForObject(m).foo, "main is shared");
-  assert.ok(Cu.getGlobalForObject(a).foo, "a is shared");
-  assert.ok(!Cu.getGlobalForObject(b).foo, "b isn't shared");
-
-  unload(loader);
-}
-
-exports['test deprecated shared globals exception name'] = function(assert) {
-  let uri = root + '/fixtures/loader/cycles/';
-  let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
-                        sharedGlobalBlacklist: ['b'] });
-
-  let program = main(loader, 'main');
-
-  assert.ok(loader.sharedGlobalBlocklist.includes("b"), "b should be in the blocklist");
-  assert.equal(loader.sharedGlobalBlocklist.length, loader.sharedGlobalBlacklist.length,
-               "both blocklists should have the same number of items.");
-  assert.equal(loader.sharedGlobalBlocklist.join(","), loader.sharedGlobalBlacklist.join(","),
-               "both blocklists should have the same items.");
-
-  // As it is hard to verify what is the global of an object
-  // (due to wrappers) we check that we see the `foo` symbol
-  // being manually injected into the shared global object
-  loader.sharedGlobalSandbox.foo = true;
-
-  let m = loader.sandboxes[uri + 'main.js'];
-  let a = loader.sandboxes[uri + 'a.js'];
-  let b = loader.sandboxes[uri + 'b.js'];
-
-  assert.ok(Cu.getGlobalForObject(m).foo, "main is shared");
-  assert.ok(Cu.getGlobalForObject(a).foo, "a is shared");
-  assert.ok(!Cu.getGlobalForObject(b).foo, "b isn't shared");
-
-  unload(loader);
-}
-
-exports['test prototype of global'] = function (assert) {
-  let uri = root + '/fixtures/loader/globals/';
-  let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
-                        sandboxPrototype: { globalFoo: 5 }});
-
-  let program = main(loader, 'main');
-
-  assert.ok(program.globalFoo === 5, '`globalFoo` exists');
-};
-
-exports["test require#resolve"] = function(assert) {
-  let foundRoot = require.resolve("sdk/tabs").replace(/sdk\/tabs.js$/, "");
-  assert.ok(root, foundRoot, "correct resolution root");
-
-  assert.equal(foundRoot + "sdk/tabs.js", require.resolve("sdk/tabs"), "correct resolution of sdk module");
-  assert.equal(foundRoot + "toolkit/loader.js", require.resolve("toolkit/loader"), "correct resolution of sdk module");
-
-  const localLoader = Loader({
-    paths: { "foo/bar": "bizzle",
-             // Just to make sure this doesn't match the first entry,
-             // let use resolve this module
-             "foo/bar-bar": "foo/bar-bar" }
-  });
-  const localRequire = Require(localLoader, module);
-  assert.equal(localRequire.resolve("foo/bar"), "bizzle.js");
-  assert.equal(localRequire.resolve("foo/bar/baz"), "bizzle/baz.js");
-  assert.equal(localRequire.resolve("foo/bar-bar"), "foo/bar-bar.js");
-};
-
-const modulesURI = require.resolve("toolkit/loader").replace("toolkit/loader.js", "");
-exports["test loading a loader"] = function(assert) {
-  const loader = Loader({ paths: { "": modulesURI } });
-
-  const require = Require(loader, module);
-
-  const requiredLoader = require("toolkit/loader");
-
-  assert.equal(requiredLoader.Loader, Loader,
-               "got the same Loader instance");
-
-  const jsmLoader = Cu.import(require.resolve("toolkit/loader"), {}).Loader;
-
-  assert.equal(jsmLoader.Loader, requiredLoader.Loader,
-               "loading loader via jsm returns same loader");
-
-  unload(loader);
-};
-
-exports['test loader on unsupported modules with checkCompatibility true'] = function(assert) {
-  let loader = Loader({
-    paths: { '': root + "/" },
-    checkCompatibility: true
-  });
-  let require = Require(loader, module);
-
-  assert.throws(() => {
-    if (!app.is('Firefox')) {
-      require('fixtures/loader/unsupported/firefox');
-    }
-    else {
-      require('fixtures/loader/unsupported/fennec');
-    }
-  }, /^Unsupported Application/, "throws Unsupported Application");
-
-  unload(loader);
-};
-
-exports['test loader on unsupported modules with checkCompatibility false'] = function(assert) {
-  let loader = Loader({
-    paths: { '': root + "/" },
-    checkCompatibility: false
-  });
-  let require = Require(loader, module);
-
-  try {
-    if (!app.is('Firefox')) {
-      require('fixtures/loader/unsupported/firefox');
-    }
-    else {
-      require('fixtures/loader/unsupported/fennec');
-    }
-    assert.pass("loaded unsupported module without an error");
-  }
-  catch(e) {
-    assert.fail(e);
-  }
-
-  unload(loader);
-};
-
-exports['test loader on unsupported modules with checkCompatibility default'] = function(assert) {
-  let loader = Loader({ paths: { '': root + "/" } });
-  let require = Require(loader, module);
-
-  try {
-    if (!app.is('Firefox')) {
-      require('fixtures/loader/unsupported/firefox');
-    }
-    else {
-      require('fixtures/loader/unsupported/fennec');
-    }
-    assert.pass("loaded unsupported module without an error");
-  }
-  catch(e) {
-    assert.fail(e);
-  }
-
-  unload(loader);
-};
-
-exports["test Cu.import of toolkit/loader"] = (assert) => {
-  const toolkitLoaderURI = require.resolve("toolkit/loader");
-  const loaderModule = Cu.import(toolkitLoaderURI).Loader;
-  const { Loader, Require, Main } = loaderModule;
-  const version = "0.1.0";
-  const id = `fxos_${version.replace(".", "_")}_simulator@mozilla.org`;
-  const uri = `resource://${encodeURIComponent(id.replace("@", "at"))}/`;
-
-  const loader = Loader({
-    paths: {
-      "./": uri + "lib/",
-      // Can't just put `resource://gre/modules/commonjs/` as it
-      // won't take module overriding into account.
-      "": toolkitLoaderURI.replace("toolkit/loader.js", "")
-    },
-    globals: {
-      console: console
-    },
-    modules: {
-      "toolkit/loader": loaderModule,
-      addon: {
-        id: "simulator",
-        version: "0.1",
-        uri: uri
-      }
-    }
-  });
-
-  let require_ = Require(loader, { id: "./addon" });
-  assert.equal(typeof(loaderModule),
-               typeof(require_("toolkit/loader")),
-               "module returned is whatever was mapped to it");
-};
-
-exports["test Cu.import in b2g style"] = (assert) => {
-  const {FakeCu} = require("./loader/b2g");
-  const toolkitLoaderURI = require.resolve("toolkit/loader");
-  const b2g = new FakeCu();
-
-  const exported = {};
-  const loader = b2g.import(toolkitLoaderURI, exported);
-
-  assert.equal(typeof(exported.Loader),
-               "function",
-               "loader is a function");
-  assert.equal(typeof(exported.Loader.Loader),
-               "function",
-               "Loader.Loader is a funciton");
-};
-
-exports['test lazy globals'] = function (assert) {
-  let uri = root + '/fixtures/loader/lazy/';
-  let gotFoo = false;
-  let foo = {};
-  let modules = {
-    get foo() {
-      gotFoo = true;
-      return foo;
-    }
-  };
-  let loader = Loader({ paths: { '': uri }, modules: modules});
-  assert.ok(!gotFoo, "foo hasn't been accessed during loader instanciation");
-  let program = main(loader, 'main');
-  assert.ok(!gotFoo, "foo hasn't been accessed during module loading");
-  assert.equal(program.useFoo(), foo, "foo mock works");
-  assert.ok(gotFoo, "foo has been accessed only when we first try to use it");
-};
-
-exports['test user global'] = function(assert) {
-  // Test case for bug 827792
-  let com = {};
-  let loader = require('toolkit/loader');
-  let loadOptions = require('@loader/options');
-  let options = loader.override(loadOptions,
-                                {globals: loader.override(loadOptions.globals,
-                                                          {com: com,
-                                                           console: console,
-                                                           dump: dump})});
-  let subloader = loader.Loader(options);
-  let userRequire = loader.Require(subloader, module);
-  let userModule = userRequire("./loader/user-global");
-
-  assert.equal(userModule.getCom(), com,
-               "user module returns expected `com` global");
-};
-
-exports['test custom require caching'] = function(assert) {
-  const loader = Loader({
-    paths: { '': root + "/" },
-    requireHook: (id, require) => {
-      // Just load it normally
-      return require(id);
-    }
-  });
-  const require = Require(loader, module);
-
-  let data = require('fixtures/loader/json/mutation.json');
-  assert.equal(data.value, 1, 'has initial value');
-  data.value = 2;
-  let newdata = require('fixtures/loader/json/mutation.json');
-  assert.equal(
-    newdata.value,
-    2,
-    'JSON objects returned should be cached and the same instance'
-  );
-};
-
-exports['test caching when proxying a loader'] = function(assert) {
-  const parentRequire = require;
-  const loader = Loader({
-    paths: { '': root + "/" },
-    requireHook: (id, childRequire) => {
-      if(id === 'gimmejson') {
-        return childRequire('fixtures/loader/json/mutation.json')
-      }
-      // Load it with the original (global) require
-      return parentRequire(id);
-    }
-  });
-  const childRequire = Require(loader, module);
-
-  let data = childRequire('./fixtures/loader/json/mutation.json');
-  assert.equal(data.value, 1, 'data has initial value');
-  data.value = 2;
-
-  let newdata = childRequire('./fixtures/loader/json/mutation.json');
-  assert.equal(newdata.value, 2, 'data has changed');
-
-  let childData = childRequire('gimmejson');
-  assert.equal(childData.value, 1, 'data from child loader has initial value');
-  childData.value = 3;
-  let newChildData = childRequire('gimmejson');
-  assert.equal(newChildData.value, 3, 'data from child loader has changed');
-
-  data = childRequire('./fixtures/loader/json/mutation.json');
-  assert.equal(data.value, 2, 'data from parent loader has not changed');
-
-  // Set it back to the original value just in case (this instance
-  // will be shared across tests)
-  data.value = 1;
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-match-pattern.js
+++ /dev/null
@@ -1,137 +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 { MatchPattern } = require("sdk/util/match-pattern");
-
-exports.testMatchPatternTestTrue = function(assert) {
-  function ok(pattern, url) {
-    let mp = new MatchPattern(pattern);
-    assert.ok(mp.test(url), pattern + " should match " + url);
-  }
-
-  ok("*", "http://example.com");
-  ok("*", "https://example.com");
-  ok("*", "ftp://example.com");
-
-  ok("*.example.com", "http://example.com");
-  ok("*.example.com", "http://hamburger.example.com");
-  ok("*.example.com", "http://hotdog.hamburger.example.com");
-
-  ok("http://example.com*", "http://example.com");
-  ok("http://example.com*", "http://example.com/");
-  ok("http://example.com/*", "http://example.com/");
-  ok("http://example.com/*", "http://example.com/potato-salad");
-  ok("http://example.com/pickles/*", "http://example.com/pickles/");
-  ok("http://example.com/pickles/*", "http://example.com/pickles/lemonade");
-
-  ok("http://example.com", "http://example.com");
-  ok("http://example.com/ice-cream", "http://example.com/ice-cream");
-
-  ok(/.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
-  ok(/.*A.*/i, "http://A.com");
-  ok(/.*A.*/i, "http://a.com");
-  ok(/https:.*zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
-  ok('*.sample.com', 'http://ex.sample.com/foo.html');
-  ok('*.amp.le.com', 'http://ex.amp.le.com');
-
-  ok('data:*', 'data:text/html;charset=utf-8,');
-};
-
-exports.testMatchPatternTestFalse = function(assert) {
-  function ok(pattern, url) {
-    let mp = new MatchPattern(pattern);
-    assert.ok(!mp.test(url), pattern + " should not match " + url);
-  }
-
-  ok("*", null);
-  ok("*", "");
-  ok("*", "bogus");
-  ok("*", "chrome://browser/content/browser.xul");
-  ok("*", "nttp://example.com");
-
-  ok("*.example.com", null);
-  ok("*.example.com", "");
-  ok("*.example.com", "bogus");
-  ok("*.example.com", "http://example.net");
-  ok("*.example.com", "http://foo.com");
-  ok("*.example.com", "http://example.com.foo");
-  ok("*.example2.com", "http://example.com");
-
-  ok("http://example.com/*", null);
-  ok("http://example.com/*", "");
-  ok("http://example.com/*", "bogus");
-  ok("http://example.com/*", "http://example.com");
-  ok("http://example.com/*", "http://foo.com/");
-
-  ok("http://example.com", null);
-  ok("http://example.com", "");
-  ok("http://example.com", "bogus");
-  ok("http://example.com", "http://example.com/");
-
-  ok(/zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
-  ok(/.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
-  ok(/.*Zilla.*/, "https://bugzilla.redhat.com/show_bug.cgi?id=655464"); // bug 655464
-  ok(/https:.*zilla/, "https://bugzilla.redhat.com/show_bug.cgi?id=569753");
-
-  // bug 856913
-  ok('*.ign.com', 'http://www.design.com');
-  ok('*.ign.com', 'http://design.com');
-  ok('*.zilla.com', 'http://bugzilla.mozilla.com');
-  ok('*.zilla.com', 'http://mo-zilla.com');
-  ok('*.amp.le.com', 'http://amp-le.com');
-  ok('*.amp.le.com', 'http://examp.le.com');
-};
-
-exports.testMatchPatternErrors = function(assert) {
-  assert.throws(
-    () => new MatchPattern("*.google.com/*"),
-    /There can be at most one/,
-    "MatchPattern throws when supplied multiple '*'"
-  );
-
-  assert.throws(
-    () => new MatchPattern("google.com"),
-    /expected to be either an exact URL/,
-    "MatchPattern throws when the wildcard doesn't use '*' and doesn't " +
-    "look like a URL"
-  );
-
-  assert.throws(
-    () => new MatchPattern("http://google*.com"),
-    /expected to be the first or the last/,
-    "MatchPattern throws when a '*' is in the middle of the wildcard"
-  );
-
-  assert.throws(
-    () => new MatchPattern(/ /g),
-    /^A RegExp match pattern cannot be set to `global` \(i\.e\. \/\/g\)\.$/,
-    "MatchPattern throws on a RegExp set to `global` (i.e. //g)."
-  );
-
-  assert.throws(
-    () => new MatchPattern( / /m ),
-    /^A RegExp match pattern cannot be set to `multiline` \(i\.e\. \/\/m\)\.$/,
-    "MatchPattern throws on a RegExp set to `multiline` (i.e. //m)."
-  );
-};
-
-exports.testMatchPatternInternals = function(assert) {
-  assert.equal(
-    new MatchPattern("http://google.com/test").exactURL,
-    "http://google.com/test"
-  );
-
-  assert.equal(
-    new MatchPattern("http://google.com/test/*").urlPrefix,
-    "http://google.com/test/"
-  );
-
-  assert.equal(
-    new MatchPattern("*.example.com").domain,
-    "example.com"
-  );
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-method.js
+++ /dev/null
@@ -1,7 +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.exports = require("method/test/common");
deleted file mode 100644
--- a/addon-sdk/source/test/test-module.js
+++ /dev/null
@@ -1,36 +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";
-
-/** Disabled because of Bug 672199
-exports["test module exports are frozen"] = function(assert) {
-  assert.ok(Object.isFrozen(require("sdk/hotkeys")),
-            "module exports are frozen");
-};
-
-exports["test redefine exported property"] = function(assert) {
-  let hotkeys = require("sdk/hotkeys");
-  let { Hotkey } = hotkeys;
-  try { Object.defineProperty(hotkeys, 'Hotkey', { value: {} }); } catch(e) {}
-  assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be redefined");
-};
-*/
-
-exports["test can't delete exported property"] = function(assert) {
-  let hotkeys = require("sdk/hotkeys");
-  let { Hotkey } = hotkeys;
-
-  try { delete hotkeys.Hotkey; } catch(e) {}
-  assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be deleted");
-};
-
-exports["test can't override exported property"] = function(assert) {
-  let hotkeys = require("sdk/hotkeys");
-  let { Hotkey } = hotkeys;
-
-  try { hotkeys.Hotkey = Object } catch(e) {}
-  assert.equal(hotkeys.Hotkey, Hotkey, "exports can't be overriden");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-modules.js
+++ /dev/null
@@ -1,150 +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/. */
-
-exports.testDefine = function(assert) {
-  let tiger = require('./modules/tiger');
-  assert.equal(tiger.name, 'tiger', 'name proprety was exported properly');
-  assert.equal(tiger.type, 'cat', 'property form other module exported');
-};
-
-exports.testDefineInoresNonFactory = function(assert) {
-  let mod = require('./modules/async2');
-  assert.equal(mod.name, 'async2', 'name proprety was exported properly');
-  assert.ok(mod.traditional2Name !== 'traditional2', '1st is ignored');
-};
-/* Disable test that require AMD specific functionality:
-
-// define() that exports a function as the module value,
-// specifying a module name.
-exports.testDefExport = function(assert) {
-  var add = require('modules/add');
-  assert.equal(add(1, 1), 2, 'Named define() exporting a function');
-};
-
-// define() that exports function as a value, but is anonymous
-exports.testAnonDefExport = function (assert) {
-  var subtract = require('modules/subtract');
-  assert.equal(subtract(4, 2), 2,
-                   'Anonymous define() exporting a function');
-}
-
-// using require([], function () {}) to load modules.
-exports.testSimpleRequire = function (assert) {
-  require(['modules/blue', 'modules/orange'], function (blue, orange) {
-    assert.equal(blue.name, 'blue', 'Simple require for blue');
-    assert.equal(orange.name, 'orange', 'Simple require for orange');
-    assert.equal(orange.parentType, 'color',
-                     'Simple require dependency check for orange');
-  });
-}
-
-// using nested require([]) calls.
-exports.testSimpleRequireNested = function (assert) {
-  require(['modules/blue', 'modules/orange', 'modules/green'],
-  function (blue, orange, green) {
-
-    require(['modules/orange', 'modules/red'], function (orange, red) {
-      assert.equal(red.name, 'red', 'Simple require for red');
-      assert.equal(red.parentType, 'color',
-                       'Simple require dependency check for red');
-      assert.equal(blue.name, 'blue', 'Simple require for blue');
-      assert.equal(orange.name, 'orange', 'Simple require for orange');
-      assert.equal(orange.parentType, 'color',
-                       'Simple require dependency check for orange');
-      assert.equal(green.name, 'green', 'Simple require for green');
-      assert.equal(green.parentType, 'color',
-                       'Simple require dependency check for green');
-    });
-
-  });
-}
-
-// requiring a traditional module, that uses async, that use traditional and
-// async, with a circular reference
-exports.testMixedCircular = function (assert) {
-  var t = require('modules/traditional1');
-  assert.equal(t.name, 'traditional1', 'Testing name');
-  assert.equal(t.traditional2Name, 'traditional2',
-                   'Testing dependent name');
-  assert.equal(t.traditional1Name, 'traditional1', 'Testing circular name');
-  assert.equal(t.async2Name, 'async2', 'Testing async2 name');
-  assert.equal(t.async2Traditional2Name, 'traditional2',
-                   'Testing nested traditional2 name');
-}
-
-// Testing define()(function(require) {}) with some that use exports,
-// some that use return.
-exports.testAnonExportsReturn = function (assert) {
-  var lion = require('modules/lion');
-  require(['modules/tiger', 'modules/cheetah'], function (tiger, cheetah) {
-    assert.equal('lion', lion, 'Check lion name');
-    assert.equal('tiger', tiger.name, 'Check tiger name');
-    assert.equal('cat', tiger.type, 'Check tiger type');
-    assert.equal('cheetah', cheetah(), 'Check cheetah name');
-  });
-}
-
-// circular dependency
-exports.testCircular = function (assert) {
-  var pollux = require('modules/pollux'),
-      castor = require('modules/castor');
-
-  assert.equal(pollux.name, 'pollux', 'Pollux\'s name');
-  assert.equal(pollux.getCastorName(),
-                   'castor', 'Castor\'s name from Pollux.');
-  assert.equal(castor.name, 'castor', 'Castor\'s name');
-  assert.equal(castor.getPolluxName(), 'pollux',
-                   'Pollux\'s name from Castor.');
-}
-
-// test a bad module that asks for exports but also does a define() return
-exports.testBadExportAndReturn = function (assert) {
-  var passed = false;
-  try {
-    var bad = require('modules/badExportAndReturn');
-  } catch(e) {
-    passed = /cannot use exports and also return/.test(e.toString());
-  }
-  assert.equal(passed, true, 'Make sure exports and return fail');
-}
-
-// test a bad circular dependency, where an exported value is needed, but
-// the return value happens too late, a module already asked for the exported
-// value.
-exports.testBadExportAndReturnCircular = function (assert) {
-  var passed = false;
-  try {
-    var bad = require('modules/badFirst');
-  } catch(e) {
-    passed = /after another module has referenced its exported value/
-             .test(e.toString());
-  }
-  assert.equal(passed, true, 'Make sure return after an exported ' +
-                                 'value is grabbed by another module fails.');
-}
-
-// only allow one define call per file.
-exports.testOneDefine = function (assert) {
-  var passed = false;
-  try {
-    var dupe = require('modules/dupe');
-  } catch(e) {
-    passed = /Only one call to define/.test(e.toString());
-  }
-  assert.equal(passed, true, 'Only allow one define call per module');
-}
-
-// only allow one define call per file, testing a bad nested define call.
-exports.testOneDefineNested = function (assert) {
-  var passed = false;
-  try {
-    var dupe = require('modules/dupeNested');
-  } catch(e) {
-    passed = /Only one call to define/.test(e.toString());
-  }
-  assert.equal(passed, true, 'Only allow one define call per module');
-}
-*/
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-mozilla-toolkit-versioning.js
+++ /dev/null
@@ -1,59 +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 {parse, increment} = require("mozilla-toolkit-versioning/index")
-
-const TestParse = assert => (version, min, max) => {
-  const actual = parse(version);
-  assert.equal(actual.min, min);
-  assert.equal(actual.max, max);
-}
-
-const TestInc = assert => (version, expected) => {
-  assert.equal(increment(version), expected,
-               `increment: ${version} should be equal ${expected}`)
-}
-
-
-
-exports['test parse(version) single value'] = assert => {
-  const testParse = TestParse(assert)
-  testParse('1.2.3', '1.2.3', '1.2.3');
-  testParse('>=1.2.3', '1.2.3', undefined);
-  testParse('<=1.2.3', undefined, '1.2.3');
-  testParse('>1.2.3', '1.2.3.1', undefined);
-  testParse('<1.2.3', undefined, '1.2.3.-1');
-  testParse('*', undefined, undefined);
-};
-
-exports['test parse(version) range'] = assert => {
-  const testParse = TestParse(assert);
-  testParse('>=1.2.3 <=2.3.4', '1.2.3', '2.3.4');
-  testParse('>1.2.3 <=2.3.4', '1.2.3.1', '2.3.4');
-  testParse('>=1.2.3 <2.3.4', '1.2.3', '2.3.4.-1');
-  testParse('>1.2.3 <2.3.4', '1.2.3.1', '2.3.4.-1');
-
-  testParse('<=2.3.4 >=1.2.3', '1.2.3', '2.3.4');
-  testParse('<=2.3.4 >1.2.3', '1.2.3.1', '2.3.4');
-  testParse('<2.3.4 >=1.2.3', '1.2.3', '2.3.4.-1');
-  testParse('<2.3.4 >1.2.3', '1.2.3.1', '2.3.4.-1');
-
-  testParse('1.2.3pre1 - 2.3.4', '1.2.3pre1', '2.3.4');
-};
-
-exports['test increment(version)'] = assert => {
-  const testInc = TestInc(assert);
-
-  testInc('1.2.3', '1.2.3.1');
-  testInc('1.2.3a', '1.2.3a1');
-  testInc('1.2.3pre', '1.2.3pre1');
-  testInc('1.2.3pre1', '1.2.3pre2');
-  testInc('1.2', '1.2.1');
-  testInc('1.2pre1a', '1.2pre1b');
-  testInc('1.2pre1pre', '1.2pre1prf');
-};
-
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-mpl2-license-header.js
+++ /dev/null
@@ -1,105 +0,0 @@
-// Note: This line is here intentionally, to break MPL2_LICENSE_TEST
-/* 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 options = require('@loader/options');
-const { id } = require("sdk/self");
-const { getAddonByID } = require("sdk/addon/manager");
-const { mapcat, map, filter, fromEnumerator } = require("sdk/util/sequence");
-const { readURISync } = require('sdk/net/url');
-const { Request } = require('sdk/request');
-const { defer } = require("sdk/core/promise");
-
-const ios = Cc['@mozilla.org/network/io-service;1'].
-              getService(Ci.nsIIOService);
-
-const MIT_LICENSE_HEADER = [];
-
-const MPL2_LICENSE_TEST = new RegExp([
-  "^\\/\\* 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\\/\\. \\*\\/"
-].join("\n"));
-
-// Note: Using regular expressions because the paths a different for cfx vs jpm
-const IGNORES = [
-  /lib[\/\\](diffpatcher|method)[\/\\].+$/, // MIT
-  /lib[\/\\]sdk[\/\\]fs[\/\\]path\.js$/, // MIT
-  /lib[\/\\]sdk[\/\\]system[\/\\]child_process[\/\\].*/,
-  /tests?[\/\\]buffers[\/\\].+$/, // MIT
-  /tests?[\/\\]path[\/\\]test-path\.js$/,
-  /tests?[\/\\]querystring[\/\\]test-querystring\.js$/,
-];
-
-const ignoreFile = file => !!IGNORES.find(regex => regex.test(file));
-
-const baseURI = "resource://test-sdk-addon/";
-
-const uri = (path="") => baseURI + path;
-
-const toFile = x => x.QueryInterface(Ci.nsIFile);
-const isTestFile = ({ path, leafName }) => {
-  return !ignoreFile(path) && /\.jsm?$/.test(leafName)
-};
-const getFileURI = x => ios.newFileURI(x).spec;
-
-const getDirectoryEntries = file => map(toFile, fromEnumerator(_ => file.directoryEntries));
-
-const isDirectory = x => x.isDirectory();
-const getEntries = directory => mapcat(entry => {
-  if (isDirectory(entry)) {
-    return getEntries(entry);
-  }
-  else if (isTestFile(entry)) {
-    return [ entry ];
-  }
-  return [];
-}, filter(() => true, getDirectoryEntries(directory)));
-
-function readURL(url) {
-  let { promise, resolve } = defer();
-
-  Request({
-    url: url,
-    overrideMimeType: "text/plain",
-    onComplete: (response) => resolve(response.text)
-  }).get();
-
-  return promise;
-}
-
-exports["test MPL2 license header"] = function*(assert) {
-  let addon = yield getAddonByID(id);
-  let xpiURI = addon.getResourceURI();
-  let rootURL = xpiURI.spec;
-  assert.ok(rootURL, rootURL);
-  let files = [...getEntries(xpiURI.QueryInterface(Ci.nsIFileURL).file)];
-
-  assert.ok(files.length > 1, files.length + " files found.");
-  let failures = [];
-  let success = 0;
-
-  for (let i = 0, len = files.length; i < len; i++) {
-    let file = files[i];
-    assert.ok(file.path, "Trying " + file.path);
-
-    const URI = ios.newFileURI(file);
-
-    let leafName = URI.spec.replace(rootURL, "");
-
-    let contents = yield readURL(URI.spec);
-    if (!MPL2_LICENSE_TEST.test(contents)) {
-      failures.push(leafName);
-    }
-  }
-
-  assert.equal(1, failures.length, "we expect one failure");
-  assert.ok(/test-mpl2-license-header\.js$/.test(failures[0]), "the only failure is this file");
-  failures.shift();
-  assert.equal("", failures.join(",\n"), failures.length + " files found missing the required mpl 2 header");
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-namespace.js
+++ /dev/null
@@ -1,120 +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 { ns } = require("sdk/core/namespace");
-const { Cc, Ci, Cu } = require("chrome");
-const { setTimeout } = require("sdk/timers")
-
-exports["test post GC references"] = function (assert, done) {
-  var target = {}, local = ns()
-  local(target).there = true
-
-  assert.equal(local(target).there, true, "namespaced preserved");
-
-  Cu.schedulePreciseGC(function() {
-    assert.equal(local(target).there, true, "namespace is preserved post GC");
-    done();
-  });
-};
-
-exports["test namsepace basics"] = function(assert) {
-  var privates = ns();
-  var object = { foo: function foo() { return "hello foo"; } };
-
-  assert.notEqual(privates(object), object,
-                  "namespaced object is not the same");
-  assert.ok(!('foo' in privates(object)),
-            "public properties are not in the namespace");
-
-  assert.equal(privates(object), privates(object),
-               "same namespaced object is returned on each call");
-};
-
-exports["test namespace overlays"] = function(assert) {
-  var _ = ns();
-  var object = { foo: 'foo' };
-
-  _(object).foo = 'bar';
-
-  assert.equal(_(object).foo, "bar",
-               "namespaced property `foo` changed value");
-
-  assert.equal(object.foo, "foo",
-               "public property `foo` has original value");
-
-  object.foo = "baz";
-  assert.equal(_(object).foo, "bar",
-               "property changes do not affect namespaced properties");
-
-  object.bar = "foo";
-  assert.ok(!("bar" in _(object)),
-              "new public properties are not reflected in namespace");
-};
-
-exports["test shared namespaces"] = function(assert) {
-  var _ = ns();
-
-  var f1 = { hello: 1 };
-  var f2 = { foo: 'foo', hello: 2 };
-  _(f1).foo = _(f2).foo = 'bar';
-
-  assert.equal(_(f1).hello, _(f2).hello, "namespace can be shared");
-  assert.notEqual(f1.hello, _(f1).hello, "shared namespace can overlay");
-  assert.notEqual(f2.hello, _(f2).hello, "target is not affected");
-
-  _(f1).hello = 3;
-
-  assert.notEqual(_(f1).hello, _(f2).hello,
-                  "namespaced property can be overided");
-  assert.equal(_(f2).hello, _({}).hello, "namespace does not change");
-};
-
-exports["test multi namespace"] = function(assert) {
-  var n1 = ns();
-  var n2 = ns();
-  var object = { baz: 1 };
-  n1(object).foo = 1;
-  n2(object).foo = 2;
-  n1(object).bar = n2(object).bar = 3;
-
-  assert.notEqual(n1(object).foo, n2(object).foo,
-                  "object can have multiple namespaces");
-  assert.equal(n1(object).bar, n2(object).bar,
-               "object can have matching props in diff namespaces");
-};
-
-exports["test ns alias"] = function(assert) {
-  assert.strictEqual(ns, require('sdk/core/namespace').Namespace,
-                      "ns is an alias of Namespace");
-};
-
-exports["test ns inheritance"] = function(assert) {
-  let _ = ns();
-
-  let prototype = { level: 1 };
-  let object = Object.create(prototype);
-  let delegee = Object.create(object);
-
-  _(prototype).foo = {};
-
-  assert.ok(!Object.prototype.hasOwnProperty.call(_(delegee), "foo"),
-            "namespaced property is not copied to descendants");
-  assert.equal(_(delegee).foo, _(prototype).foo,
-               "namespaced properties are inherited by descendants");
-
-  _(object).foo = {};
-  assert.notEqual(_(object).foo, _(prototype).foo,
-                  "namespaced properties may be shadowed");
-  assert.equal(_(object).foo, _(delegee).foo,
-               "shadwed properties are inherited by descendants");
-
-  _(object).bar = {};
-  assert.ok(!("bar" in _(prototype)),
-            "descendants properties are not copied to ancestors");
-  assert.ok(_(object).bar, _(delegee).bar,
-            "descendants properties are inherited");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-native-loader.js
+++ /dev/null
@@ -1,394 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-var {
-  Loader, main, unload, parseStack, resolve, nodeResolve
-} = require('toolkit/loader');
-var { readURI } = require('sdk/net/url');
-var { all } = require('sdk/core/promise');
-var { before, after } = require('sdk/test/utils');
-var testOptions = require('@test/options');
-
-var root = module.uri.substr(0, module.uri.lastIndexOf('/'))
-// The following adds Debugger constructor to the global namespace.
-const { Cc, Ci, Cu } = require('chrome');
-const { addDebuggerToGlobal } = Cu.import('resource://gre/modules/jsdebugger.jsm', {});
-addDebuggerToGlobal(this);
-
-const { NetUtil } = Cu.import('resource://gre/modules/NetUtil.jsm', {});
-
-const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"]
-        .getService(Ci.nsIResProtocolHandler);
-
-const fileRoot = resProto.resolveURI(NetUtil.newURI(root));
-
-let variants = [
-  {
-    description: "unpacked resource:",
-    getRootURI(fixture) {
-      return `${root}/fixtures/${fixture}/`;
-    },
-  },
-  {
-    description: "unpacked file:",
-    getRootURI(fixture) {
-      return `${fileRoot}/fixtures/${fixture}/`;
-    },
-  },
-  {
-    description: "packed resource:",
-    getRootURI(fixture) {
-      return `resource://${fixture}/`;
-    },
-  },
-  {
-    description: "packed jar:",
-    getRootURI(fixture) {
-      return `jar:${fileRoot}/fixtures/${fixture}.xpi!/`;
-    },
-  },
-];
-
-let fixtures = [
-  'native-addon-test',
-  'native-overrides-test',
-];
-
-for (let variant of variants) {
-  exports[`test nodeResolve (${variant.description})`] = function (assert) {
-    let rootURI = variant.getRootURI('native-addon-test');
-    let manifest = {};
-    manifest.dependencies = {};
-
-    // Handles extensions
-    resolveTest('../package.json', './dir/c.js', './package.json');
-    resolveTest('../dir/b.js', './dir/c.js', './dir/b.js');
-
-    resolveTest('./dir/b', './index.js', './dir/b.js');
-    resolveTest('../index', './dir/b.js', './index.js');
-    resolveTest('../', './dir/b.js', './index.js');
-    resolveTest('./dir/a', './index.js', './dir/a.js', 'Precedence dir/a.js over dir/a/');
-    resolveTest('../utils', './dir/a.js', './utils/index.js', 'Requiring a directory defaults to dir/index.js');
-    resolveTest('../newmodule', './dir/c.js', './newmodule/lib/file.js', 'Uses package.json main in dir to load appropriate "main"');
-    resolveTest('test-math', './utils/index.js', './node_modules/test-math/index.js',
-      'Dependencies default to their index.js');
-    resolveTest('test-custom-main', './utils/index.js', './node_modules/test-custom-main/lib/custom-entry.js',
-      'Dependencies use "main" entry');
-    resolveTest('test-math/lib/sqrt', './utils/index.js', './node_modules/test-math/lib/sqrt.js',
-      'Dependencies\' files can be consumed via "/"');
-
-    resolveTest('sdk/tabs/utils', './index.js', undefined,
-      'correctly ignores SDK references in paths');
-    resolveTest('fs', './index.js', undefined,
-      'correctly ignores built in node modules in paths');
-
-    resolveTest('test-add', './node_modules/test-math/index.js',
-      './node_modules/test-math/node_modules/test-add/index.js',
-      'Dependencies\' dependencies can be found');
-
-    resolveTest('resource://gre/modules/commonjs/sdk/tabs.js', './index.js', undefined,
-                'correctly ignores absolute URIs.');
-
-    resolveTest('../tabs', 'resource://gre/modules/commonjs/sdk/addon/bootstrap.js', undefined,
-                'correctly ignores attempts to resolve from a module at an absolute URI.');
-
-    resolveTest('sdk/tabs', 'resource://gre/modules/commonjs/sdk/addon/bootstrap.js', undefined,
-                'correctly ignores attempts to resolve from a module at an absolute URI.');
-
-    function resolveTest (id, requirer, expected, msg) {
-      let result = nodeResolve(id, requirer, { manifest: manifest, rootURI: rootURI });
-      assert.equal(result, expected, 'nodeResolve ' + id + ' from ' + requirer + ' ' +msg);
-    }
-  }
-
-  /*
-  // TODO not working in current env
-  exports[`test bundle (${variant.description`] = function (assert, done) {
-    loadAddon('/native-addons/native-addon-test/')
-  };
-  */
-
-  exports[`test native Loader overrides (${variant.description})`] = function*(assert) {
-    const expectedKeys = Object.keys(require("sdk/io/file")).join(", ");
-    const manifest = yield getJSON('/fixtures/native-overrides-test/package.json');
-    const rootURI = variant.getRootURI('native-overrides-test');
-
-    let loader = Loader({
-      paths: makePaths(rootURI),
-      rootURI: rootURI,
-      manifest: manifest,
-      metadata: manifest,
-      isNative: true
-    });
-
-    let program = main(loader);
-    let fooKeys = Object.keys(program.foo).join(", ");
-    let barKeys = Object.keys(program.foo).join(", ");
-    let fsKeys = Object.keys(program.fs).join(", ");
-    let overloadKeys = Object.keys(program.overload.fs).join(", ");
-    let overloadLibKeys = Object.keys(program.overloadLib.fs).join(", ");
-
-    assert.equal(fooKeys, expectedKeys, "foo exports sdk/io/file");
-    assert.equal(barKeys, expectedKeys, "bar exports sdk/io/file");
-    assert.equal(fsKeys, expectedKeys, "sdk/io/file exports sdk/io/file");
-    assert.equal(overloadKeys, expectedKeys, "overload exports foo which exports sdk/io/file");
-    assert.equal(overloadLibKeys, expectedKeys, "overload/lib/foo exports foo/lib/foo");
-    assert.equal(program.internal, "test", "internal exports ./lib/internal");
-    assert.equal(program.extra, true, "fs-extra was exported properly");
-
-    assert.equal(program.Tabs, "no tabs exist", "sdk/tabs exports ./lib/tabs from the add-on");
-    assert.equal(program.CoolTabs, "no tabs exist", "sdk/tabs exports ./lib/tabs from the node_modules");
-    assert.equal(program.CoolTabsLib, "a cool tabs implementation", "./lib/tabs true relative path from the node_modules");
-
-    assert.equal(program.ignore, "do not ignore this export", "../ignore override was ignored.");
-
-    unload(loader);
-  };
-
-  exports[`test invalid native Loader overrides cause no errors (${variant.description})`] = function*(assert) {
-    const manifest = yield getJSON('/fixtures/native-overrides-test/package.json');
-    const rootURI = variant.getRootURI('native-overrides-test');
-    const EXPECTED = JSON.stringify({});
-
-    let makeLoader = (rootURI, manifest) => Loader({
-      paths: makePaths(rootURI),
-      rootURI: rootURI,
-      manifest: manifest,
-      metadata: manifest,
-      isNative: true
-    });
-
-    manifest.jetpack.overrides = "string";
-    let loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a string caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack.overrides = true;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a boolean caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack.overrides = 5;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a number caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack.overrides = null;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to null caused no errors making the loader");
-    unload(loader);
-  };
-
-  exports[`test invalid native Loader jetpack key cause no errors (${variant.description})`] = function*(assert) {
-    const manifest = yield getJSON('/fixtures/native-overrides-test/package.json');
-    const rootURI = variant.getRootURI('native-overrides-test');
-    const EXPECTED = JSON.stringify({});
-
-    let makeLoader = (rootURI, manifest) => Loader({
-      paths: makePaths(rootURI),
-      rootURI: rootURI,
-      manifest: manifest,
-      metadata: manifest,
-      isNative: true
-    });
-
-    manifest.jetpack = "string";
-    let loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a string caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack = true;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a boolean caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack = 5;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to a number caused no errors making the loader");
-    unload(loader);
-
-    manifest.jetpack = null;
-    loader = makeLoader(rootURI, manifest);
-    assert.equal(JSON.stringify(loader.manifest.jetpack.overrides), EXPECTED,
-                 "setting jetpack.overrides to null caused no errors making the loader");
-    unload(loader);
-  };
-
-  exports[`test native Loader without mappings (${variant.description})`] = function (assert, done) {
-    getJSON('/fixtures/native-addon-test/package.json').then(manifest => {
-      let rootURI = variant.getRootURI('native-addon-test');
-      let loader = Loader({
-        paths: makePaths(rootURI),
-        rootURI: rootURI,
-        manifest: manifest,
-        isNative: true
-      });
-
-      let program = main(loader);
-      testLoader(program, assert);
-      unload(loader);
-      done();
-    }).catch((reason) => console.error(reason));
-  };
-
-  exports[`test require#resolve with relative, dependencies (${variant.description})`] = function(assert, done) {
-    getJSON('/fixtures/native-addon-test/package.json').then(manifest => {
-      let rootURI = variant.getRootURI('native-addon-test');
-      let loader = Loader({
-        paths: makePaths(rootURI),
-        rootURI: rootURI,
-        manifest: manifest,
-        isNative: true
-      });
-
-      let program = main(loader);
-      let fixtureRoot = program.require.resolve("./").replace(/index\.js$/, "");
-
-      assert.equal(variant.getRootURI("native-addon-test"), fixtureRoot, "correct resolution root");
-      assert.equal(program.require.resolve("test-math"), fixtureRoot + "node_modules/test-math/index.js", "works with node_modules");
-      assert.equal(program.require.resolve("./newmodule"), fixtureRoot + "newmodule/lib/file.js", "works with directory mains");
-      assert.equal(program.require.resolve("./dir/a"), fixtureRoot + "dir/a.js", "works with normal relative module lookups");
-      assert.equal(program.require.resolve("modules/Promise.jsm"), "resource://gre/modules/Promise.jsm", "works with path lookups");
-
-      // TODO bug 1050422, handle loading non JS/JSM file paths
-      // assert.equal(program.require.resolve("test-assets/styles.css"), fixtureRoot + "node_modules/test-assets/styles.css",
-      // "works with different file extension lookups in dependencies");
-
-      unload(loader);
-      done();
-    }).catch((reason) => console.error(reason));
-  };
-}
-
-before(exports, () => {
-  for (let fixture of fixtures) {
-    let url = `jar:${root}/fixtures/${fixture}.xpi!/`;
-
-    resProto.setSubstitution(fixture, NetUtil.newURI(url));
-  }
-});
-
-after(exports, () => {
-  for (let fixture of fixtures)
-    resProto.setSubstitution(fixture, null);
-});
-
-exports['test JSM loading'] = function (assert, done) {
-  getJSON('/fixtures/jsm-package/package.json').then(manifest => {
-    let rootURI = root + '/fixtures/jsm-package/';
-    let loader = Loader({
-      paths: makePaths(rootURI),
-      rootURI: rootURI,
-      manifest: manifest,
-      isNative: true
-    });
-
-    let program = main(loader);
-    assert.ok(program.localJSMCached, 'local relative JSMs are cached');
-    assert.ok(program.isCachedJSAbsolute , 'absolute resource:// js are cached');
-    assert.ok(program.isCachedPath, 'JSMs resolved in paths are cached');
-    assert.ok(program.isCachedAbsolute, 'absolute resource:// JSMs are cached');
-
-    assert.ok(program.localJSM, 'able to load local relative JSMs');
-    all([
-      program.isLoadedPath(10),
-      program.isLoadedAbsolute(20),
-      program.isLoadedJSAbsolute(30)
-    ]).then(([path, absolute, jsabsolute]) => {
-      assert.equal(path, 10, 'JSM files resolved from path work');
-      assert.equal(absolute, 20, 'JSM files resolved from full resource:// work');
-      assert.equal(jsabsolute, 30, 'JS files resolved from full resource:// work');
-    }).then(done, console.error);
-
-  }).catch(console.error);
-};
-
-function testLoader (program, assert) {
-  // Test 'main' entries
-  // no relative custom main `lib/index.js`
-  assert.equal(program.customMainModule, 'custom entry file',
-    'a node_module dependency correctly uses its `main` entry in manifest');
-  // relative custom main `./lib/index.js`
-  assert.equal(program.customMainModuleRelative, 'custom entry file relative',
-    'a node_module dependency correctly uses its `main` entry in manifest with relative ./');
-  // implicit './index.js'
-  assert.equal(program.defaultMain, 'default main',
-    'a node_module dependency correctly defautls to index.js for main');
-
-  // Test directory exports
-  assert.equal(program.directoryDefaults, 'utils',
-    '`require`ing a directory defaults to dir/index.js');
-  assert.equal(program.directoryMain, 'main from new module',
-    '`require`ing a directory correctly loads the `main` entry and not index.js');
-  assert.equal(program.resolvesJSoverDir, 'dir/a',
-    '`require`ing "a" resolves "a.js" over "a/index.js"');
-
-  // Test dependency's dependencies
-  assert.ok(program.math.add,
-    'correctly defaults to index.js of a module');
-  assert.equal(program.math.add(10, 5), 15,
-    'node dependencies correctly include their own dependencies');
-  assert.equal(program.math.subtract(10, 5), 5,
-    'node dependencies correctly include their own dependencies');
-  assert.equal(program.mathInRelative.subtract(10, 5), 5,
-    'relative modules can also include node dependencies');
-
-  // Test SDK natives
-  assert.ok(program.promise.defer, 'main entry can include SDK modules with no deps');
-  assert.ok(program.promise.resolve, 'main entry can include SDK modules with no deps');
-  assert.ok(program.eventCore.on, 'main entry can include SDK modules that have dependencies');
-  assert.ok(program.eventCore.off, 'main entry can include SDK modules that have dependencies');
-
-  // Test JSMs
-  assert.ok(program.promisejsm.defer, 'can require JSM files in path');
-  assert.equal(program.localJSM.test, 'this is a jsm',
-    'can require relative JSM files');
-
-  // Other tests
-  assert.equal(program.areModulesCached, true,
-    'modules are correctly cached');
-  assert.equal(program.testJSON.dependencies['test-math'], '*',
-    'correctly requires JSON files');
-}
-
-function getJSON (uri) {
-  return readURI(root + uri).then(manifest => JSON.parse(manifest));
-}
-
-function makePaths (uri) {
-  // Uses development SDK modules if overloaded in loader
-  let sdkPaths = testOptions.paths ? testOptions.paths[''] : 'resource://gre/modules/commonjs/';
-  return {
-    './': uri,
-    'sdk/': sdkPaths + 'sdk/',
-    'toolkit/': sdkPaths + 'toolkit/',
-    'modules/': 'resource://gre/modules/'
-  };
-}
-
-function loadAddon (uri, map) {
-  let rootURI = root + uri;
-  getJSON(uri + '/package.json').then(manifest => {
-    let loader = Loader({
-      paths: makePaths(rootURI),
-      rootURI: rootURI,
-      manifest: manifest,
-      isNative: true,
-      modules: {
-        '@test/options': testOptions
-      }
-    });
-    let program = main(loader);
-  }).catch(console.error);
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-native-options.js
+++ /dev/null
@@ -1,183 +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 { setDefaults, injectOptions: inject, validate } = require('sdk/preferences/native-options');
-const { activeBrowserWindow: { document } } = require("sdk/deprecated/window-utils");
-const { preferencesBranch, id } = require('sdk/self');
-const { get } = require('sdk/preferences/service');
-const { setTimeout } = require('sdk/timers');
-const simple = require('sdk/simple-prefs');
-const fixtures = require('./fixtures');
-const { Cc, Ci } = require('chrome');
-
-const prefsrv = Cc['@mozilla.org/preferences-service;1'].
-                    getService(Ci.nsIPrefService);
-
-function injectOptions(preferences, preferencesBranch, document, parent) {
-  inject({
-    id: id,
-    preferences: preferences,
-    preferencesBranch: preferencesBranch,
-    document: document,
-    parent: parent
-  });
-}
-
-exports.testValidate = function(assert) {
-  let { preferences } = packageJSON('simple-prefs');
-
-  let block = () => validate(preferences);
-
-  delete preferences[3].options[0].value;
-  assert.throws(block, /option requires both a value/, "option missing value error");
-
-  delete preferences[2].options;
-  assert.throws(block, /'test3' pref requires options/, "menulist missing options error");
-
-  preferences[1].type = 'control';
-  assert.throws(block, /'test2' control requires a label/, "control missing label error");
-
-  preferences[1].type = 'nonvalid';
-  assert.throws(block, /'test2' pref must be of valid type/, "invalid pref type error");
-
-  delete preferences[0].title;
-  assert.throws(block, /'test' pref requires a title/, "pref missing title error");
-}
-
-exports.testNoPrefs = function(assert, done) {
-  let { preferences } = packageJSON('no-prefs');
-
-  let parent = document.createDocumentFragment();
-  injectOptions(preferences || [], preferencesBranch, document, parent);
-  assert.equal(parent.children.length, 0, "No setting elements injected");
-
-  // must test with events because we can't reset default prefs
-  function onPrefChange(name) {
-    assert.fail("No preferences should be defined");
-  }
-
-  simple.on('', onPrefChange);
-  setDefaults(preferences || [], preferencesBranch);
-  setTimeout(function() {
-    assert.pass("No preferences were defined");
-    simple.off('', onPrefChange);
-    done();
-  }, 100);
-}
-
-exports.testCurlyID = function(assert) {
-  let { preferences, id } = packageJSON('curly-id');
-  let branch = prefsrv.getDefaultBranch('extensions.' + id);
-
-  let parent = document.createDocumentFragment();
-  injectOptions(preferences, id, document, parent);
-  assert.equal(parent.children.length, 1, "One setting elements injected");
-  assert.equal(parent.firstElementChild.attributes.pref.value,
-               "extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13",
-               "Setting pref attribute is set properly");
-
-  setDefaults(preferences, id);
-  assert.equal(get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13'),
-               26, "test13 is 26");
-
-  branch.deleteBranch('');
-  assert.equal(get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13'),
-               undefined, "test13 is undefined");
-}
-
-exports.testPreferencesBranch = function(assert) {
-  let { preferences, 'preferences-branch': prefsBranch } = packageJSON('preferences-branch');
-  let branch = prefsrv.getDefaultBranch('extensions.' + prefsBranch);
-
-  let parent = document.createDocumentFragment();
-  injectOptions(preferences, prefsBranch, document, parent);
-  assert.equal(parent.children.length, 1, "One setting elements injected");
-  assert.equal(parent.firstElementChild.attributes.pref.value,
-               "extensions.human-readable.test42",
-               "Setting pref attribute is set properly");
-
-  setDefaults(preferences, prefsBranch);
-  assert.equal(get('extensions.human-readable.test42'), true, "test42 is true");
-
-  branch.deleteBranch('');
-  assert.equal(get('extensions.human-readable.test42'), undefined, "test42 is undefined");
-}
-
-exports.testSimplePrefs = function(assert) {
-  let { preferences } = packageJSON('simple-prefs');
-  let branch = prefsrv.getDefaultBranch('extensions.' + preferencesBranch);
-
-  function assertPref(setting, name, type, title, description = null) {
-    assert.equal(setting.getAttribute('data-jetpack-id'), id,
-                 "setting 'data-jetpack-id' attribute correct");
-    assert.equal(setting.getAttribute('pref'), 'extensions.' + id + '.' + name,
-                 "setting 'pref' attribute correct");
-    assert.equal(setting.getAttribute('pref-name'), name,
-                 "setting 'pref-name' attribute correct");
-    assert.equal(setting.getAttribute('type'), type,
-                 "setting 'type' attribute correct");
-    assert.equal(setting.getAttribute('title'), title,
-                 "setting 'title' attribute correct");
-    if (description) {
-      assert.equal(setting.getAttribute('desc'), description,
-                 "setting 'desc' attribute correct");
-    }
-    else {
-      assert.ok(!setting.hasAttribute('desc'),
-                 "setting 'desc' attribute is not present");
-    }
-  }
-
-  function assertOption(option, value, label) {
-    assert.equal(option.getAttribute('value'), value, "value attribute correct");
-    assert.equal(option.getAttribute('label'), label, "label attribute correct");
-  }
-
-  let parent = document.createDocumentFragment();
-  injectOptions(preferences, preferencesBranch, document, parent);
-  assert.equal(parent.children.length, 8, "Eight setting elements injected");
-
-  assertPref(parent.children[0], 'test', 'bool', 't\u00EBst', 'descr\u00EFpti\u00F6n');
-  assertPref(parent.children[1], 'test2', 'string', 't\u00EBst');
-  assertPref(parent.children[2], 'test3', 'menulist', '"><test');
-  assertPref(parent.children[3], 'test4', 'radio', 't\u00EBst');
-
-  assertPref(parent.children[4], 'test5', 'boolint', 'part part, particle');
-  assertPref(parent.children[5], 'test6', 'color', 'pop pop, popscicle');
-  assertPref(parent.children[6], 'test7', 'file', 'bike bike');
-  assertPref(parent.children[7], 'test8', 'directory', 'test test');
-
-  let menuItems = parent.children[2].querySelectorAll('menupopup>menuitem');
-  let radios = parent.children[3].querySelectorAll('radiogroup>radio');
-
-  assertOption(menuItems[0], '0', 'label1');
-  assertOption(menuItems[1], '1', 'label2');
-  assertOption(radios[0], 'red', 'rouge');
-  assertOption(radios[1], 'blue', 'bleu');
-
-  setDefaults(preferences, preferencesBranch);
-  assert.strictEqual(simple.prefs.test, false, "test is false");
-  assert.strictEqual(simple.prefs.test2, "\u00FCnic\u00F8d\u00E9", "test2 is unicode");
-  assert.strictEqual(simple.prefs.test3, "1", "test3 is '1'");
-  assert.strictEqual(simple.prefs.test4, "red", "test4 is 'red'");
-
-  // Only delete the test preferences to avoid unsetting any test harness
-  // preferences.
-  for (let setting of parent.children) {
-    let name = setting.getAttribute('pref-name');
-    branch.deleteBranch("." + name);
-  }
-
-  assert.strictEqual(simple.prefs.test, undefined, "test is undefined");
-  assert.strictEqual(simple.prefs.test2, undefined, "test2 is undefined");
-  assert.strictEqual(simple.prefs.test3, undefined, "test3 is undefined");
-  assert.strictEqual(simple.prefs.test4, undefined, "test4 is undefined");
-}
-
-function packageJSON(dir) {
-  return require(fixtures.url('preferences/' + dir + '/package.json'));
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-net-url.js
+++ /dev/null
@@ -1,137 +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 { readURI, readURISync } = require("sdk/net/url");
-const data = require("./fixtures");
-
-const utf8text = "Hello, ゼロ!";
-const latin1text = "Hello, ゼロ!";
-
-const dataURIutf8 = "data:text/plain;charset=utf-8," + encodeURIComponent(utf8text);
-const dataURIlatin1 = "data:text/plain;charset=ISO-8859-1," + escape(latin1text);
-const chromeURI = "chrome://global-platform/locale/accessible.properties";
-
-exports["test async readURI"] = function(assert, done) {
-  let content = "";
-
-  readURI(data.url("test-net-url.txt")).then(function(data) {
-    content = data;
-    assert.equal(content, utf8text, "The URL content is loaded properly");
-    done();
-  }, function() {
-    assert.fail("should not reject");
-    done();
-  })
-
-  assert.equal(content, "", "The URL content is not load yet");
-}
-
-exports["test readURISync"] = function(assert) {
-  let content = readURISync(data.url("test-net-url.txt"));
-
-  assert.equal(content, utf8text, "The URL content is loaded properly");
-}
-
-exports["test async readURI with ISO-8859-1 charset"] = function(assert, done) {
-  let content = "";
-
-  readURI(data.url("test-net-url.txt"), { charset : "ISO-8859-1"}).then(function(data) {
-    content = data;
-    assert.equal(content, latin1text, "The URL content is loaded properly");
-    done();
-  }, function() {
-    assert.fail("should not reject");
-    done();
-  })
-
-  assert.equal(content, "", "The URL content is not load yet");
-}
-
-exports["test readURISync with ISO-8859-1 charset"] = function(assert) {
-  let content = readURISync(data.url("test-net-url.txt"), "ISO-8859-1");
-
-  assert.equal(content, latin1text, "The URL content is loaded properly");
-}
-
-exports["test async readURI with not existing file"] = function(assert, done) {
-  readURI(data.url("test-net-url-fake.txt")).then(function(data) {
-    assert.fail("should not resolve");
-    done();
-  }, function(reason) {
-    assert.ok(reason.indexOf("Failed to read:") === 0);
-    done();
-  })
-}
-
-exports["test readURISync with not existing file"] = function(assert) {
-  assert.throws(function() {
-    readURISync(data.url("test-net-url-fake.txt"));
-  }, /NS_ERROR_FILE_NOT_FOUND/);
-}
-
-exports["test async readURI with data URI"] = function(assert, done) {
-  let content = "";
-
-  readURI(dataURIutf8).then(function(data) {
-    content = data;
-    assert.equal(content, utf8text, "The URL content is loaded properly");
-    done();
-  }, function() {
-    assert.fail("should not reject");
-    done();
-  })
-
-  assert.equal(content, "", "The URL content is not load yet");
-}
-
-exports["test readURISync with data URI"] = function(assert) {
-  let content = readURISync(dataURIutf8);
-
-  assert.equal(content, utf8text, "The URL content is loaded properly");
-}
-
-exports["test async readURI with data URI and ISO-8859-1 charset"] = function(assert, done) {
-  let content = "";
-
-  readURI(dataURIlatin1, { charset : "ISO-8859-1"}).then(function(data) {
-    content = unescape(data);
-    assert.equal(content, latin1text, "The URL content is loaded properly");
-    done();
-  }, function() {
-    assert.fail("should not reject");
-    done();
-  })
-
-  assert.equal(content, "", "The URL content is not load yet");
-}
-
-exports["test readURISync with data URI and ISO-8859-1 charset"] = function(assert) {
-  let content = unescape(readURISync(dataURIlatin1, "ISO-8859-1"));
-
-  assert.equal(content, latin1text, "The URL content is loaded properly");
-}
-
-exports["test readURISync with chrome URI"] = function(assert) {
-  let content = readURISync(chromeURI);
-
-  assert.ok(content, "The URL content is loaded properly");
-}
-
-exports["test async readURI with chrome URI"] = function(assert, done) {
-  let content = "";
-
-  readURI(chromeURI).then(function(data) {
-    content = data;
-    assert.equal(content, readURISync(chromeURI), "The URL content is loaded properly");
-    done();
-  }, function() {
-    assert.fail("should not reject");
-    done();
-  })
-
-  assert.equal(content, "", "The URL content is not load yet");
-}
-
-require("sdk/test").run(exports)
deleted file mode 100644
--- a/addon-sdk/source/test/test-node-os.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var os = require("node/os");
-var system = require("sdk/system");
-
-exports["test os"] = function (assert) {
-  assert.equal(os.tmpdir(), system.pathFor("TmpD"), "os.tmpdir() matches temp dir");
-  assert.ok(os.endianness() === "BE" || os.endianness() === "LE", "os.endianness is BE or LE");
-
-  assert.ok(os.arch().length > 0, "os.arch() returns a value");
-  assert.equal(typeof os.arch(), "string", "os.arch() returns a string");
-  assert.ok(os.type().length > 0, "os.type() returns a value");
-  assert.equal(typeof os.type(), "string", "os.type() returns a string");
-  assert.ok(os.platform().length > 0, "os.platform() returns a value");
-  assert.equal(typeof os.platform(), "string", "os.platform() returns a string");
-
-  assert.ok(os.release().length > 0, "os.release() returns a value");
-  assert.equal(typeof os.release(), "string", "os.release() returns a string");
-  assert.ok(os.hostname().length > 0, "os.hostname() returns a value");
-  assert.equal(typeof os.hostname(), "string", "os.hostname() returns a string");
-  assert.ok(os.EOL === "\n" || os.EOL === "\r\n", "os.EOL returns a correct EOL char");
-
-  assert.deepEqual(os.loadavg(), [0, 0, 0], "os.loadavg() returns an array of 0s");
-
-  ["uptime", "totalmem", "freemem", "cpus"].forEach(method => {
-    assert.throws(() => os[method](), "os." + method + " throws");
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-notifications.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-const { Loader } = require('sdk/test/loader');
-
-exports["test onClick"] = function(assert) {
-  let [loader, mockAlertServ] = makeLoader(module);
-  let notifs = loader.require("sdk/notifications");
-  let data = "test data";
-  let opts = {
-    onClick: function (clickedData) {
-      assert.equal(this, notifs, "|this| should be notifications module");
-      assert.equal(clickedData, data,
-                       "data passed to onClick should be correct");
-    },
-    data: data,
-    title: "test title",
-    text: "test text",
-    iconURL: "test icon URL"
-  };
-  notifs.notify(opts);
-  mockAlertServ.click();
-  loader.unload();
-};
-
-exports['test numbers and URLs in options'] = function(assert) {
-  let [loader] = makeLoader(module);
-  let notifs = loader.require('sdk/notifications');
-  let opts = {
-    title: 123,
-    text: 45678,
-    // must use in-loader `sdk/url` module for the validation type check to work
-    iconURL: loader.require('sdk/url').URL('data:image/png,blah')
-  };
-  try {
-    notifs.notify(opts);
-    assert.pass('using numbers and URLs in options works');
-  } catch (e) {
-    assert.fail('using numbers and URLs in options must not throw');
-  }
-  loader.unload();
-}
-
-exports['test new tag, dir and lang options'] = function(assert) {
-  let [loader] = makeLoader(module);
-  let notifs = loader.require('sdk/notifications');
-  let opts = {
-    title: 'best',
-    tag: 'tagging',
-    lang: 'en'
-  };
-
-  try {
-    opts.dir = 'ttb';
-    notifs.notify(opts);
-    assert.fail('`dir` option must not accept TopToBottom direction.');
-  } catch (e) {
-    assert.equal(e.message,
-      '`dir` option must be one of: "auto", "ltr" or "rtl".');
-  }
-
-  try {
-    opts.dir = 'rtl';
-    notifs.notify(opts);
-    assert.pass('`dir` option accepts "rtl" direction.');
-  } catch (e) {
-    assert.fail('`dir` option must accept "rtl" direction.');
-  }
-
-  loader.unload();
-}
-
-// Returns [loader, mockAlertService].
-function makeLoader(module) {
-  let loader = Loader(module);
-  let mockAlertServ = {
-    showAlertNotification: function (imageUrl, title, text, textClickable,
-                                     cookie, alertListener, name) {
-      this._cookie = cookie;
-      this._alertListener = alertListener;
-    },
-    click: function () {
-      this._alertListener.observe(null, "alertclickcallback", this._cookie);
-    }
-  };
-  loader.require("sdk/notifications");
-  let scope = loader.sandbox("sdk/notifications");
-  scope.notify = mockAlertServ.showAlertNotification.bind(mockAlertServ);
-  return [loader, mockAlertServ];
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-object.js
+++ /dev/null
@@ -1,36 +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 { merge, extend, has, each } = require('sdk/util/object');
-
-var o = {
-  'paper': 0,
-  'rock': 1,
-  'scissors': 2
-};
-
-//exports.testMerge = function(assert) {}
-//exports.testExtend = function(assert) {}
-
-exports.testHas = function(assert) {
-  assert.equal(has(o, 'paper'), true, 'has correctly finds key');
-  assert.equal(has(o, 'rock'), true, 'has correctly finds key');
-  assert.equal(has(o, 'scissors'), true, 'has correctly finds key');
-  assert.equal(has(o, 'nope'), false, 'has correctly does not find key');
-  assert.equal(has(o, '__proto__'), false, 'has correctly does not find key');
-  assert.equal(has(o, 'isPrototypeOf'), false, 'has correctly does not find key');
-};
-
-exports.testEach = function(assert) {
-  var keys = new Set();
-  each(o, function (value, key, object) {
-    keys.add(key);
-    assert.equal(o[key], value, 'Key and value pairs passed in');
-    assert.equal(o, object, 'Object passed in');
-  });
-  assert.equal(keys.size, 3, 'All keys have been iterated upon');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-observers.js
+++ /dev/null
@@ -1,183 +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 { Loader } = require("sdk/test/loader");
-const { isWeak, WeakReference } = require("sdk/core/reference");
-const { subscribe, unsubscribe,
-        observe, Observer } = require("sdk/core/observer");
-const { Class } = require("sdk/core/heritage");
-
-const { Cc, Ci, Cu } = require("chrome");
-const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
-                              getService(Ci.nsIObserverService);
-const { defer } = require("sdk/core/promise");
-
-const message = x => ({wrappedJSObject: x});
-
-exports["test subscribe unsubscribe"] = assert => {
-  const topic = Date.now().toString(32);
-  const Subscriber = Class({
-    extends: Observer,
-    initialize: function(observe) {
-      this.observe = observe;
-    }
-  });
-  observe.define(Subscriber, (x, subject, _, data) =>
-                                x.observe(subject.wrappedJSObject.x));
-
-  let xs = [];
-  const x = Subscriber((...rest) => xs.push(...rest));
-
-  let ys = [];
-  const y = Subscriber((...rest) => ys.push(...rest));
-
-  const publish = (topic, data) =>
-    notifyObservers(message(data), topic, null);
-
-  publish({x:0});
-
-  subscribe(x, topic);
-
-  publish(topic, {x:1});
-
-  subscribe(y, topic);
-
-  publish(topic, {x:2});
-  publish(topic + "!", {x: 2.5});
-
-  unsubscribe(x, topic);
-
-  publish(topic, {x:3});
-
-  subscribe(y, topic);
-
-  publish(topic, {x:4});
-
-  subscribe(x, topic);
-
-  publish(topic, {x:5});
-
-  unsubscribe(x, topic);
-  unsubscribe(y, topic);
-
-  publish(topic, {x:6});
-
-  assert.deepEqual(xs, [1, 2, 5]);
-  assert.deepEqual(ys, [2, 3, 4, 5]);
-}
-
-exports["test weak observers are GC-ed on unload"] = (assert, end) => {
-  const topic = Date.now().toString(32);
-  const loader = Loader(module);
-  const { Observer, observe,
-          subscribe, unsubscribe } = loader.require("sdk/core/observer");
-  const { isWeak, WeakReference } = loader.require("sdk/core/reference");
-
-  const MyObserver = Class({
-    extends: Observer,
-    initialize: function(observe) {
-      this.observe = observe;
-    }
-  });
-  observe.define(MyObserver, (x, ...rest) => x.observe(...rest));
-
-  const MyWeakObserver = Class({
-    extends: MyObserver,
-    implements: [WeakReference]
-  });
-
-  let xs = [];
-  let ys = [];
-  let x = new MyObserver((subject, topic, data) => {
-    xs.push(subject.wrappedJSObject, topic, data);
-  });
-  let y = new MyWeakObserver((subject, topic, data) => {
-    ys.push(subject.wrappedJSObject, topic, data);
-  });
-
-  subscribe(x, topic);
-  subscribe(y, topic);
-
-
-  notifyObservers(message({ foo: 1 }), topic, null);
-  x = null;
-  y = null;
-  loader.unload();
-
-  Cu.schedulePreciseGC(() => {
-
-    notifyObservers(message({ bar: 2 }), topic, ":)");
-
-    assert.deepEqual(xs, [{ foo: 1 }, topic, null,
-                          { bar: 2 }, topic, ":)"],
-                     "non week observer is kept");
-
-    assert.deepEqual(ys, [{ foo: 1 }, topic, null],
-                     "week observer was GC-ed");
-
-    end();
-  });
-};
-
-exports["test weak observer unsubscribe"] = function*(assert) {
-  const loader = Loader(module);
-  const { Observer, observe, subscribe, unsubscribe } = loader.require("sdk/core/observer");
-  const { WeakReference } = loader.require("sdk/core/reference");
-
-  let sawNotification = false;
-  let firstWait = defer();
-  let secondWait = defer();
-
-  const WeakObserver = Class({
-    extends: Observer,
-    implements: [WeakReference],
-    observe: function() {
-      sawNotification = true;
-      firstWait.resolve();
-    }
-  });
-
-  const StrongObserver = Class({
-    extends: Observer,
-    observe: function() {
-      secondWait.resolve();
-    }
-  });
-
-  observe.define(Observer, (x, ...rest) => x.observe(...rest));
-
-  let weakObserver = new WeakObserver;
-  let strongObserver = new StrongObserver();
-  subscribe(weakObserver, "test-topic");
-  subscribe(strongObserver, "test-wait");
-
-  notifyObservers(null, "test-topic", null);
-  yield firstWait.promise;
-
-  assert.ok(sawNotification, "Should have seen notification before GC");
-  sawNotification = false;
-
-  yield loader.require("sdk/test/memory").gc();
-
-  notifyObservers(null, "test-topic", null);
-  notifyObservers(null, "test-wait", null);
-  yield secondWait.promise;
-
-  assert.ok(sawNotification, "Should have seen notification after GC");
-  sawNotification = false;
-
-  try {
-    unsubscribe(weakObserver, "test-topic");
-    unsubscribe(strongObserver, "test-wait");
-    assert.pass("Should not have seen an exception");
-  }
-  catch (e) {
-    assert.fail("Should not have seen an exception");
-  }
-
-  loader.unload();
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-page-mod-debug.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/. */
-"use strict";
-
-const { Cc, Ci, Cu } = require("chrome");
-const { PageMod } = require("sdk/page-mod");
-const { testPageMod, handleReadyState, openNewTab,
-        contentScriptWhenServer, createLoader } = require("./page-mod/helpers");
-const { cleanUI, after } = require("sdk/test/utils");
-const { open, getFrames, getMostRecentBrowserWindow, getInnerId } = require("sdk/window/utils");
-
-// The following adds Debugger constructor to the global namespace.
-const { addDebuggerToGlobal } = require('resource://gre/modules/jsdebugger.jsm');
-addDebuggerToGlobal(this);
-
-exports.testDebugMetadata = function(assert, done) {
-  let dbg = new Debugger;
-  let globalDebuggees = [];
-  dbg.onNewGlobalObject = function(global) {
-    globalDebuggees.push(global);
-  }
-
-  let mods = testPageMod(assert, done, "about:", [{
-      include: "about:",
-      contentScriptWhen: "start",
-      contentScript: "null;",
-    }], function(win, done) {
-      assert.ok(globalDebuggees.some(function(global) {
-        try {
-          let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
-          return metadata && metadata.addonID && metadata.SDKContentScript &&
-                 metadata['inner-window-id'] == getInnerId(win);
-        } catch(e) {
-          // Some of the globals might not be Sandbox instances and thus
-          // will cause getSandboxMetadata to fail.
-          return false;
-        }
-      }), "one of the globals is a content script");
-      done();
-    }
-  );
-};
-
-after(exports, function*(name, assert) {
-  assert.pass("cleaning ui.");
-  yield cleanUI();
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-page-mod.js
+++ /dev/null
@@ -1,2211 +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 { PageMod } = require("sdk/page-mod");
-const { testPageMod, handleReadyState, openNewTab,
-        contentScriptWhenServer, createLoader } = require("./page-mod/helpers");
-const { Loader } = require("sdk/test/loader");
-const tabs = require("sdk/tabs");
-const { setTimeout } = require("sdk/timers");
-const system = require("sdk/system/events");
-const { open, getFrames, getMostRecentBrowserWindow, getInnerId } = require("sdk/window/utils");
-const { getTabContentWindow, getActiveTab, setTabURL, openTab, closeTab,
-        getBrowserForTab } = require("sdk/tabs/utils");
-const xulApp = require("sdk/system/xul-app");
-const { isPrivateBrowsingSupported } = require("sdk/self");
-const { isPrivate } = require("sdk/private-browsing");
-const { openWebpage } = require("./private-browsing/helper");
-const { isTabPBSupported, isWindowPBSupported } = require("sdk/private-browsing/utils");
-const promise = require("sdk/core/promise");
-const { pb } = require("./private-browsing/helper");
-const { URL } = require("sdk/url");
-const { defer, all, resolve } = require("sdk/core/promise");
-const { waitUntil } = require("sdk/test/utils");
-const data = require("./fixtures");
-const { cleanUI, after } = require("sdk/test/utils");
-
-const testPageURI = data.url("test.html");
-
-function Isolate(worker) {
-  return "(" + worker + ")()";
-}
-
-/* Tests for the PageMod APIs */
-
-exports.testPageMod1 = function*(assert) {
-  let modAttached = defer();
-  let mod = PageMod({
-    include: /about:/,
-    contentScriptWhen: "end",
-    contentScript: "new " + function WorkerScope() {
-      window.document.body.setAttribute("JEP-107", "worked");
-
-      self.port.once("done", () => {
-        self.port.emit("results", window.document.body.getAttribute("JEP-107"))
-      });
-    },
-    onAttach: function(worker) {
-      assert.equal(this, mod, "The 'this' object is the page mod.");
-      mod.port.once("results", modAttached.resolve)
-      mod.port.emit("done");
-    }
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: "about:",
-      inBackground: true,
-      onReady: resolve
-    })
-  });
-  assert.pass("test tab was opened.");
-
-  let worked = yield modAttached.promise;
-  assert.pass("test mod was attached.");
-
-  mod.destroy();
-  assert.pass("test mod was destroyed.");
-
-  assert.equal(worked, "worked", "PageMod.onReady test");
-};
-
-exports.testPageMod2 = function*(assert) {
-  let modAttached = defer();
-  let mod = PageMod({
-    include: testPageURI,
-    contentScriptWhen: "end",
-    contentScript: [
-      'new ' + function contentScript() {
-        window.AUQLUE = function() { return 42; }
-        try {
-          window.AUQLUE()
-        }
-        catch(e) {
-          throw new Error("PageMod scripts executed in order");
-        }
-        document.documentElement.setAttribute("first", "true");
-      },
-      'new ' + function contentScript() {
-        document.documentElement.setAttribute("second", "true");
-
-        self.port.once("done", () => {
-          self.port.emit("results", {
-            "first": window.document.documentElement.getAttribute("first"),
-            "second": window.document.documentElement.getAttribute("second"),
-            "AUQLUE": unsafeWindow.getAUQLUE()
-          });
-        });
-      }
-    ],
-    onAttach: modAttached.resolve
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: testPageURI,
-      inBackground: true,
-      onReady: resolve
-    })
-  });
-  assert.pass("test tab was opened.");
-
-  let worker = yield modAttached.promise;
-  assert.pass("test mod was attached.");
-
-  let results = yield new Promise(resolve => {
-    worker.port.once("results", resolve)
-    worker.port.emit("done");
-  });
-
-  mod.destroy();
-  assert.pass("test mod was destroyed.");
-
-  assert.equal(results["first"],
-               "true",
-               "PageMod test #2: first script has run");
-  assert.equal(results["second"],
-               "true",
-               "PageMod test #2: second script has run");
-  assert.equal(results["AUQLUE"], false,
-               "PageMod test #2: scripts get a wrapped window");
-};
-
-exports.testPageModIncludes = function*(assert) {
-  var modsAttached = [];
-  var modNumber = 0;
-  var modAttached = defer();
-  let includes = [
-    "*",
-    "*.google.com",
-    "resource:*",
-    "resource:",
-    testPageURI
-  ];
-  let expected = [
-    false,
-    false,
-    true,
-    false,
-    true
-  ]
-
-  let mod = PageMod({
-    include: testPageURI,
-    contentScript: 'new ' + function() {
-      self.port.on("get-local-storage", () => {
-        let result = {};
-        self.options.forEach(include => {
-          result[include] = !!window.localStorage[include]
-        });
-
-        self.port.emit("got-local-storage", result);
-
-        window.localStorage.clear();
-      });
-    },
-    contentScriptOptions: includes,
-    onAttach: modAttached.resolve
-  });
-
-  function createPageModTest(include, expectedMatch) {
-    var modIndex = modNumber++;
-
-    let attached = defer();
-    modsAttached.push(expectedMatch ? attached.promise : resolve());
-
-    // ...and corresponding PageMod options
-    return PageMod({
-      include: include,
-      contentScript: 'new ' + function() {
-        self.on("message", function(msg) {
-          window.localStorage[msg] = true
-          self.port.emit('done');
-        });
-      },
-      // The testPageMod callback with test assertions is called on 'end',
-      // and we want this page mod to be attached before it gets called,
-      // so we attach it on 'start'.
-      contentScriptWhen: 'start',
-      onAttach: function(worker) {
-        assert.pass("mod " + modIndex + " was attached");
-
-        worker.port.once("done", () => {
-          assert.pass("mod " + modIndex + " is done");
-          attached.resolve(worker);
-        });
-        worker.postMessage(this.include[0]);
-      }
-    });
-  }
-
-  let mods = [
-    createPageModTest("*", false),
-    createPageModTest("*.google.com", false),
-    createPageModTest("resource:*", true),
-    createPageModTest("resource:", false),
-    createPageModTest(testPageURI, true)
-  ];
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: testPageURI,
-      inBackground: true,
-      onReady: resolve
-    });
-  });
-  assert.pass("tab was opened");
-
-  yield all(modsAttached);
-  assert.pass("all mods were attached.");
-
-  mods.forEach(mod => mod.destroy());
-  assert.pass("all mods were destroyed.");
-
-  yield modAttached.promise;
-  assert.pass("final test mod was attached.");
-
-  yield new Promise(resolve => {
-    mod.port.on("got-local-storage", (storage) => {
-      includes.forEach((include, i) => {
-        assert.equal(storage[include], expected[i], "localStorage is correct for " + include);
-      });
-      resolve();
-    });
-    mod.port.emit("get-local-storage");
-  });
-  assert.pass("final test of localStorage is complete.");
-
-  mod.destroy();
-  assert.pass("final test mod was destroyed.");
-};
-
-exports.testPageModExcludes = function(assert, done) {
-  var asserts = [];
-  function createPageModTest(include, exclude, expectedMatch) {
-    // Create an 'onload' test function...
-    asserts.push(function(test, win) {
-      var matches = JSON.stringify([include, exclude]) in win.localStorage;
-      assert.ok(expectedMatch ? matches : !matches,
-          "[include, exclude] = [" + include + ", " + exclude +
-          "] match test, expected: " + expectedMatch);
-    });
-    // ...and corresponding PageMod options
-    return {
-      include: include,
-      exclude: exclude,
-      contentScript: 'new ' + function() {
-        self.on("message", function(msg) {
-          // The key in localStorage is "[<include>, <exclude>]".
-          window.localStorage[JSON.stringify(msg)] = true;
-        });
-      },
-      // The testPageMod callback with test assertions is called on 'end',
-      // and we want this page mod to be attached before it gets called,
-      // so we attach it on 'start'.
-      contentScriptWhen: 'start',
-      onAttach: function(worker) {
-        worker.postMessage([this.include[0], this.exclude[0]]);
-      }
-    };
-  }
-
-  testPageMod(assert, done, testPageURI, [
-      createPageModTest("*", testPageURI, false),
-      createPageModTest(testPageURI, testPageURI, false),
-      createPageModTest(testPageURI, "resource://*", false),
-      createPageModTest(testPageURI, "*.google.com", true)
-    ],
-    function (win, done) {
-      waitUntil(() => win.localStorage[JSON.stringify([testPageURI, "*.google.com"])],
-          testPageURI + " page-mod to be executed")
-        .then(() => {
-          asserts.forEach(fn => fn(assert, win));
-          win.localStorage.clear();
-          done();
-        });
-    });
-};
-
-exports.testPageModValidationAttachTo = function(assert) {
-  [{ val: 'top', type: 'string "top"' },
-   { val: 'frame', type: 'string "frame"' },
-   { val: ['top', 'existing'], type: 'array with "top" and "existing"' },
-   { val: ['frame', 'existing'], type: 'array with "frame" and "existing"' },
-   { val: ['top'], type: 'array with "top"' },
-   { val: ['frame'], type: 'array with "frame"' },
-   { val: undefined, type: 'undefined' }].forEach((attachTo) => {
-    new PageMod({ attachTo: attachTo.val, include: '*.validation111' });
-    assert.pass("PageMod() does not throw when attachTo is " + attachTo.type);
-  });
-
-  [{ val: 'existing', type: 'string "existing"' },
-   { val: ['existing'], type: 'array with "existing"' },
-   { val: 'not-legit', type: 'string with "not-legit"' },
-   { val: ['not-legit'], type: 'array with "not-legit"' },
-   { val: {}, type: 'object' }].forEach((attachTo) => {
-    assert.throws(() =>
-      new PageMod({ attachTo: attachTo.val, include: '*.validation111' }),
-      /The `attachTo` option/,
-      "PageMod() throws when 'attachTo' option is " + attachTo.type + ".");
-  });
-};
-
-exports.testPageModValidationInclude = function(assert) {
-  [{ val: undefined, type: 'undefined' },
-   { val: {}, type: 'object' },
-   { val: [], type: 'empty array'},
-   { val: [/regexp/, 1], type: 'array with non string/regexp' },
-   { val: 1, type: 'number' }].forEach((include) => {
-    assert.throws(() => new PageMod({ include: include.val }),
-      /The `include` option must always contain atleast one rule/,
-      "PageMod() throws when 'include' option is " + include.type + ".");
-  });
-
-  [{ val: '*.validation111', type: 'string' },
-   { val: /validation111/, type: 'regexp' },
-   { val: ['*.validation111'], type: 'array with length > 0'}].forEach((include) => {
-    new PageMod({ include: include.val });
-    assert.pass("PageMod() does not throw when include option is " + include.type);
-  });
-};
-
-exports.testPageModValidationExclude = function(assert) {
-  let includeVal = '*.validation111';
-
-  [{ val: {}, type: 'object' },
-   { val: [], type: 'empty array'},
-   { val: [/regexp/, 1], type: 'array with non string/regexp' },
-   { val: 1, type: 'number' }].forEach((exclude) => {
-    assert.throws(() => new PageMod({ include: includeVal, exclude: exclude.val }),
-      /If set, the `exclude` option must always contain at least one rule as a string, regular expression, or an array of strings and regular expressions./,
-      "PageMod() throws when 'exclude' option is " + exclude.type + ".");
-  });
-
-  [{ val: undefined, type: 'undefined' },
-   { val: '*.validation111', type: 'string' },
-   { val: /validation111/, type: 'regexp' },
-   { val: ['*.validation111'], type: 'array with length > 0'}].forEach((exclude) => {
-    new PageMod({ include: includeVal, exclude: exclude.val });
-    assert.pass("PageMod() does not throw when exclude option is " + exclude.type);
-  });
-};
-
-/* Tests for internal functions. */
-exports.testCommunication1 = function*(assert) {
-  let workerDone = defer();
-
-  let mod = PageMod({
-    include: "about:*",
-    contentScriptWhen: "end",
-    contentScript: 'new ' + function WorkerScope() {
-      self.on('message', function(msg) {
-        document.body.setAttribute('JEP-107', 'worked');
-        self.postMessage(document.body.getAttribute('JEP-107'));
-      });
-      self.port.on('get-jep-107', () => {
-        self.port.emit('got-jep-107', document.body.getAttribute('JEP-107'));
-      });
-    },
-    onAttach: function(worker) {
-      worker.on('error', function(e) {
-        assert.fail('Errors where reported');
-      });
-      worker.on('message', function(value) {
-        assert.equal(
-          "worked",
-          value,
-          "test comunication"
-        );
-        workerDone.resolve();
-      });
-      worker.postMessage("do it!")
-    }
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: "about:",
-      onReady: resolve
-    });
-  });
-  assert.pass("opened tab");
-
-  yield workerDone.promise;
-  assert.pass("the worker has made a change");
-
-  let value = yield new Promise(resolve => {
-    mod.port.once("got-jep-107", resolve);
-    mod.port.emit("get-jep-107");
-  });
-
-  assert.equal("worked", value, "attribute should be modified");
-
-  mod.destroy();
-  assert.pass("the worker was destroyed");
-};
-
-exports.testCommunication2 = function*(assert) {
-  let workerDone = defer();
-  let url = data.url("test.html");
-
-  let mod = PageMod({
-    include: url,
-    contentScriptWhen: 'start',
-    contentScript: 'new ' + function WorkerScope() {
-      document.documentElement.setAttribute('AUQLUE', 42);
-
-      window.addEventListener('load', function listener() {
-        self.postMessage({
-          msg: 'onload',
-          AUQLUE: document.documentElement.getAttribute('AUQLUE')
-        });
-      });
-
-      self.on("message", function(msg) {
-        if (msg == "get window.test") {
-          unsafeWindow.changesInWindow();
-        }
-
-        self.postMessage({
-          msg: document.documentElement.getAttribute("test")
-        });
-      });
-    },
-    onAttach: function(worker) {
-      worker.on('error', function(e) {
-        assert.fail('Errors where reported');
-      });
-      worker.on('message', function({ msg, AUQLUE }) {
-        if ('onload' == msg) {
-          assert.equal('42', AUQLUE, 'PageMod scripts executed in order');
-          worker.postMessage('get window.test');
-        }
-        else {
-          assert.equal('changes in window', msg, 'PageMod test #2: second script has run');
-          workerDone.resolve();
-        }
-      });
-    }
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: url,
-      inBackground: true,
-      onReady: resolve
-    });
-  });
-  assert.pass("opened tab");
-
-  yield workerDone.promise;
-
-  mod.destroy();
-  assert.pass("the worker was destroyed");
-};
-
-exports.testEventEmitter = function(assert, done) {
-  let workerDone = false,
-      callbackDone = null;
-
-  testPageMod(assert, done, "about:", [{
-      include: "about:*",
-      contentScript: 'new ' + function WorkerScope() {
-        self.port.on('addon-to-content', function(data) {
-          self.port.emit('content-to-addon', data);
-        });
-      },
-      onAttach: function(worker) {
-        worker.on('error', function(e) {
-          assert.fail('Errors were reported : '+e);
-        });
-        worker.port.on('content-to-addon', function(value) {
-          assert.equal(
-            "worked",
-            value,
-            "EventEmitter API works!"
-          );
-          if (callbackDone)
-            callbackDone();
-          else
-            workerDone = true;
-        });
-        worker.port.emit('addon-to-content', 'worked');
-      }
-    }],
-    function(win, done) {
-      if (workerDone)
-        done();
-      else
-        callbackDone = done;
-    }
-  );
-};
-
-// Execute two concurrent page mods on same document to ensure that their
-// JS contexts are different
-exports.testMixedContext = function(assert, done) {
-  let doneCallback = null;
-  let messages = 0;
-  let modObject = {
-    include: "data:text/html;charset=utf-8,",
-    contentScript: 'new ' + function WorkerScope() {
-      // Both scripts will execute this,
-      // context is shared if one script see the other one modification.
-      let isContextShared = "sharedAttribute" in document;
-      self.postMessage(isContextShared);
-      document.sharedAttribute = true;
-    },
-    onAttach: function(w) {
-      w.on("message", function (isContextShared) {
-        if (isContextShared) {
-          assert.fail("Page mod contexts are mixed.");
-          doneCallback();
-        }
-        else if (++messages == 2) {
-          assert.pass("Page mod contexts are different.");
-          doneCallback();
-        }
-      });
-    }
-  };
-  testPageMod(assert, done, "data:text/html;charset=utf-8,", [modObject, modObject],
-    function(win, done) {
-      doneCallback = done;
-    }
-  );
-};
-
-exports.testHistory = function(assert, done) {
-  // We need a valid url in order to have a working History API.
-  // (i.e do not work on data: or about: pages)
-  // Test bug 679054.
-  let url = data.url("test-page-mod.html");
-  let callbackDone = null;
-  testPageMod(assert, done, url, [{
-      include: url,
-      contentScriptWhen: 'end',
-      contentScript: 'new ' + function WorkerScope() {
-        history.pushState({}, "", "#");
-        history.replaceState({foo: "bar"}, "", "#");
-        self.postMessage(history.state);
-      },
-      onAttach: function(worker) {
-        worker.on('message', function (data) {
-          assert.equal(JSON.stringify(data), JSON.stringify({foo: "bar"}),
-                           "History API works!");
-          callbackDone();
-        });
-      }
-    }],
-    function(win, done) {
-      callbackDone = done;
-    }
-  );
-};
-
-exports.testRelatedTab = function(assert, done) {
-  let tab;
-  let pageMod = new PageMod({
-    include: "about:*",
-    onAttach: function(worker) {
-      assert.ok(!!worker.tab, "Worker.tab exists");
-      assert.equal(tab, worker.tab, "Worker.tab is valid");
-      pageMod.destroy();
-      tab.close(done);
-    }
-  });
-
-  tabs.open({
-    url: "about:",
-    onOpen: function onOpen(t) {
-      tab = t;
-    }
-  });
-};
-
-// related to bug #989288
-// https://bugzilla.mozilla.org/show_bug.cgi?id=989288
-exports.testRelatedTabNewWindow = function(assert, done) {
-  let url = "about:logo"
-  let pageMod = new PageMod({
-    include: url,
-    onAttach: function(worker) {
-      assert.equal(worker.tab.url, url, "Worker.tab.url is valid");
-      worker.tab.close(done);
-    }
-  });
-
-  tabs.activeTab.attach({
-    contentScript: "window.open('about:logo', '', " +
-                   "'width=800,height=600,resizable=no,status=no,location=no');"
-  });
-
-};
-
-exports.testRelatedTabNoRequireTab = function(assert, done) {
-  let loader = Loader(module);
-  let tab;
-  let url = "data:text/html;charset=utf-8," + encodeURI("Test related worker tab 2");
-  let { PageMod } = loader.require("sdk/page-mod");
-  let pageMod = new PageMod({
-    include: url,
-    onAttach: function(worker) {
-      assert.equal(worker.tab.url, url, "Worker.tab.url is valid");
-      worker.tab.close(function() {
-        pageMod.destroy();
-        loader.unload();
-        done();
-      });
-    }
-  });
-
-  tabs.open(url);
-};
-
-exports.testRelatedTabNoOtherReqs = function(assert, done) {
-  let loader = Loader(module);
-  let { PageMod } = loader.require("sdk/page-mod");
-  let pageMod = new PageMod({
-    include: "about:blank?testRelatedTabNoOtherReqs",
-    onAttach: function(worker) {
-      assert.ok(!!worker.tab, "Worker.tab exists");
-      pageMod.destroy();
-      worker.tab.close(function() {
-        worker.destroy();
-        loader.unload();
-        done();
-      });
-    }
-  });
-
-  tabs.open({
-    url: "about:blank?testRelatedTabNoOtherReqs"
-  });
-};
-
-exports.testWorksWithExistingTabs = function(assert, done) {
-  let url = "data:text/html;charset=utf-8," + encodeURI("Test unique document");
-  let { PageMod } = require("sdk/page-mod");
-  tabs.open({
-    url: url,
-    onReady: function onReady(tab) {
-      let pageModOnExisting = new PageMod({
-        include: url,
-        attachTo: ["existing", "top", "frame"],
-        onAttach: function(worker) {
-          assert.ok(!!worker.tab, "Worker.tab exists");
-          assert.equal(tab, worker.tab, "A worker has been created on this existing tab");
-
-          worker.on('pageshow', () => {
-            assert.fail("Should not have seen pageshow for an already loaded page");
-          });
-
-          setTimeout(function() {
-            pageModOnExisting.destroy();
-            pageModOffExisting.destroy();
-            tab.close(done);
-          }, 0);
-        }
-      });
-
-      let pageModOffExisting = new PageMod({
-        include: url,
-        onAttach: function(worker) {
-          assert.fail("pageModOffExisting page-mod should not have attached to anything");
-        }
-      });
-    }
-  });
-};
-
-exports.testExistingFrameDoesntMatchInclude = function(assert, done) {
-  let iframeURL = 'data:text/html;charset=utf-8,UNIQUE-TEST-STRING-42';
-  let iframe = '<iframe src="' + iframeURL + '" />';
-  let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(iframe);
-  tabs.open({
-    url: url,
-    onReady: function onReady(tab) {
-      let pagemod = new PageMod({
-        include: url,
-        attachTo: ['existing', 'frame'],
-        onAttach: function() {
-          assert.fail("Existing iframe URL doesn't match include, must not attach to anything");
-        }
-      });
-      setTimeout(function() {
-        assert.pass("PageMod didn't attach to anything")
-        pagemod.destroy();
-        tab.close(done);
-      }, 250);
-    }
-  });
-};
-
-exports.testExistingOnlyFrameMatchesInclude = function(assert, done) {
-  let iframeURL = 'data:text/html;charset=utf-8,UNIQUE-TEST-STRING-43';
-  let iframe = '<iframe src="' + iframeURL + '" />';
-  let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(iframe);
-  tabs.open({
-    url: url,
-    onReady: function onReady(tab) {
-      let pagemod = new PageMod({
-        include: iframeURL,
-        attachTo: ['existing', 'frame'],
-        onAttach: function(worker) {
-          assert.equal(iframeURL, worker.url,
-              "PageMod attached to existing iframe when only it matches include rules");
-          pagemod.destroy();
-          tab.close(done);
-        }
-      });
-    }
-  });
-};
-
-exports.testAttachOnlyOncePerDocument = function(assert, done) {
-  let iframeURL = 'data:text/html;charset=utf-8,testAttachOnlyOncePerDocument';
-  let iframe = '<iframe src="' + iframeURL + '" />';
-  let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(iframe);
-  let count = 0;
-
-  tabs.open({
-    url: url,
-    onReady: function onReady(tab) {
-      let pagemod = new PageMod({
-        include: iframeURL,
-        attachTo: ['existing', 'frame'],
-        onAttach: (worker) => {
-          count++;
-          assert.equal(iframeURL, worker.url,
-            "PageMod attached to existing iframe");
-          assert.equal(count, 1, "PageMod attached only once");
-          setTimeout(_ => {
-            assert.equal(count, 1, "PageMod attached only once");
-            pagemod.destroy();
-            tab.close(done);
-          }, 1);
-        }
-      });
-    }
-  });
-}
-
-exports.testContentScriptWhenDefault = function(assert) {
-  let pagemod = PageMod({include: '*'});
-
-  assert.equal(pagemod.contentScriptWhen, 'end', "Default contentScriptWhen is 'end'");
-  pagemod.destroy();
-}
-
-// test timing for all 3 contentScriptWhen options (start, ready, end)
-// for new pages, or tabs opened after PageMod is created
-exports.testContentScriptWhenForNewTabs = function(assert, done) {
-  let srv = contentScriptWhenServer();
-  let url = srv.URL + '?ForNewTabs';
-  let count = 0;
-
-  handleReadyState(url, 'start', {
-    onLoading: (tab) => {
-      assert.pass("PageMod is attached while document is loading");
-      checkDone(++count, tab, srv, done);
-    },
-    onInteractive: () => assert.fail("onInteractive should not be called with 'start'."),
-    onComplete: () => assert.fail("onComplete should not be called with 'start'."),
-  });
-
-  handleReadyState(url, 'ready', {
-    onInteractive: (tab) => {
-      assert.pass("PageMod is attached while document is interactive");
-      checkDone(++count, tab, srv, done);
-    },
-    onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
-    onComplete: () => assert.fail("onComplete should not be called with 'ready'."),
-  });
-
-  handleReadyState(url, 'end', {
-    onComplete: (tab) => {
-      assert.pass("PageMod is attached when document is complete");
-      checkDone(++count, tab, srv, done);
-    },
-    onLoading: () => assert.fail("onLoading should not be called with 'end'."),
-    onInteractive: () => assert.fail("onInteractive should not be called with 'end'."),
-  });
-
-  tabs.open(url);
-}
-
-// test timing for all 3 contentScriptWhen options (start, ready, end)
-// for PageMods created right as the tab is created (in tab.onOpen)
-exports.testContentScriptWhenOnTabOpen = function(assert, done) {
-  let srv = contentScriptWhenServer();
-  let url = srv.URL + '?OnTabOpen';
-  let count = 0;
-
-  tabs.open({
-    url: url,
-    onOpen: function(tab) {
-
-      handleReadyState(url, 'start', {
-        onLoading: () => {
-          assert.pass("PageMod is attached while document is loading");
-          checkDone(++count, tab, srv, done);
-        },
-        onInteractive: () => assert.fail("onInteractive should not be called with 'start'."),
-        onComplete: () => assert.fail("onComplete should not be called with 'start'."),
-      });
-
-      handleReadyState(url, 'ready', {
-        onInteractive: () => {
-          assert.pass("PageMod is attached while document is interactive");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
-        onComplete: () => assert.fail("onComplete should not be called with 'ready'."),
-      });
-
-      handleReadyState(url, 'end', {
-        onComplete: () => {
-          assert.pass("PageMod is attached when document is complete");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'end'."),
-        onInteractive: () => assert.fail("onInteractive should not be called with 'end'."),
-      });
-
-    }
-  });
-}
-
-// test timing for all 3 contentScriptWhen options (start, ready, end)
-// for PageMods created while the tab is interactive (in tab.onReady)
-exports.testContentScriptWhenOnTabReady = function(assert, done) {
-  let srv = contentScriptWhenServer();
-  let url = srv.URL + '?OnTabReady';
-  let count = 0;
-
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-
-      handleReadyState(url, 'start', {
-        onInteractive: () => {
-          assert.pass("PageMod is attached while document is interactive");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'start'."),
-        onComplete: () => assert.fail("onComplete should not be called with 'start'."),
-      });
-
-      handleReadyState(url, 'ready', {
-        onInteractive: () => {
-          assert.pass("PageMod is attached while document is interactive");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
-        onComplete: () => assert.fail("onComplete should not be called with 'ready'."),
-      });
-
-      handleReadyState(url, 'end', {
-        onComplete: () => {
-          assert.pass("PageMod is attached when document is complete");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'end'."),
-        onInteractive: () => assert.fail("onInteractive should not be called with 'end'."),
-      });
-
-    }
-  });
-}
-
-// test timing for all 3 contentScriptWhen options (start, ready, end)
-// for PageMods created after a tab has completed loading (in tab.onLoad)
-exports.testContentScriptWhenOnTabLoad = function(assert, done) {
-  let srv = contentScriptWhenServer();
-  let url = srv.URL + '?OnTabLoad';
-  let count = 0;
-
-  tabs.open({
-    url: url,
-    onLoad: function(tab) {
-
-      handleReadyState(url, 'start', {
-        onComplete: () => {
-          assert.pass("PageMod is attached when document is complete");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'start'."),
-        onInteractive: () => assert.fail("onInteractive should not be called with 'start'."),
-      });
-
-      handleReadyState(url, 'ready', {
-        onComplete: () => {
-          assert.pass("PageMod is attached when document is complete");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
-        onInteractive: () => assert.fail("onInteractive should not be called with 'ready'."),
-      });
-
-      handleReadyState(url, 'end', {
-        onComplete: () => {
-          assert.pass("PageMod is attached when document is complete");
-          checkDone(++count, tab, srv, done);
-        },
-        onLoading: () => assert.fail("onLoading should not be called with 'end'."),
-        onInteractive: () => assert.fail("onInteractive should not be called with 'end'."),
-      });
-
-    }
-  });
-}
-
-function checkDone(count, tab, srv, done) {
-  if (count === 3)
-    tab.close(_ => srv.stop(done));
-}
-
-exports.testTabWorkerOnMessage = function(assert, done) {
-  let { browserWindows } = require("sdk/windows");
-  let tabs = require("sdk/tabs");
-  let { PageMod } = require("sdk/page-mod");
-
-  let url1 = "data:text/html;charset=utf-8,<title>tab1</title><h1>worker1.tab</h1>";
-  let url2 = "data:text/html;charset=utf-8,<title>tab2</title><h1>worker2.tab</h1>";
-  let worker1 = null;
-
-  let mod = PageMod({
-    include: "data:text/html*",
-    contentScriptWhen: "ready",
-    contentScript: "self.postMessage('#1');",
-    onAttach: function onAttach(worker) {
-      worker.on("message", function onMessage() {
-        this.tab.attach({
-          contentScriptWhen: "ready",
-          contentScript: "self.postMessage({ url: window.location.href, title: document.title });",
-          onMessage: function onMessage(data) {
-            assert.equal(this.tab.url, data.url, "location is correct");
-            assert.equal(this.tab.title, data.title, "title is correct");
-            if (this.tab.url === url1) {
-              worker1 = this;
-              tabs.open({ url: url2, inBackground: true });
-            }
-            else if (this.tab.url === url2) {
-              mod.destroy();
-              worker1.tab.close(function() {
-                worker1.destroy();
-                worker.tab.close(function() {
-                  worker.destroy();
-                  done();
-                });
-              });
-            }
-          }
-        });
-      });
-    }
-  });
-
-  tabs.open(url1);
-};
-
-exports.testAutomaticDestroy = function(assert, done) {
-  let loader = Loader(module);
-
-  let pageMod = loader.require("sdk/page-mod").PageMod({
-    include: "about:*",
-    contentScriptWhen: "start",
-    onAttach: function(w) {
-      assert.fail("Page-mod should have been detroyed during module unload");
-    }
-  });
-
-  // Unload the page-mod module so that our page mod is destroyed
-  loader.unload();
-
-  // Then create a second tab to ensure that it is correctly destroyed
-  let tabs = require("sdk/tabs");
-  tabs.open({
-    url: "about:",
-    onReady: function onReady(tab) {
-      assert.pass("check automatic destroy");
-      tab.close(done);
-    }
-  });
-};
-
-exports.testAttachToTabsOnly = function(assert, done) {
-  let { PageMod } = require('sdk/page-mod');
-  let openedTab = null; // Tab opened in openTabWithIframe()
-  let workerCount = 0;
-
-  let mod = PageMod({
-    include: 'data:text/html*',
-    contentScriptWhen: 'start',
-    contentScript: '',
-    onAttach: function onAttach(worker) {
-      if (worker.tab === openedTab) {
-        if (++workerCount == 3) {
-          assert.pass('Succesfully applied to tab documents and its iframe');
-          worker.destroy();
-          mod.destroy();
-          openedTab.close(done);
-        }
-      }
-      else {
-        assert.fail('page-mod attached to a non-tab document');
-      }
-    }
-  });
-
-  function openHiddenFrame() {
-    assert.pass('Open iframe in hidden window');
-    let hiddenFrames = require('sdk/frame/hidden-frame');
-    let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({
-      onReady: function () {
-        let element = this.element;
-        element.addEventListener('DOMContentLoaded', function() {
-          hiddenFrames.remove(hiddenFrame);
-
-          if (!xulApp.is("Fennec")) {
-            openToplevelWindow();
-          }
-          else {
-            openBrowserIframe();
-          }
-        }, {once: true});
-        element.setAttribute('src', 'data:text/html;charset=utf-8,foo');
-      }
-    }));
-  }
-
-  function openToplevelWindow() {
-    assert.pass('Open toplevel window');
-    let win = open('data:text/html;charset=utf-8,bar');
-    win.addEventListener('DOMContentLoaded', function() {
-      win.close();
-      openBrowserIframe();
-    }, {once: true});
-  }
-
-  function openBrowserIframe() {
-    assert.pass('Open iframe in browser window');
-    let window = require('sdk/deprecated/window-utils').activeBrowserWindow;
-    let document = window.document;
-    let iframe = document.createElement('iframe');
-    iframe.setAttribute('type', 'content');
-    iframe.setAttribute('src', 'data:text/html;charset=utf-8,foobar');
-    iframe.addEventListener('DOMContentLoaded', function() {
-      iframe.remove();
-      openTabWithIframes();
-    }, {once: true});
-    document.documentElement.appendChild(iframe);
-  }
-
-  // Only these three documents will be accepted by the page-mod
-  function openTabWithIframes() {
-    assert.pass('Open iframes in a tab');
-    let subContent = '<iframe src="data:text/html;charset=utf-8,sub frame" />'
-    let content = '<iframe src="data:text/html;charset=utf-8,' +
-                  encodeURIComponent(subContent) + '" />';
-    require('sdk/tabs').open({
-      url: 'data:text/html;charset=utf-8,' + encodeURIComponent(content),
-      onOpen: function onOpen(tab) {
-        openedTab = tab;
-      }
-    });
-  }
-
-  openHiddenFrame();
-};
-
-exports['test111 attachTo [top]'] = function(assert, done) {
-  let { PageMod } = require('sdk/page-mod');
-
-  let subContent = '<iframe src="data:text/html;charset=utf-8,sub frame" />'
-  let content = '<iframe src="data:text/html;charset=utf-8,' +
-                encodeURIComponent(subContent) + '" />';
-  let topDocumentURL = 'data:text/html;charset=utf-8,' + encodeURIComponent(content)
-
-  let workerCount = 0;
-
-  let mod = PageMod({
-    include: 'data:text/html*',
-    contentScriptWhen: 'start',
-    contentScript: 'self.postMessage(document.location.href);',
-    attachTo: ['top'],
-    onAttach: function onAttach(worker) {
-      if (++workerCount == 1) {
-        worker.on('message', function (href) {
-          assert.equal(href, topDocumentURL,
-                           "worker on top level document only");
-          let tab = worker.tab;
-          worker.destroy();
-          mod.destroy();
-          tab.close(done);
-        });
-      }
-      else {
-        assert.fail('page-mod attached to a non-top document');
-      }
-    }
-  });
-
-  require('sdk/tabs').open(topDocumentURL);
-};
-
-exports['test111 attachTo [frame]'] = function(assert, done) {
-  let { PageMod } = require('sdk/page-mod');
-
-  let subFrameURL = 'data:text/html;charset=utf-8,subframe';
-  let subContent = '<iframe src="' + subFrameURL + '" />';
-  let frameURL = 'data:text/html;charset=utf-8,' + encodeURIComponent(subContent);
-  let content = '<iframe src="' + frameURL + '" />';
-  let topDocumentURL = 'data:text/html;charset=utf-8,' + encodeURIComponent(content)
-
-  let workerCount = 0, messageCount = 0;
-
-  function onMessage(href) {
-    if (href == frameURL)
-      assert.pass("worker on first frame");
-    else if (href == subFrameURL)
-      assert.pass("worker on second frame");
-    else
-      assert.fail("worker on unexpected document: " + href);
-    this.destroy();
-    if (++messageCount == 2) {
-      mod.destroy();
-      require('sdk/tabs').activeTab.close(done);
-    }
-  }
-  let mod = PageMod({
-    include: 'data:text/html*',
-    contentScriptWhen: 'start',
-    contentScript: 'self.postMessage(document.location.href);',
-    attachTo: ['frame'],
-    onAttach: function onAttach(worker) {
-      if (++workerCount <= 2) {
-        worker.on('message', onMessage);
-      }
-      else {
-        assert.fail('page-mod attached to a non-frame document');
-      }
-    }
-  });
-
-  require('sdk/tabs').open(topDocumentURL);
-};
-
-exports.testContentScriptOptionsOption = function(assert, done) {
-  let callbackDone = null;
-  testPageMod(assert, done, "about:", [{
-      include: "about:*",
-      contentScript: "self.postMessage( [typeof self.options.d, self.options] );",
-      contentScriptWhen: "end",
-      contentScriptOptions: {a: true, b: [1,2,3], c: "string", d: function(){ return 'test'}},
-      onAttach: function(worker) {
-        worker.on('message', function(msg) {
-          assert.equal( msg[0], 'undefined', 'functions are stripped from contentScriptOptions' );
-          assert.equal( typeof msg[1], 'object', 'object as contentScriptOptions' );
-          assert.equal( msg[1].a, true, 'boolean in contentScriptOptions' );
-          assert.equal( msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions' );
-          assert.equal( msg[1].c, 'string', 'string in contentScriptOptions' );
-          callbackDone();
-        });
-      }
-    }],
-    function(win, done) {
-      callbackDone = done;
-    }
-  );
-};
-
-exports.testPageModCss = function(assert, done) {
-  let [pageMod] = testPageMod(assert, done,
-    'data:text/html;charset=utf-8,<div style="background: silver">css test</div>', [{
-      include: ["*", "data:*"],
-      contentStyle: "div { height: 100px; }",
-      contentStyleFile: [data.url("include-file.css"), "./border-style.css"]
-    }],
-    function(win, done) {
-      let div = win.document.querySelector("div");
-
-      assert.equal(div.clientHeight, 100,
-        "PageMod contentStyle worked");
-
-      assert.equal(div.offsetHeight, 120,
-        "PageMod contentStyleFile worked");
-
-      assert.equal(win.getComputedStyle(div).borderTopStyle, "dashed",
-        "PageMod contentStyleFile with relative path worked");
-
-      done();
-    }
-  );
-};
-
-exports.testPageModCssList = function*(assert) {
-  const URL = 'data:text/html;charset=utf-8,<div style="width:320px; max-width: 480px!important">css test</div>';
-  let modAttached = defer();
-
-  let pageMod = PageMod({
-    include: "data:*",
-    contentStyleFile: [
-      // Highlight evaluation order in this list
-      "data:text/css;charset=utf-8,div { border: 1px solid black; }",
-      "data:text/css;charset=utf-8,div { border: 10px solid black; }",
-      // Highlight evaluation order between contentStylesheet & contentStylesheetFile
-      "data:text/css;charset=utf-8s,div { height: 1000px; }",
-      // Highlight precedence between the author and user style sheet
-      "data:text/css;charset=utf-8,div { width: 200px; max-width: 640px!important}",
-    ],
-    contentStyle: [
-      "div { height: 10px; }",
-      "div { height: 100px; }"
-    ],
-    contentScript:  'new ' + function WorkerScope() {
-      self.port.on('get-results', () => {
-        let div = window.document.querySelector('div');
-        let style = window.getComputedStyle(div);
-
-        self.port.emit("results", {
-          clientHeight: div.clientHeight,
-          offsetHeight: div.offsetHeight,
-          width: style.width,
-          maxWidth: style.maxWidth
-        });
-      })
-    },
-    onAttach: modAttached.resolve
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: URL,
-      onReady: resolve
-    });
-  });
-  assert.pass("the tab was opened");
-
-  yield modAttached.promise;
-  assert.pass("the mod has been attached");
-
-  let results = yield new Promise(resolve => {
-    pageMod.port.on("results", resolve);
-    pageMod.port.emit("get-results");
-  })
-
-  assert.equal(
-   results.clientHeight,
-    100,
-    "PageMod contentStyle list works and is evaluated after contentStyleFile"
-  );
-
-  assert.equal(
-    results.offsetHeight,
-    120,
-    "PageMod contentStyleFile list works"
-  );
-
-  assert.equal(
-    results.width,
-    "320px",
-    "PageMod add-on author/page author style sheet precedence works"
-  );
-
-  assert.equal(
-    results.maxWidth,
-    "480px",
-    "PageMod add-on author/page author style sheet precedence with !important works"
-  );
-
-  pageMod.destroy();
-  assert.pass("the page mod was destroyed");
-};
-
-exports.testPageModCssDestroy = function(assert, done) {
-  let loader = Loader(module);
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,<div style='width:200px'>css test</div>",
-
-    onReady: function onReady(tab) {
-      let browserWindow = getMostRecentBrowserWindow();
-      let win = getTabContentWindow(getActiveTab(browserWindow));
-
-      let div = win.document.querySelector("div");
-      let style = win.getComputedStyle(div);
-
-      assert.equal(
-        style.width,
-        "200px",
-        "PageMod contentStyle is current before page-mod applies"
-      );
-
-      let pageMod = loader.require("sdk/page-mod").PageMod({
-        include: "data:*",
-        contentStyle: "div { width: 100px!important; }",
-        attachTo: ["top", "existing"],
-        onAttach: function(worker) {
-          assert.equal(
-            style.width,
-            "100px",
-            "PageMod contentStyle worked"
-          );
-
-          worker.once('detach', () => {
-            assert.equal(
-              style.width,
-              "200px",
-              "PageMod contentStyle is removed after page-mod destroy"
-            );
-
-            tab.close(done);
-          });
-
-          pageMod.destroy();
-        }
-      });
-    }
-  });
-};
-
-exports.testPageModCssAutomaticDestroy = function(assert, done) {
- let loader = Loader(module);
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,<div style='width:200px'>css test</div>",
-
-    onReady: function onReady(tab) {
-      let browserWindow = getMostRecentBrowserWindow();
-      let win = getTabContentWindow(getActiveTab(browserWindow));
-
-      let div = win.document.querySelector("div");
-      let style = win.getComputedStyle(div);
-
-      assert.equal(
-        style.width,
-        "200px",
-        "PageMod contentStyle is current before page-mod applies"
-      );
-
-      let pageMod = loader.require("sdk/page-mod").PageMod({
-        include: "data:*",
-        contentStyle: "div { width: 100px!important; }",
-        attachTo: ["top", "existing"],
-        onAttach: function(worker) {
-          assert.equal(
-            style.width,
-            "100px",
-            "PageMod contentStyle worked"
-          );
-
-          // Wait for a second page-mod to attach to be sure the unload
-          // message has made it to the child
-          let pageMod2 = PageMod({
-            include: "data:*",
-            contentStyle: "div { width: 100px!important; }",
-            attachTo: ["top", "existing"],
-            onAttach: function(worker) {
-              assert.equal(
-                style.width,
-                "200px",
-                "PageMod contentStyle is removed after page-mod destroy"
-              );
-
-              pageMod2.destroy();
-              tab.close(done);
-            }
-          });
-
-          loader.unload();
-        }
-      });
-    }
-  });
-};
-
-exports.testPageModContentScriptFile = function(assert, done) {
-  let loader = createLoader();
-  let { PageMod } = loader.require("sdk/page-mod");
-
-  tabs.open({
-    url: "about:license",
-    onReady: function(tab) {
-      let mod = PageMod({
-        include: "about:*",
-        attachTo: ["existing", "top"],
-        contentScriptFile: "./test-contentScriptFile.js",
-        onMessage: message => {
-          assert.equal(message, "msg from contentScriptFile",
-            "PageMod contentScriptFile with relative path worked");
-          tab.close(function() {
-            mod.destroy();
-            loader.unload();
-            done();
-          });
-        }
-      });
-    }
-  })
-};
-
-exports.testPageModTimeout = function(assert, done) {
-  let tab = null
-  let loader = Loader(module);
-  let { PageMod } = loader.require("sdk/page-mod");
-
-  let mod = PageMod({
-    include: "data:*",
-    contentScript: Isolate(function() {
-      var id = setTimeout(function() {
-        self.port.emit("fired", id)
-      }, 10)
-      self.port.emit("scheduled", id);
-    }),
-    onAttach: function(worker) {
-      worker.port.on("scheduled", function(id) {
-        assert.pass("timer was scheduled")
-        worker.port.on("fired", function(data) {
-          assert.equal(id, data, "timer was fired")
-          tab.close(function() {
-            worker.destroy()
-            loader.unload()
-            done()
-          });
-        })
-      })
-    }
-  });
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,timeout",
-    onReady: function($) { tab = $ }
-  })
-}
-
-
-exports.testPageModcancelTimeout = function(assert, done) {
-  let tab = null
-  let loader = Loader(module);
-  let { PageMod } = loader.require("sdk/page-mod");
-
-  let mod = PageMod({
-    include: "data:*",
-    contentScript: Isolate(function() {
-      var id1 = setTimeout(function() {
-        self.port.emit("failed")
-      }, 10)
-      var id2 = setTimeout(function() {
-        self.port.emit("timeout")
-      }, 100)
-      clearTimeout(id1)
-    }),
-    onAttach: function(worker) {
-      worker.port.on("failed", function() {
-        assert.fail("cancelled timeout fired")
-      })
-      worker.port.on("timeout", function(id) {
-        assert.pass("timer was scheduled")
-        tab.close(function() {
-          worker.destroy();
-          mod.destroy();
-          loader.unload();
-          done();
-        });
-      })
-    }
-  });
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,cancell timeout",
-    onReady: function($) { tab = $ }
-  })
-}
-
-exports.testExistingOnFrames = function(assert, done) {
-  let subFrameURL = 'data:text/html;charset=utf-8,testExistingOnFrames-sub-frame';
-  let subIFrame = '<iframe src="' + subFrameURL + '" />'
-  let iFrameURL = 'data:text/html;charset=utf-8,' + encodeURIComponent(subIFrame)
-  let iFrame = '<iframe src="' + iFrameURL + '" />';
-  let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(iFrame);
-
-  // we want all urls related to the test here, and not just the iframe urls
-  // because we need to fail if the test is applied to the top window url.
-  let urls = [url, iFrameURL, subFrameURL];
-
-  let counter = 0;
-  let tab = openTab(getMostRecentBrowserWindow(), url);
-
-  function wait4Iframes() {
-    let window = getTabContentWindow(tab);
-    if (window.document.readyState != "complete" ||
-        getFrames(window).length != 2) {
-      return;
-    }
-
-    let pagemodOnExisting = PageMod({
-      include: ["*", "data:*"],
-      attachTo: ["existing", "frame"],
-      contentScriptWhen: 'ready',
-      onAttach: function(worker) {
-        // need to ignore urls that are not part of the test, because other
-        // tests are not closing their tabs when they complete..
-        if (urls.indexOf(worker.url) == -1)
-          return;
-
-        assert.notEqual(url,
-                            worker.url,
-                            'worker should not be attached to the top window');
-
-        if (++counter < 2) {
-          // we can rely on this order in this case because we are sure that
-          // the frames being tested have completely loaded
-          assert.equal(iFrameURL, worker.url, '1st attach is for top frame');
-        }
-        else if (counter > 2) {
-          assert.fail('applied page mod too many times');
-        }
-        else {
-          assert.equal(subFrameURL, worker.url, '2nd attach is for sub frame');
-          // need timeout because onAttach is called before the constructor returns
-          setTimeout(function() {
-            pagemodOnExisting.destroy();
-            pagemodOffExisting.destroy();
-            closeTab(tab);
-            done();
-          }, 0);
-        }
-      }
-    });
-
-    let pagemodOffExisting = PageMod({
-      include: ["*", "data:*"],
-      attachTo: ["frame"],
-      contentScriptWhen: 'ready',
-      onAttach: function(mod) {
-        assert.fail('pagemodOffExisting page-mod should not have been attached');
-      }
-    });
-  }
-
-  getBrowserForTab(tab).addEventListener("load", wait4Iframes, true);
-};
-
-exports.testIFramePostMessage = function(assert, done) {
-  let count = 0;
-
-  tabs.open({
-    url: data.url("test-iframe.html"),
-    onReady: function(tab) {
-      var worker = tab.attach({
-        contentScriptFile: data.url('test-iframe.js'),
-        contentScript: 'var iframePath = \'' + data.url('test-iframe-postmessage.html') + '\'',
-        onMessage: function(msg) {
-          assert.equal(++count, 1);
-          assert.equal(msg.first, 'a string');
-          assert.ok(msg.second[1], "array");
-          assert.equal(typeof msg.third, 'object');
-
-          worker.destroy();
-          tab.close(done);
-        }
-      });
-    }
-  });
-};
-
-exports.testEvents = function*(assert) {
-  let modAttached = defer();
-  let content = "<script>\n new " + function DocumentScope() {
-    window.addEventListener("ContentScriptEvent", function () {
-      window.document.body.setAttribute("receivedEvent", "ok");
-    });
-  } + "\n</script>";
-  let url = "data:text/html;charset=utf-8," + encodeURIComponent(content);
-
-  let mod = PageMod({
-    include: "data:*",
-    contentScript: 'new ' + function WorkerScope() {
-      let evt = document.createEvent("Event");
-      evt.initEvent("ContentScriptEvent", true, true);
-      document.body.dispatchEvent(evt);
-
-      self.port.on("get-result", () => {
-        self.port.emit("result", {
-          receivedEvent: window.document.body.getAttribute("receivedEvent")
-        });
-      });
-    },
-    onAttach: modAttached.resolve
-  });
-
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: url,
-      onReady: resolve
-    });
-  });
-  assert.pass("the tab is ready");
-
-  yield modAttached.promise;
-  assert.pass("the mod was attached")
-
-  let result = yield new Promise(resolve => {
-    mod.port.once("result", resolve);
-    mod.port.emit("get-result");
-  });
-
-  assert.equal(result.receivedEvent, "ok",
-               "Content script sent an event and document received it");
-};
-
-exports["test page-mod on private tab"] = function (assert, done) {
-  let fail = assert.fail.bind(assert);
-
-  let privateUri = "data:text/html;charset=utf-8," +
-                   "<iframe src=\"data:text/html;charset=utf-8,frame\" />";
-  let nonPrivateUri = "data:text/html;charset=utf-8,non-private";
-
-  let pageMod = new PageMod({
-    include: "data:*",
-    onAttach: function(worker) {
-      if (isTabPBSupported || isWindowPBSupported) {
-        // When PB isn't supported, the page-mod will apply to all document
-        // as all of them will be non-private
-        assert.equal(worker.tab.url,
-                         nonPrivateUri,
-                         "page-mod should only attach to the non-private tab");
-      }
-
-      assert.ok(!isPrivate(worker),
-                  "The worker is really non-private");
-      assert.ok(!isPrivate(worker.tab),
-                  "The document is really non-private");
-      pageMod.destroy();
-
-      page1.close().
-        then(page2.close).
-        then(done, fail);
-    }
-  });
-
-  let page1, page2;
-  page1 = openWebpage(privateUri, true);
-  page1.ready.then(function() {
-    page2 = openWebpage(nonPrivateUri, false);
-  }, fail);
-}
-
-// Bug 699450: Calling worker.tab.close() should not lead to exception
-exports.testWorkerTabClose = function(assert, done) {
-  let callbackDone;
-  testPageMod(assert, done, "about:", [{
-      include: "about:",
-      contentScript: '',
-      onAttach: function(worker) {
-        assert.pass("The page-mod was attached");
-
-        worker.tab.close(function () {
-          // On Fennec, tab is completely destroyed right after close event is
-          // dispatch, so we need to wait for the next event loop cycle to
-          // check for tab nulliness.
-          setTimeout(function () {
-            assert.ok(!worker.tab,
-                        "worker.tab should be null right after tab.close()");
-            callbackDone();
-          }, 0);
-        });
-      }
-    }],
-    function(win, done) {
-      callbackDone = done;
-    }
-  );
-};
-
-exports.testDetachOnDestroy = function(assert, done) {
-  let tab;
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-  const loader = Loader(module);
-  const { PageMod } = loader.require('sdk/page-mod');
-
-  let mod1 = PageMod({
-    include: TEST_URL,
-    contentScript: Isolate(function() {
-      self.port.on('detach', function(reason) {
-        window.document.body.innerHTML += '!' + reason;
-      });
-    }),
-    onAttach: worker => {
-      assert.pass('attach[1] happened');
-
-      worker.on('detach', _ => setTimeout(_ => {
-        assert.pass('detach happened');
-
-        let mod2 = PageMod({
-          attachTo: [ 'existing', 'top' ],
-          include: TEST_URL,
-          contentScript: Isolate(function() {
-            self.port.on('test', _ => {
-              self.port.emit('result', { result: window.document.body.innerHTML});
-            });
-          }),
-          onAttach: worker => {
-            assert.pass('attach[2] happened');
-            worker.port.once('result', ({ result }) => {
-              assert.equal(result, 'detach!', 'the body.innerHTML is as expected');
-              mod1.destroy();
-              mod2.destroy();
-              loader.unload();
-              tab.close(done);
-            });
-            worker.port.emit('test');
-          }
-        });
-      }));
-
-      worker.destroy();
-    }
-  });
-
-  tabs.open({
-    url: TEST_URL,
-    onOpen: t => tab = t
-  })
-}
-
-exports.testDetachOnUnload = function(assert, done) {
-  let tab;
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-  const loader = Loader(module);
-  const { PageMod } = loader.require('sdk/page-mod');
-
-  let mod1 = PageMod({
-    include: TEST_URL,
-    contentScript: Isolate(function() {
-      self.port.on('detach', function(reason) {
-        window.document.body.innerHTML += '!' + reason;
-      });
-    }),
-    onAttach: worker => {
-      assert.pass('attach[1] happened');
-
-      worker.on('detach', _ => setTimeout(_ => {
-        assert.pass('detach happened');
-
-        let mod2 = require('sdk/page-mod').PageMod({
-          attachTo: [ 'existing', 'top' ],
-          include: TEST_URL,
-          contentScript: Isolate(function() {
-            self.port.on('test', _ => {
-              self.port.emit('result', { result: window.document.body.innerHTML});
-            });
-          }),
-          onAttach: worker => {
-            assert.pass('attach[2] happened');
-            worker.port.once('result', ({ result }) => {
-              assert.equal(result, 'detach!shutdown', 'the body.innerHTML is as expected');
-              mod2.destroy();
-              tab.close(done);
-            });
-            worker.port.emit('test');
-          }
-        });
-      }));
-
-      loader.unload('shutdown');
-    }
-  });
-
-  tabs.open({
-    url: TEST_URL,
-    onOpen: t => tab = t
-  })
-}
-
-exports.testConsole = function(assert, done) {
-  let innerID;
-  const TEST_URL = 'data:text/html;charset=utf-8,console';
-
-  let seenMessage = false;
-
-  system.on('console-api-log-event', onMessage);
-
-  function onMessage({ subject: { wrappedJSObject: msg }}) {
-    if (msg.arguments[0] !== "Hello from the page mod")
-      return;
-    seenMessage = true;
-    innerID = msg.innerID;
-  }
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: "ready",
-    contentScript: Isolate(function() {
-      console.log("Hello from the page mod");
-      self.port.emit("done");
-    }),
-    onAttach: function(worker) {
-      worker.port.on("done", function() {
-        let window = getTabContentWindow(tab);
-        let id = getInnerId(window);
-        assert.ok(seenMessage, "Should have seen the console message");
-        assert.equal(innerID, id, "Should have seen the right inner ID");
-
-        system.off('console-api-log-event', onMessage);
-        mod.destroy();
-        closeTab(tab);
-        done();
-      });
-    },
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-exports.testSyntaxErrorInContentScript = function *(assert) {
-  const url = "data:text/html;charset=utf-8,testSyntaxErrorInContentScript";
-  const loader = createLoader();
-  const { PageMod } = loader.require("sdk/page-mod");
-  let attached = defer();
-  let errored = defer();
-
-  let mod = PageMod({
-    include: url,
-    contentScript: 'console.log(23',
-    onAttach: attached.resolve,
-    onError: errored.resolve
-  });
-  openNewTab(url);
-
-  yield attached.promise;
-  let hitError = yield errored.promise;
-
-  assert.notStrictEqual(hitError, null, "The syntax error was reported.");
-  assert.equal(hitError.name, "SyntaxError", "The error thrown should be a SyntaxError");
-
-  loader.unload();
-  yield cleanUI();
-};
-
-exports.testPageShowWhenStart = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-  let sawWorkerPageShow = false;
-  let sawInjected = false;
-  let sawContentScriptPageShow = false;
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'start',
-    contentScript: Isolate(function() {
-      self.port.emit("injected");
-      self.on("pageshow", () => {
-        self.port.emit("pageshow");
-      });
-    }),
-    onAttach: worker => {
-      worker.port.on("injected", () => {
-        sawInjected = true;
-      });
-
-      worker.port.on("pageshow", () => {
-        sawContentScriptPageShow = true;
-        closeTab(tab);
-      });
-
-      worker.on("pageshow", () => {
-        sawWorkerPageShow = true;
-      });
-
-      worker.on("detach", () => {
-        assert.ok(sawWorkerPageShow, "Worker emitted pageshow");
-        assert.ok(sawInjected, "Content script ran");
-        assert.ok(sawContentScriptPageShow, "Content script saw pageshow");
-        mod.destroy();
-        done();
-      });
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-};
-
-exports.testPageShowWhenReady = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-  let sawWorkerPageShow = false;
-  let sawInjected = false;
-  let sawContentScriptPageShow = false;
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'ready',
-    contentScript: Isolate(function() {
-      self.port.emit("injected");
-      self.on("pageshow", () => {
-        self.port.emit("pageshow");
-      });
-    }),
-    onAttach: worker => {
-      worker.port.on("injected", () => {
-        sawInjected = true;
-      });
-
-      worker.port.on("pageshow", () => {
-        sawContentScriptPageShow = true;
-        closeTab(tab);
-      });
-
-      worker.on("pageshow", () => {
-        sawWorkerPageShow = true;
-      });
-
-      worker.on("detach", () => {
-        assert.ok(sawWorkerPageShow, "Worker emitted pageshow");
-        assert.ok(sawInjected, "Content script ran");
-        assert.ok(sawContentScriptPageShow, "Content script saw pageshow");
-        mod.destroy();
-        done();
-      });
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-};
-
-exports.testPageShowWhenEnd = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-  let sawWorkerPageShow = false;
-  let sawInjected = false;
-  let sawContentScriptPageShow = false;
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'end',
-    contentScript: Isolate(function() {
-      self.port.emit("injected");
-      self.on("pageshow", () => {
-        self.port.emit("pageshow");
-      });
-    }),
-    onAttach: worker => {
-      worker.port.on("injected", () => {
-        sawInjected = true;
-      });
-
-      worker.port.on("pageshow", () => {
-        sawContentScriptPageShow = true;
-        closeTab(tab);
-      });
-
-      worker.on("pageshow", () => {
-        sawWorkerPageShow = true;
-      });
-
-      worker.on("detach", () => {
-        assert.ok(sawWorkerPageShow, "Worker emitted pageshow");
-        assert.ok(sawInjected, "Content script ran");
-        assert.ok(sawContentScriptPageShow, "Content script saw pageshow");
-        mod.destroy();
-        done();
-      });
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-};
-
-// Tests that after destroy existing workers have been destroyed
-exports.testDestroyKillsChild = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-
-  let mod1 = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'end',
-    contentScript: Isolate(function() {
-      self.port.on("ping", detail => {
-        let event = document.createEvent("CustomEvent");
-        event.initCustomEvent("Test:Ping", true, true, detail);
-        document.dispatchEvent(event);
-        self.port.emit("pingsent");
-      });
-
-      let listener = function(event) {
-        self.port.emit("pong", event.detail);
-      };
-
-      self.port.on("detach", () => {
-        window.removeEventListener("Test:Pong", listener);
-      });
-      window.addEventListener("Test:Pong", listener);
-    }),
-    onAttach: worker1 => {
-      let mod2 = PageMod({
-        include: TEST_URL,
-        attachTo: ["top", "existing"],
-        contentScriptWhen: 'end',
-        contentScript: Isolate(function() {
-          let listener = function(event) {
-            let newEvent = document.createEvent("CustomEvent");
-            newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-            document.dispatchEvent(newEvent);
-          };
-          self.port.on("detach", () => {
-            window.removeEventListener("Test:Ping", listener);
-          })
-          window.addEventListener("Test:Ping", listener);
-          self.postMessage();
-        }),
-        onAttach: worker2 => {
-          worker1.port.emit("ping", "test1");
-          worker1.port.once("pong", detail => {
-            assert.equal(detail, "test1", "Saw the right message");
-            worker1.port.once("pingsent", () => {
-              assert.pass("The message was sent");
-
-              mod2.destroy();
-
-              worker1.port.emit("ping", "test2");
-              worker1.port.once("pong", detail => {
-                assert.fail("worker2 shouldn't have responded");
-              })
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-                mod1.destroy();
-                closeTab(tab);
-                done();
-              });
-            });
-          })
-        }
-      });
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-// Tests that after destroy child page-mod won't attach
-exports.testDestroyWontAttach = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-
-  let badMod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'start',
-    contentScript: Isolate(function() {
-      unsafeWindow.testProperty = "attached";
-    })
-  });
-  badMod.destroy();
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'end',
-    contentScript: Isolate(function() {
-      self.postMessage(unsafeWindow.testProperty);
-    }),
-    onMessage: property => {
-      assert.equal(property, undefined, "Shouldn't have seen the test property set.");
-      mod.destroy();
-      closeTab(tab);
-      done();
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-// Tests that after unload existing workers have been destroyed
-exports.testUnloadKillsChild = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-
-  let mod1 = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'end',
-    contentScript: Isolate(function() {
-      self.port.on("ping", detail => {
-        let event = document.createEvent("CustomEvent");
-        event.initCustomEvent("Test:Ping", true, true, detail);
-        document.dispatchEvent(event);
-        self.port.emit("pingsent");
-      });
-
-      let listener = function(event) {
-        self.port.emit("pong", event.detail);
-      };
-
-      self.port.on("detach", () => {
-        window.removeEventListener("Test:Pong", listener);
-      });
-      window.addEventListener("Test:Pong", listener);
-    }),
-    onAttach: worker1 => {
-      let loader = Loader(module);
-      let mod2 = loader.require('sdk/page-mod').PageMod({
-        include: TEST_URL,
-        attachTo: ["top", "existing"],
-        contentScriptWhen: 'end',
-        contentScript: Isolate(function() {
-          let listener = function(event) {
-            let newEvent = document.createEvent("CustomEvent");
-            newEvent.initCustomEvent("Test:Pong", true, true, event.detail);
-            document.dispatchEvent(newEvent);
-          };
-          self.port.on("detach", () => {
-            window.removeEventListener("Test:Ping", listener);
-          })
-          window.addEventListener("Test:Ping", listener);
-          self.postMessage();
-        }),
-        onAttach: worker2 => {
-          worker1.port.emit("ping", "test1");
-          worker1.port.once("pong", detail => {
-            assert.equal(detail, "test1", "Saw the right message");
-            worker1.port.once("pingsent", () => {
-              assert.pass("The message was sent");
-
-              loader.unload();
-
-              worker1.port.emit("ping", "test2");
-              worker1.port.once("pong", detail => {
-                assert.fail("worker2 shouldn't have responded");
-              })
-              worker1.port.once("pingsent", () => {
-                assert.pass("The message was sent");
-                mod1.destroy();
-                closeTab(tab);
-                done();
-              });
-            });
-          })
-        }
-      });
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-// Tests that after unload child page-mod won't attach
-exports.testUnloadWontAttach = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,detach';
-
-  let loader = Loader(module);
-  let badMod = loader.require('sdk/page-mod').PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'start',
-    contentScript: Isolate(function() {
-      unsafeWindow.testProperty = "attached";
-    })
-  });
-  loader.unload();
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScriptWhen: 'end',
-    contentScript: Isolate(function() {
-      self.postMessage(unsafeWindow.testProperty);
-    }),
-    onMessage: property => {
-      assert.equal(property, undefined, "Shouldn't have seen the test property set.");
-      mod.destroy();
-      closeTab(tab);
-      done();
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-// Tests that the SDK console isn't injected into documents loaded in tabs
-exports.testDontInjectConsole = function(assert, done) {
-  const TEST_URL = 'data:text/html;charset=utf-8,consoleinject';
-
-  let loader = Loader(module);
-
-  let mod = PageMod({
-    include: TEST_URL,
-    contentScript: Isolate(function() {
-      // This relies on the fact that the SDK console doesn't have assert defined
-      self.postMessage((typeof unsafeWindow.console.assert) == "function");
-    }),
-    onMessage: isNativeConsole => {
-      assert.ok(isNativeConsole, "Shouldn't have injected the SDK console.");
-      mod.destroy();
-      closeTab(tab);
-      done();
-    }
-  });
-
-  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
-}
-
-after(exports, function*(name, assert) {
-  assert.pass("cleaning ui.");
-  yield cleanUI();
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-page-worker.js
+++ /dev/null
@@ -1,558 +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 { Loader } = require('sdk/test/loader');
-const { Page } = require("sdk/page-worker");
-const { URL } = require("sdk/url");
-const fixtures = require("./fixtures");
-const testURI = fixtures.url("test.html");
-const { getActiveView } = require("sdk/view/core");
-const { getDocShell } = require('sdk/frame/utils');
-
-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 Isolate = fn => "(" + fn + ")()";
-
-exports.testSimplePageCreation = function(assert, done) {
-  let page = new Page({
-    contentScript: "self.postMessage(window.location.href)",
-    contentScriptWhen: "end",
-    onMessage: function (message) {
-      assert.equal(message, "about:blank",
-                       "Page Worker should start with a blank page by default");
-      assert.equal(this, page, "The 'this' object is the page itself.");
-      done();
-    }
-  });
-}
-
-/*
- * Tests that we can't be tricked by document overloads as we have access
- * to wrapped nodes
- */
-exports.testWrappedDOM = function(assert, done) {
-  let page = Page({
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.getElementById=3;window.scrollTo=3;</script>",
-    contentScript: 'new ' + function() {
-      function send() {
-        self.postMessage([typeof(document.getElementById), typeof(window.scrollTo)]);
-      }
-      if (document.readyState !== 'complete')
-        window.addEventListener('load', send, true)
-      else
-        send();
-    },
-    onMessage: function (message) {
-      assert.equal(message[0],
-                       "function",
-                       "getElementById from content script is the native one");
-
-      assert.equal(message[1],
-                       "function",
-                       "scrollTo from content script is the native one");
-
-      done();
-    }
-  });
-}
-
-/*
-// We do not offer unwrapped access to DOM since bug 601295 landed
-// See 660780 to track progress of unwrap feature
-exports.testUnwrappedDOM = function(assert, done) {
-  let page = Page({
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.getElementById=3;window.scrollTo=3;</script>",
-    contentScript: "window.addEventListener('load', function () {" +
-                   "return self.postMessage([typeof(unsafeWindow.document.getElementById), " +
-                   "typeof(unsafeWindow.scrollTo)]); }, true)",
-    onMessage: function (message) {
-      assert.equal(message[0],
-                       "number",
-                       "document inside page is free to be changed");
-
-      assert.equal(message[1],
-                       "number",
-                       "window inside page is free to be changed");
-
-      done();
-    }
-  });
-}
-*/
-
-exports.testPageProperties = function(assert) {
-  let page = new Page();
-
-  for (let prop of ['contentURL', 'allow', 'contentScriptFile',
-                         'contentScript', 'contentScriptWhen', 'on',
-                         'postMessage', 'removeListener']) {
-    assert.ok(prop in page, prop + " property is defined on page.");
-  }
-
-  assert.ok(() => page.postMessage("foo") || true,
-              "postMessage doesn't throw exception on page.");
-}
-
-exports.testConstructorAndDestructor = function(assert, done) {
-  let loader = Loader(module);
-  let { Page } = loader.require("sdk/page-worker");
-  let global = loader.sandbox("sdk/page-worker");
-
-  let pagesReady = 0;
-
-  let page1 = Page({
-    contentScript:      "self.postMessage('')",
-    contentScriptWhen:  "end",
-    onMessage:          pageReady
-  });
-  let page2 = Page({
-    contentScript:      "self.postMessage('')",
-    contentScriptWhen:  "end",
-    onMessage:          pageReady
-  });
-
-  assert.notEqual(page1, page2,
-                      "Page 1 and page 2 should be different objects.");
-
-  function pageReady() {
-    if (++pagesReady == 2) {
-      page1.destroy();
-      page2.destroy();
-
-      assert.ok(isDestroyed(page1), "page1 correctly unloaded.");
-      assert.ok(isDestroyed(page2), "page2 correctly unloaded.");
-
-      loader.unload();
-      done();
-    }
-  }
-}
-
-exports.testAutoDestructor = function(assert, done) {
-  let loader = Loader(module);
-  let { Page } = loader.require("sdk/page-worker");
-
-  let page = Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: function() {
-      loader.unload();
-      assert.ok(isDestroyed(page), "Page correctly unloaded.");
-      done();
-    }
-  });
-}
-
-exports.testValidateOptions = function(assert) {
-  assert.throws(
-    () => Page({ contentURL: 'home' }),
-    /The `contentURL` option must be a valid URL\./,
-    "Validation correctly denied a non-URL contentURL"
-  );
-
-  assert.throws(
-    () => Page({ onMessage: "This is not a function."}),
-    /The option "onMessage" must be one of the following types: function/,
-    "Validation correctly denied a non-function onMessage."
-  );
-
-  assert.pass("Options validation is working.");
-}
-
-exports.testContentAndAllowGettersAndSetters = function(assert, done) {
-  let content = "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=3;</script>";
-
-  // Load up the page with testURI initially for the resource:// principal,
-  // then load the actual data:* content, as data:* URIs no longer
-  // have localStorage
-  let page = Page({
-    contentURL: testURI,
-    contentScript: "if (window.location.href==='"+testURI+"')" +
-      "  self.postMessage('reload');" +
-      "else " +
-      "  self.postMessage(window.localStorage.allowScript)",
-    contentScriptWhen: "end",
-    onMessage: step0
-  });
-
-  function step0(message) {
-    if (message === 'reload')
-      return page.contentURL = content;
-    assert.equal(message, "3",
-                     "Correct value expected for allowScript - 3");
-    assert.equal(page.contentURL, content,
-                     "Correct content expected");
-    page.removeListener('message', step0);
-    page.on('message', step1);
-    page.allow = { script: false };
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript='f'</script>";
-  }
-
-  function step1(message) {
-    assert.equal(message, "3",
-                     "Correct value expected for allowScript - 3");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step1);
-    page.on('message', step2);
-    page.allow = { script: true };
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript='g'</script>";
-  }
-
-  function step2(message) {
-    assert.equal(message, "g",
-                     "Correct value expected for allowScript - g");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step2);
-    page.on('message', step3);
-    page.allow.script = false;
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=3</script>";
-  }
-
-  function step3(message) {
-    assert.equal(message, "g",
-                     "Correct value expected for allowScript - g");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    page.removeListener('message', step3);
-    page.on('message', step4);
-    page.allow.script = true;
-    page.contentURL = content =
-      "data:text/html;charset=utf-8,<script>window.localStorage.allowScript=4</script>";
-  }
-
-  function step4(message) {
-    assert.equal(message, "4",
-                     "Correct value expected for allowScript - 4");
-    assert.equal(page.contentURL, content, "Correct content expected");
-    done();
-  }
-
-}
-
-exports.testOnMessageCallback = function(assert, done) {
-  Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: function() {
-      assert.pass("onMessage callback called");
-      done();
-    }
-  });
-}
-
-exports.testMultipleOnMessageCallbacks = function(assert, done) {
-  let count = 0;
-  let page = Page({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    onMessage: () => count += 1
-  });
-  page.on('message', () => count += 2);
-  page.on('message', () => count *= 3);
-  page.on('message', () =>
-    assert.equal(count, 9, "All callbacks were called, in order."));
-  page.on('message', done);
-};
-
-exports.testLoadContentPage = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      // The message is an array whose first item is the test method to call
-      // and the rest of whose items are arguments to pass it.
-      let msg = message.shift();
-      if (msg == "done")
-        return done();
-      assert[msg].apply(assert, message);
-    },
-    contentURL: fixtures.url("addon-sdk/data/test-page-worker.html"),
-    contentScriptFile: fixtures.url("addon-sdk/data/test-page-worker.js"),
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testLoadContentPageRelativePath = function(assert, done) {
-  const self = require("sdk/self");
-  const { merge } = require("sdk/util/object");
-
-  const options = merge({}, require('@loader/options'),
-      { id: "testloader", prefixURI: require('./fixtures').url() });
-
-  let loader = Loader(module, null, options);
-
-  let page = loader.require("sdk/page-worker").Page({
-    onMessage: function(message) {
-      // The message is an array whose first item is the test method to call
-      // and the rest of whose items are arguments to pass it.
-      let msg = message.shift();
-      if (msg == "done")
-        return done();
-      assert[msg].apply(assert, message);
-    },
-    contentURL: "./test-page-worker.html",
-    contentScriptFile: "./test-page-worker.js",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testAllowScriptDefault = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      assert.ok(message, "Script is allowed to run by default.");
-      done();
-    },
-    contentURL: "data:text/html;charset=utf-8,<script>document.documentElement.setAttribute('foo', 3);</script>",
-    contentScript: "self.postMessage(document.documentElement.getAttribute('foo'))",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testAllowScript = function(assert, done) {
-  let page = Page({
-    onMessage: function(message) {
-      assert.ok(message, "Script runs when allowed to do so.");
-      page.destroy();
-      done();
-    },
-    allow: { script: true },
-    contentURL: "data:text/html;charset=utf-8,<script>document.documentElement.setAttribute('foo', 3);</script>",
-    contentScript: "self.postMessage(document.documentElement.hasAttribute('foo') && " +
-                   "                 document.documentElement.getAttribute('foo') == 3)",
-    contentScriptWhen: "ready"
-  });
-}
-
-exports.testPingPong = function(assert, done) {
-  let page = Page({
-    contentURL: 'data:text/html;charset=utf-8,ping-pong',
-    contentScript: 'self.on("message", message => self.postMessage("pong"));'
-      + 'self.postMessage("ready");',
-    onMessage: function(message) {
-      if ('ready' == message) {
-        page.postMessage('ping');
-      }
-      else {
-        assert.ok(message, 'pong', 'Callback from contentScript');
-        done();
-      }
-    }
-  });
-};
-
-exports.testRedirect = function (assert, done) {
-  let page = Page({
-    contentURL: 'data:text/html;charset=utf-8,first-page',
-    contentScriptWhen: "end",
-    contentScript: '' +
-      'if (/first-page/.test(document.location.href)) ' +
-      '  document.location.href = "data:text/html;charset=utf-8,redirect";' +
-      'else ' +
-      '  self.port.emit("redirect", document.location.href);'
-  });
-
-  page.port.on('redirect', function (url) {
-    assert.equal(url, 'data:text/html;charset=utf-8,redirect', 'Reinjects contentScript on reload');
-    done();
-  });
-};
-
-exports.testRedirectIncludeArrays = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '  self.port.on("redirect", function (url) {' +
-      '   document.location.href = url;' +
-      '  })' +
-      '})();',
-    include: ['about:blank', 'data:*']
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.port.emit('redirect', 'about:blank');
-    } else if (url === 'about:blank') {
-      page.port.emit('redirect', 'about:mozilla');
-      assert.ok('`include` property handles arrays');
-      assert.equal(url, 'about:blank', 'Redirects work with accepted domains');
-      done();
-    } else if (url === 'about:mozilla') {
-      assert.fail('Should not redirect to restricted domain');
-    }
-  });
-};
-
-exports.testRedirectFromWorker = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let secondURL = 'data:text/html;charset=utf-8,second-page';
-  let thirdURL = 'data:text/html;charset=utf-8,third-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '  self.port.on("redirect", function (url) {' +
-      '   document.location.href = url;' +
-      '  })' +
-      '})();',
-    include: 'data:*'
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.port.emit('redirect', secondURL);
-    } else if (url === secondURL) {
-      page.port.emit('redirect', thirdURL);
-    } else if (url === thirdURL) {
-      page.port.emit('redirect', 'about:mozilla');
-      assert.equal(url, thirdURL, 'Redirects work with accepted domains on include strings');
-      done();
-    } else {
-      assert.fail('Should not redirect to unauthorized domains');
-    }
-  });
-};
-
-exports.testRedirectWithContentURL = function (assert, done) {
-  let firstURL = 'data:text/html;charset=utf-8,first-page';
-  let secondURL = 'data:text/html;charset=utf-8,second-page';
-  let thirdURL = 'data:text/html;charset=utf-8,third-page';
-  let page = Page({
-    contentURL: firstURL,
-    contentScript: '(function () {' +
-      'self.port.emit("load", document.location.href);' +
-      '})();',
-    include: 'data:*'
-  });
-
-  page.port.on('load', function (url) {
-    if (url === firstURL) {
-      page.contentURL = secondURL;
-    } else if (url === secondURL) {
-      page.contentURL = thirdURL;
-    } else if (url === thirdURL) {
-      page.contentURL = 'about:mozilla';
-      assert.equal(url, thirdURL, 'Redirects work with accepted domains on include strings');
-      done();
-    } else {
-      assert.fail('Should not redirect to unauthorized domains');
-    }
-  });
-};
-
-
-exports.testMultipleDestroys = function(assert) {
-  let page = Page();
-  page.destroy();
-  page.destroy();
-  assert.pass("Multiple destroys should not cause an error");
-};
-
-exports.testContentScriptOptionsOption = function(assert, done) {
-  let page = new Page({
-    contentScript: "self.postMessage( [typeof self.options.d, self.options] );",
-    contentScriptWhen: "end",
-    contentScriptOptions: {a: true, b: [1,2,3], c: "string", d: function(){ return 'test'}},
-    onMessage: function(msg) {
-      assert.equal(msg[0], 'undefined', 'functions are stripped from contentScriptOptions');
-      assert.equal(typeof msg[1], 'object', 'object as contentScriptOptions');
-      assert.equal(msg[1].a, true, 'boolean in contentScriptOptions');
-      assert.equal(msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions');
-      assert.equal(msg[1].c, 'string', 'string in contentScriptOptions');
-      done();
-    }
-  });
-};
-
-exports.testMessageQueue = function (assert, done) {
-  let page = new Page({
-    contentScript: 'self.on("message", function (m) {' +
-      'self.postMessage(m);' +
-      '});',
-    contentURL: 'data:text/html;charset=utf-8,',
-  });
-  page.postMessage('ping');
-  page.on('message', function (m) {
-    assert.equal(m, 'ping', 'postMessage should queue messages');
-    done();
-  });
-};
-
-exports.testWindowStopDontBreak = function (assert, done) {
-  const { Ci, Cc } = require('chrome');
-  const consoleService = Cc['@mozilla.org/consoleservice;1'].
-                            getService(Ci.nsIConsoleService);
-  const listener = {
-    observe: ({message}) => {
-      if (message.includes('contentWorker is null'))
-        assert.fail('contentWorker is null');
-    }
-  };
-  consoleService.registerListener(listener)
-
-  let page = new Page({
-    contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
-    contentScriptWhen: 'ready',
-    contentScript: Isolate(() => {
-      window.stop();
-      self.port.on('ping', () => self.port.emit('pong'));
-    })
-  });
-
-  page.port.on('pong', () => {
-    assert.pass('page-worker works after window.stop');
-    page.destroy();
-    consoleService.unregisterListener(listener);
-    done();
-  });
-
-  page.port.emit("ping");
-};
-
-/**
- * bug 1138545 - the docs claim you can pass in a bare regexp.
- */
-exports.testRegexArgument = function (assert, done) {
-  let url = 'data:text/html;charset=utf-8,testWindowStopDontBreak';
-
-  let page = new Page({
-    contentURL: url,
-    contentScriptWhen: 'ready',
-    contentScript: Isolate(() => {
-     self.port.emit("pong", document.location.href);
-    }),
-    include: /^data\:text\/html;.*/
-  });
-
-  assert.pass("We can pass in a RegExp into page-worker's include option.");
-
-  page.port.on("pong", (href) => {
-    assert.equal(href, url, "we get back the same url from the content script.");
-    page.destroy();
-    done();
-  });
-};
-
-function isDestroyed(page) {
-  try {
-    page.postMessage("foo");
-  }
-  catch (err) {
-    if (err.message == ERR_DESTROYED) {
-      return true;
-    }
-    else {
-      throw err;
-    }
-  }
-  return false;
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-panel.js
+++ /dev/null
@@ -1,1447 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require("chrome");
-const { Loader } = require('sdk/test/loader');
-const { LoaderWithHookedConsole } = require("sdk/test/loader");
-const { setTimeout } = require("sdk/timers");
-const self = require('sdk/self');
-const { open, close, focus, ready } = require('sdk/window/helpers');
-const { isPrivate } = require('sdk/private-browsing');
-const { isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { defer, all } = require('sdk/core/promise');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { URL } = require('sdk/url');
-const { wait } = require('./event/helpers');
-const packaging = require('@loader/options');
-const { cleanUI, after, isTravisCI } = require("sdk/test/utils");
-const { platform } = require('sdk/system');
-
-const fixtures = require('./fixtures')
-
-const SVG_URL = fixtures.url('mofo_logo.SVG');
-
-const Isolate = fn => '(' + fn + ')()';
-
-function ignorePassingDOMNodeWarning(type, message) {
-  if (type !== 'warn' || !message.startsWith('Passing a DOM node'))
-    console[type](message);
-}
-
-function makeEmptyPrivateBrowserWindow(options) {
-  options = options || {};
-  return open('chrome://browser/content/browser.xul', {
-    features: {
-      chrome: true,
-      toolbar: true,
-      private: true
-    }
-  });
-}
-
-exports["test Panel"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  const { getActiveView } = require("sdk/view/core");
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    contentScript: "self.postMessage(1); self.on('message', () => self.postMessage(2));",
-    onMessage: function (message) {
-      assert.equal(this, panel, "The 'this' object is the panel.");
-      switch(message) {
-        case 1:
-          assert.pass("The panel was loaded.");
-          panel.postMessage('');
-          break;
-        case 2:
-          assert.pass("The panel posted a message and received a response.");
-          panel.destroy();
-          done();
-          break;
-      }
-    }
-  });
-  getActiveView(panel);
-};
-
-exports["test Panel Emit"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  const { getActiveView } = require("sdk/view/core");
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    contentScript: "self.port.emit('loaded');" +
-                   "self.port.on('addon-to-content', " +
-                   "             () => self.port.emit('received'));",
-  });
-  panel.port.on("loaded", function () {
-    assert.pass("The panel was loaded and sent a first event.");
-    panel.port.emit("addon-to-content");
-  });
-  panel.port.on("received", function () {
-    assert.pass("The panel posted a message and received a response.");
-    panel.destroy();
-    done();
-  });
-  getActiveView(panel);
-};
-
-exports["test Panel Emit Early"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  const { getActiveView } = require("sdk/view/core");
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    contentScript: "self.port.on('addon-to-content', " +
-                   "             () => self.port.emit('received'));",
-  });
-  panel.port.on("received", function () {
-    assert.pass("The panel posted a message early and received a response.");
-    panel.destroy();
-    done();
-  });
-  panel.port.emit("addon-to-content");
-  getActiveView(panel);
-};
-
-exports["test Show Hide Panel"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  let { getActiveView } = require('sdk/view/core');
-
-  let panel = Panel({
-    contentScript: "self.postMessage('')",
-    contentScriptWhen: "end",
-    contentURL: "data:text/html;charset=utf-8,",
-    onMessage: function (message) {
-      panel.show();
-    },
-    onShow: function () {
-      assert.pass("The panel was shown.");
-      assert.equal(this, panel, "The 'this' object is the panel.");
-      assert.equal(this.isShowing, true, "panel.isShowing == true.");
-      panel.hide();
-    },
-    onHide: function () {
-      assert.pass("The panel was hidden.");
-      assert.equal(this, panel, "The 'this' object is the panel.");
-      assert.equal(this.isShowing, false, "panel.isShowing == false.");
-      panel.destroy();
-      done();
-    }
-  });
-  getActiveView(panel);
-};
-
-exports["test Document Reload"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  const { getActiveView } = require("sdk/view/core");
-
-  let url2 = "data:text/html;charset=utf-8,page2";
-  let content =
-    "<script>" +
-    "window.addEventListener('message', function({ data }) {"+
-    "  if (data == 'move') window.location = '" + url2 + "';" +
-    '}, false);' +
-    "</script>";
-  let messageCount = 0;
-  let panel = Panel({
-    // using URL here is intentional, see bug 859009
-    contentURL: URL("data:text/html;charset=utf-8," + encodeURIComponent(content)),
-    contentScript: "self.postMessage(window.location.href);" +
-                   // initiate change to url2
-                   "self.port.once('move', () => document.defaultView.postMessage('move', '*'));",
-    onMessage: function (message) {
-      messageCount++;
-      assert.notEqual(message, "about:blank", "about:blank is not a message " + messageCount);
-
-      if (messageCount == 1) {
-        assert.ok(/data:text\/html/.test(message), "First document had a content script; " + message);
-        panel.port.emit('move');
-        assert.pass('move message was sent');
-        return;
-      }
-      else if (messageCount == 2) {
-        assert.equal(message, url2, "Second document too; " + message);
-        panel.destroy();
-        done();
-      }
-    }
-  });
-  getActiveView(panel);
-  assert.pass('Panel was created');
-};
-
-// Test disabled because of bug 910230
-/*
-exports["test Parent Resize Hack"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  let browserWindow = getMostRecentBrowserWindow();
-
-  let previousWidth = browserWindow.outerWidth;
-  let previousHeight = browserWindow.outerHeight;
-
-  let content = "<script>" +
-                "function contentResize() {" +
-                "  resizeTo(200,200);" +
-                "  resizeBy(200,200);" +
-                "  window.postMessage('resize-attempt', '*');" +
-                "}" +
-                "</script>" +
-                "Try to resize browser window";
-
-  let panel = Panel({
-    contentURL: "data:text/html;charset=utf-8," + encodeURIComponent(content),
-    contentScriptWhen: "ready",
-    contentScript: Isolate(() => {
-        self.on('message', message => {
-          if (message === 'resize') unsafeWindow.contentResize();
-        });
-
-        window.addEventListener('message', ({ data }) => self.postMessage(data));
-      }),
-    onMessage: function (message) {
-      if (message !== "resize-attempt") return;
-
-      assert.equal(browserWindow, getMostRecentBrowserWindow(),
-        "The browser window is still the same");
-      assert.equal(previousWidth, browserWindow.outerWidth,
-        "Size doesn't change by calling resizeTo/By/...");
-      assert.equal(previousHeight, browserWindow.outerHeight,
-        "Size doesn't change by calling resizeTo/By/...");
-
-      try {
-        panel.destroy();
-      }
-      catch (e) {
-        assert.fail(e);
-        throw e;
-      }
-
-      done();
-    },
-    onShow: () => panel.postMessage('resize')
-  });
-
-  panel.show();
-}
-*/
-
-exports["test Resize Panel"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  let { getActiveView } = require('sdk/view/core');
-
-  // These tests fail on Linux if the browser window in which the panel
-  // is displayed is not active.  And depending on what other tests have run
-  // before this one, it might not be (the untitled window in which the test
-  // runner executes is often active).  So we make sure the browser window
-  // is focused by focusing it before running the tests.  Then, to be the best
-  // possible test citizen, we refocus whatever window was focused before we
-  // started running these tests.
-
-  let activeWindow = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-                      getService(Ci.nsIWindowWatcher).
-                      activeWindow;
-  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
-                      getService(Ci.nsIWindowMediator).
-                      getMostRecentWindow("navigator:browser");
-
-
-  function onFocus() {
-    browserWindow.removeEventListener("focus", onFocus, true);
-
-    let panel = Panel({
-      contentScript: "self.postMessage('')",
-      contentScriptWhen: "end",
-      contentURL: "data:text/html;charset=utf-8,",
-      height: 10,
-      width: 10,
-      onMessage: function (message) {
-        // Make sure that attempting to resize a panel while it isn't
-        // visible doesn't cause an error.
-        panel.resize(1, 1);
-
-        panel.show();
-      },
-      onShow: function () {
-        panel.resize(100,100);
-        panel.hide();
-      },
-      onHide: function () {
-        assert.ok((panel.width == 100) && (panel.height == 100),
-          "The panel was resized.");
-        if (activeWindow)
-          activeWindow.focus();
-        done();
-      }
-    });
-    getActiveView(panel);
-  }
-
-  if (browserWindow === activeWindow) {
-    onFocus();
-  }
-  else {
-    browserWindow.addEventListener("focus", onFocus, true);
-    browserWindow.focus();
-  }
-};
-
-exports["test Hide Before Show"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  let showCalled = false;
-  let hideCalled = false;
-  let panel1 = Panel({
-    onShow: function () {
-      showCalled = true;
-    },
-    onHide: function () {
-      hideCalled = true;
-    }
-  });
-  panel1.show();
-  panel1.hide();
-
-  let panel2 = Panel({
-    onShow: function () {
-      if (showCalled) {
-        assert.ok(hideCalled, 'should not emit show without also emitting hide');
-      } else {
-        assert.ok(!hideCalled, 'should not emit hide without also emitting show');
-      }
-      panel1.destroy();
-      panel2.destroy();
-      done();
-    },
-  });
-  panel2.show();
-};
-
-exports["test Several Show Hides"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  let hideCalled = 0;
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    onShow: function () {
-      panel.hide();
-    },
-    onHide: function () {
-      hideCalled++;
-      if (hideCalled < 3)
-        panel.show();
-      else {
-        assert.pass("onHide called three times as expected");
-        done();
-      }
-    }
-  });
-  panel.on('error', function(e) {
-    assert.fail('error was emitted:' + e.message + '\n' + e.stack);
-  });
-  panel.show();
-};
-
-exports["test Anchor And Arrow"] = function*(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module, ignorePassingDOMNodeWarning);
-  let { Panel } = loader.require('sdk/panel');
-
-  let count = 0;
-  let url = 'data:text/html;charset=utf-8,' +
-    '<html><head><title>foo</title></head><body>' +
-    '</body></html>';
-
-  let panel = yield new Promise(resolve => {
-    let browserWindow = getMostRecentBrowserWindow();
-    let anchor = browserWindow.document.getElementById("identity-box");
-    let panel = Panel({
-      contentURL: "data:text/html;charset=utf-8,<html><body style='padding: 0; margin: 0; " +
-                  "background: gray; text-align: center;'>Anchor: " +
-                  anchor.id + "</body></html>",
-      width: 200,
-      height: 100,
-      onShow: () => resolve(panel)
-    });
-    panel.show(null, anchor);
-  });
-  assert.pass("All anchored panel test displayed");
-
-  panel.destroy();
-  assert.pass("panel was destroyed.");
-};
-
-exports["test Panel Focus True"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  const FM = Cc["@mozilla.org/focus-manager;1"].
-                getService(Ci.nsIFocusManager);
-
-  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
-                      getService(Ci.nsIWindowMediator).
-                      getMostRecentWindow("navigator:browser");
-
-  // Make sure there is a focused element
-  browserWindow.document.documentElement.focus();
-
-  // Get the current focused element
-  let focusedElement = FM.focusedElement;
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    focus: true,
-    onShow: function () {
-      assert.ok(focusedElement !== FM.focusedElement,
-        "The panel takes the focus away.");
-      done();
-    }
-  });
-  panel.show();
-};
-
-exports["test Panel Focus False"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  const FM = Cc["@mozilla.org/focus-manager;1"].
-                getService(Ci.nsIFocusManager);
-
-  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
-                      getService(Ci.nsIWindowMediator).
-                      getMostRecentWindow("navigator:browser");
-
-  // Make sure there is a focused element
-  browserWindow.document.documentElement.focus();
-
-  // Get the current focused element
-  let focusedElement = FM.focusedElement;
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    focus: false,
-    onShow: function () {
-      assert.ok(focusedElement === FM.focusedElement,
-        "The panel does not take the focus away.");
-      done();
-    }
-  });
-  panel.show();
-};
-
-exports["test Panel Focus Not Set"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-
-  const FM = Cc["@mozilla.org/focus-manager;1"].
-                getService(Ci.nsIFocusManager);
-
-  let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
-                      getService(Ci.nsIWindowMediator).
-                      getMostRecentWindow("navigator:browser");
-
-  // Make sure there is a focused element
-  browserWindow.document.documentElement.focus();
-
-  // Get the current focused element
-  let focusedElement = FM.focusedElement;
-
-  let panel = Panel({
-    contentURL: "about:buildconfig",
-    onShow: function () {
-      assert.ok(focusedElement !== FM.focusedElement,
-        "The panel takes the focus away.");
-      done();
-    }
-  });
-  panel.show();
-};
-
-exports["test Panel Text Color"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  let { getActiveView } = require('sdk/view/core');
-
-  let html = "<html><head><style>body {color: yellow}</style></head>" +
-             "<body><p>Foo</p></body></html>";
-  let panel = Panel({
-    contentURL: "data:text/html;charset=utf-8," + encodeURI(html),
-    contentScript: "self.port.emit('color', " +
-                   "window.getComputedStyle(document.body.firstChild, null). " +
-                   "       getPropertyValue('color'));"
-  });
-  panel.port.on("color", function (color) {
-    assert.equal(color, "rgb(255, 255, 0)",
-      "The panel text color style is preserved when a style exists.");
-    panel.destroy();
-    done();
-  });
-  getActiveView(panel);
-};
-
-// Bug 866333
-exports["test watch event name"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  let { getActiveView } = require('sdk/view/core');
-
-  let html = "<html><head><style>body {color: yellow}</style></head>" +
-             "<body><p>Foo</p></body></html>";
-
-  let panel = Panel({
-    contentURL: "data:text/html;charset=utf-8," + encodeURI(html),
-    contentScript: "self.port.emit('watch', 'test');"
-  });
-  panel.port.on("watch", function (msg) {
-    assert.equal(msg, "test", 'watch event name works');
-    panel.destroy();
-    done();
-  });
-  getActiveView(panel);
-}
-
-// Bug 696552: Ensure panel.contentURL modification support
-exports["test Change Content URL"] = function(assert, done) {
-  const { Panel } = require('sdk/panel');
-  const { getActiveView } = require("sdk/view/core");
-
-  let panel = Panel({
-    contentURL: "about:blank",
-    contentScript: "self.port.emit('ready', document.location.href);"
-  });
-
-  getActiveView(panel);
-
-  let count = 0;
-  panel.port.on("ready", function (location) {
-    count++;
-    if (count == 1) {
-      assert.equal(location, "about:blank");
-      assert.equal(panel.contentURL, "about:blank");
-      panel.contentURL = "about:buildconfig";
-    }
-    else {
-      assert.equal(location, "about:buildconfig");
-      assert.equal(panel.contentURL, "about:buildconfig");
-      panel.destroy();
-      done();
-    }
-  });
-};
-
-function makeEventOrderTest(options) {
-  let expectedEvents = [];
-
-  return function(assert, done) {
-    const { Panel } = require('sdk/panel');
-
-    let panel = Panel({ contentURL: "about:buildconfig" });
-
-    function expect(event, cb) {
-      expectedEvents.push(event);
-      panel.on(event, function() {
-        assert.equal(event, expectedEvents.shift());
-        if (cb)
-          setTimeout(cb, 1);
-      });
-      return {then: expect};
-    }
-
-    options.test(assert, done, expect, panel);
-  }
-}
-
-exports["test Automatic Destroy"] = function(assert) {
-  let loader = Loader(module);
-  let panel = loader.require("sdk/panel").Panel({
-    contentURL: "about:buildconfig",
-    contentScript:
-      "self.port.on('event', () => self.port.emit('event-back'));"
-  });
-
-  loader.unload();
-
-  assert.throws(() => {
-    panel.port.emit("event");
-  }, /already have been unloaded/, "check automatic destroy");
-};
-
-exports["test Show Then Destroy"] = makeEventOrderTest({
-  test: function(assert, done, expect, panel) {
-    panel.show();
-    expect('show', function() { panel.destroy(); }).
-      then('hide', function() { done(); });
-  }
-});
-
-
-// TODO: Re-enable and fix this intermittent test
-// See Bug 1111695 https://bugzilla.mozilla.org/show_bug.cgi?id=1111695
-/*
-exports["test Show Then Hide Then Destroy"] = makeEventOrderTest({
-  test: function(assert, done, expect, panel) {
-    panel.show();
-    expect('show', function() { panel.hide(); }).
-      then('hide', function() { panel.destroy(); done(); });
-  }
-});
-*/
-
-exports["test Content URL Option"] = function(assert) {
-  const { Panel } = require('sdk/panel');
-
-  const URL_STRING = "about:buildconfig";
-  const HTML_CONTENT = "<html><title>Test</title><p>This is a test.</p></html>";
-  let dataURL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML_CONTENT);
-
-  let panel = Panel({ contentURL: URL_STRING });
-  assert.pass("contentURL accepts a string URL.");
-  assert.equal(panel.contentURL, URL_STRING,
-              "contentURL is the string to which it was set.");
-  panel.destroy();
-
-  panel = Panel({ contentURL: dataURL });
-  assert.pass("contentURL accepts a data: URL.");
-  panel.destroy();
-
-  panel = Panel({});
-  assert.ok(panel.contentURL == null, "contentURL is undefined.");
-  panel.destroy();
-
-  assert.throws(() => Panel({ contentURL: "foo" }),
-                    /The `contentURL` option must be a valid URL./,
-                    "Panel throws an exception if contentURL is not a URL.");
-};
-
-exports["test SVG Document"] = function(assert) {
-  let panel = require("sdk/panel").Panel({ contentURL: SVG_URL });
-
-  panel.show();
-  panel.hide();
-  panel.destroy();
-
-  assert.pass("contentURL accepts a svg document");
-  assert.equal(panel.contentURL, SVG_URL,
-              "contentURL is the string to which it was set.");
-};
-
-exports["test ContentScriptOptions Option"] = function(assert, done) {
-  let loader = Loader(module);
-  let panel = loader.require("sdk/panel").Panel({
-      contentScript: "self.postMessage( [typeof self.options.d, self.options] );",
-      contentScriptWhen: "end",
-      contentScriptOptions: {a: true, b: [1,2,3], c: "string", d: function(){ return 'test'}},
-      contentURL: "data:text/html;charset=utf-8,",
-      onMessage: function(msg) {
-        assert.equal( msg[0], 'undefined', 'functions are stripped from contentScriptOptions' );
-        assert.equal( typeof msg[1], 'object', 'object as contentScriptOptions' );
-        assert.equal( msg[1].a, true, 'boolean in contentScriptOptions' );
-        assert.equal( msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions' );
-        assert.equal( msg[1].c, 'string', 'string in contentScriptOptions' );
-        done();
-      }
-    });
-  const { getActiveView } = loader.require("sdk/view/core");
-  getActiveView(panel);
-};
-
-exports["test console.log in Panel"] = function(assert, done) {
-  let text = 'console.log() in Panel works!';
-  let html = '<script>onload = function log(){\
-                console.log("' + text + '");\
-              }</script>';
-
-  let { loader } = LoaderWithHookedConsole(module, onMessage);
-  let { Panel } = loader.require('sdk/panel');
-
-  let panel = Panel({
-    contentURL: 'data:text/html;charset=utf-8,' + encodeURIComponent(html)
-  });
-
-  panel.show();
-
-  function onMessage(type, message) {
-    assert.equal(type, 'log', 'console.log() works');
-    assert.equal(message, text, 'console.log() works');
-    panel.destroy();
-    done();
-  }
-};
-
-/*if (isWindowPBSupported) {
-  exports.testPanelDoesNotShowInPrivateWindowNoAnchor = function(assert, done) {
-    let { loader } = LoaderWithHookedConsole(module, ignorePassingDOMNodeWarning);
-    let { Panel } = loader.require("sdk/panel");
-    let browserWindow = getMostRecentBrowserWindow();
-
-    assert.equal(isPrivate(browserWindow), false, 'open window is not private');
-
-    let panel = Panel({
-      contentURL: SVG_URL
-    });
-
-    testShowPanel(assert, panel).
-      then(makeEmptyPrivateBrowserWindow).
-      then(focus).
-      then(function(window) {
-        assert.equal(isPrivate(window), true, 'opened window is private');
-        assert.pass('private window was focused');
-        return window;
-      }).
-      then(function(window) {
-        let { promise, resolve } = defer();
-        let showTries = 0;
-        let showCount = 0;
-
-        panel.on('show', function runTests() {
-          showCount++;
-
-          if (showTries == 2) {
-            panel.removeListener('show', runTests);
-            assert.equal(showCount, 1, 'show count is correct - 1');
-            resolve(window);
-          }
-        });
-        showTries++;
-        panel.show();
-        showTries++;
-        panel.show(null, browserWindow.gBrowser);
-
-        return promise;
-      }).
-      then(function(window) {
-        assert.equal(panel.isShowing, true, 'panel is still showing');
-        panel.hide();
-        assert.equal(panel.isShowing, false, 'panel is hidden');
-        return window;
-      }).
-      then(close).
-      then(function() {
-        assert.pass('private window was closed');
-      }).
-      then(testShowPanel.bind(null, assert, panel)).
-      then(done, assert.fail.bind(assert));
-  }
-
-  exports.testPanelDoesNotShowInPrivateWindowWithAnchor = function(assert, done) {
-    let { loader } = LoaderWithHookedConsole(module, ignorePassingDOMNodeWarning);
-    let { Panel } = loader.require("sdk/panel");
-    let browserWindow = getMostRecentBrowserWindow();
-
-    assert.equal(isPrivate(browserWindow), false, 'open window is not private');
-
-    let panel = Panel({
-      contentURL: SVG_URL
-    });
-
-    testShowPanel(assert, panel).
-      then(makeEmptyPrivateBrowserWindow).
-      then(focus).
-      then(function(window) {
-        assert.equal(isPrivate(window), true, 'opened window is private');
-        assert.pass('private window was focused');
-        return window;
-      }).
-      then(function(window) {
-        let { promise, resolve } = defer();
-        let showTries = 0;
-        let showCount = 0;
-
-        panel.on('show', function runTests() {
-          showCount++;
-
-          if (showTries == 2) {
-            panel.removeListener('show', runTests);
-            assert.equal(showCount, 1, 'show count is correct - 1');
-            resolve(window);
-          }
-        });
-        showTries++;
-        panel.show(null, window.gBrowser);
-        showTries++;
-        panel.show(null, browserWindow.gBrowser);
-
-        return promise;
-      }).
-      then(function(window) {
-        assert.equal(panel.isShowing, true, 'panel is still showing');
-        panel.hide();
-        assert.equal(panel.isShowing, false, 'panel is hidden');
-        return window;
-      }).
-      then(close).
-      then(function() {
-        assert.pass('private window was closed');
-      }).
-      then(testShowPanel.bind(null, assert, panel)).
-      then(done, assert.fail.bind(assert));
-  }
-}*/
-
-function testShowPanel(assert, panel) {
-  let { promise, resolve } = defer();
-
-  assert.ok(!panel.isShowing, 'the panel is not showing [1]');
-
-  panel.once('show', function() {
-    assert.ok(panel.isShowing, 'the panel is showing');
-
-    panel.once('hide', function() {
-      assert.ok(!panel.isShowing, 'the panel is not showing [2]');
-
-      resolve(null);
-    });
-
-    panel.hide();
-  })
-  panel.show();
-
-  return promise;
-}
-
-exports['test Style Applied Only Once'] = function (assert, done) {
-  let loader = Loader(module);
-  let panel = loader.require("sdk/panel").Panel({
-    contentURL: "data:text/html;charset=utf-8,",
-    contentScript:
-      'self.port.on("check",function() { self.port.emit("count", document.getElementsByTagName("style").length); });' +
-      'self.port.on("ping", function (count) { self.port.emit("pong", count); });'
-  });
-
-  panel.port.on('count', function (styleCount) {
-    assert.equal(styleCount, 1, 'should only have one style');
-    done();
-  });
-
-  panel.port.on('pong', function (counter) {
-    panel[--counter % 2 ? 'hide' : 'show']();
-    panel.port.emit(!counter ? 'check' : 'ping', counter);
-  });
-
-  panel.on('show', init);
-  panel.show();
-
-  function init () {
-    panel.removeListener('show', init);
-    panel.port.emit('ping', 10);
-  }
-};
-
-exports['test Only One Panel Open Concurrently'] = function (assert, done) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel')
-
-  let panelA = Panel({
-    contentURL: 'about:buildconfig'
-  });
-
-  let panelB = Panel({
-    contentURL: 'about:buildconfig',
-    onShow: function () {
-      // When loading two panels simulataneously, only the second
-      // should be shown, never showing the first
-      assert.equal(panelA.isShowing, false, 'First panel is hidden');
-      assert.equal(panelB.isShowing, true, 'Second panel is showing');
-      panelC.show();
-    }
-  });
-
-  let panelC = Panel({
-    contentURL: 'about:buildconfig',
-    onShow: function () {
-      assert.equal(panelA.isShowing, false, 'First panel is hidden');
-      assert.equal(panelB.isShowing, false, 'Second panel is hidden');
-      assert.equal(panelC.isShowing, true, 'Third panel is showing');
-      done();
-    }
-  });
-
-  panelA.show();
-  panelB.show();
-};
-
-exports['test passing DOM node as first argument'] = function (assert, done) {
-  let warned = defer();
-  let shown = defer();
-
-  function onMessage(type, message) {
-    if (type != 'warn') return;
-
-    let warning = 'Passing a DOM node to Panel.show() method is an unsupported ' +
-                  'feature that will be soon replaced. ' +
-                  'See: https://bugzilla.mozilla.org/show_bug.cgi?id=878877';
-
-    assert.equal(type, 'warn',
-      'the message logged is a warning');
-
-    assert.equal(message, warning,
-      'the warning content is correct');
-
-    warned.resolve();
-  }
-
-  let { loader } = LoaderWithHookedConsole(module, onMessage);
-  let { Panel } = loader.require('sdk/panel');
-  let { ActionButton } = loader.require('sdk/ui/button/action');
-  let { getNodeView } = loader.require('sdk/view/core');
-  let { document } = getMostRecentBrowserWindow();
-
-  let panel = Panel({
-    onShow: function() {
-      let panelNode = document.getElementById('mainPopupSet').lastChild;
-
-      assert.equal(panelNode.anchorNode, buttonNode,
-        'the panel is properly anchored to the button');
-
-      shown.resolve();
-    }
-  });
-
-  let button = ActionButton({
-    id: 'panel-button',
-    label: 'panel button',
-    icon: './icon.png'
-  });
-
-  let buttonNode = getNodeView(button);
-
-  all([warned.promise, shown.promise]).
-    then(loader.unload).
-    then(done, assert.fail)
-
-  panel.show(buttonNode);
-};
-
-// This test is checking that `onpupshowing` events emitted by panel's children
-// are not considered.
-// See Bug 886329
-exports['test nested popups'] = function (assert, done) {
-  let loader = Loader(module);
-  let { Panel } = loader.require('sdk/panel');
-  let { getActiveView } = loader.require('sdk/view/core');
-  let url = '<select><option>1<option>2<option>3</select>';
-
-  let getContentWindow = panel => {
-    return getActiveView(panel).querySelector('iframe').contentWindow;
-  }
-
-  let panel = Panel({
-    contentURL: 'data:text/html;charset=utf-8,' + encodeURIComponent(url),
-    onShow: () => {
-      ready(getContentWindow(panel)).then(({ window, document }) => {
-        let select = document.querySelector('select');
-        let event = document.createEvent('UIEvent');
-
-        event.initUIEvent('popupshowing', true, true, window, null);
-        select.dispatchEvent(event);
-
-        assert.equal(
-          select,
-          getContentWindow(panel).document.querySelector('select'),
-          'select is still loaded in panel'
-        );
-
-        done();
-      });
-    }
-  });
-
-  panel.show();
-};
-
-exports['test emits on url changes'] = function (assert, done) {
-  let loader = Loader(module);
-  let { Panel } = loader.require('sdk/panel');
-  let uriA = 'data:text/html;charset=utf-8,A';
-  let uriB = 'data:text/html;charset=utf-8,B';
-
-  let panel = Panel({
-    contentURL: uriA,
-    contentScript: 'new ' + function() {
-      self.port.on('hi', function() {
-        self.port.emit('bye', document.URL);
-      });
-    }
-  });
-
-  panel.contentURL = uriB;
-  panel.port.emit('hi', 'hi')
-  panel.port.on('bye', function(uri) {
-    assert.equal(uri, uriB, 'message was delivered to new uri');
-    loader.unload();
-    done();
-  });
-};
-
-exports['test panel can be constructed without any arguments'] = function (assert) {
-  const { Panel } = require('sdk/panel');
-
-  let panel = Panel();
-  assert.ok(true, "Creating a panel with no arguments does not throw");
-};
-
-exports['test panel CSS'] = function(assert, done) {
-  const { merge } = require("sdk/util/object");
-
-  let loader = Loader(module, null, null, {
-    modules: {
-      "sdk/self": merge({}, self, {
-        data: merge({}, self.data, fixtures)
-      })
-    }
-  });
-
-  const { Panel } = loader.require('sdk/panel');
-
-  const { getActiveView } = loader.require('sdk/view/core');
-
-  const getContentWindow = panel =>
-    getActiveView(panel).querySelector('iframe').contentWindow;
-
-  let panel = Panel({
-    contentURL: 'data:text/html;charset=utf-8,' +
-                '<div style="background: silver">css test</div>',
-    contentStyle: 'div { height: 100px; }',
-    contentStyleFile: [fixtures.url("include-file.css"), "./border-style.css"],
-    onShow: () => {
-      ready(getContentWindow(panel)).then(({ window, document }) => {
-        let div = document.querySelector('div');
-
-      assert.equal(div.clientHeight, 100,
-        "Panel contentStyle worked");
-
-      assert.equal(div.offsetHeight, 120,
-        "Panel contentStyleFile worked");
-
-      assert.equal(window.getComputedStyle(div).borderTopStyle, "dashed",
-        "Panel contentStyleFile with relative path worked");
-
-        loader.unload();
-        done();
-      }).catch(assert.fail);
-    }
-  });
-
-  panel.show();
-};
-
-exports['test panel contentScriptFile'] = function(assert, done) {
-  const { merge } = require("sdk/util/object");
-
-  let loader = Loader(module, null, null, {
-    modules: {
-      "sdk/self": merge({}, self, {
-        data: merge({}, self.data, {url: fixtures.url})
-      })
-    }
-  });
-
-  const { Panel } = loader.require('sdk/panel');
-  const { getActiveView } = loader.require('sdk/view/core');
-
-  const getContentWindow = panel =>
-    getActiveView(panel).querySelector('iframe').contentWindow;
-
-  let whenMessage = defer();
-  let whenShown = defer();
-
-  let panel = Panel({
-    contentURL: './test.html',
-    contentScriptFile: "./test-contentScriptFile.js",
-    onMessage: (message) => {
-      assert.equal(message, "msg from contentScriptFile",
-        "Panel contentScriptFile with relative path worked");
-
-      whenMessage.resolve();
-    },
-    onShow: () => {
-      ready(getContentWindow(panel)).then(({ document }) => {
-        assert.equal(document.title, 'foo',
-          "Panel contentURL with relative path worked");
-
-        whenShown.resolve();
-      });
-    }
-  });
-
-  all([whenMessage.promise, whenShown.promise]).
-    then(loader.unload).
-    then(done, assert.fail);
-
-  panel.show();
-};
-
-
-exports['test panel CSS list'] = function(assert, done) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel');
-
-  const { getActiveView } = loader.require('sdk/view/core');
-
-  const getContentWindow = panel =>
-    getActiveView(panel).querySelector('iframe').contentWindow;
-
-  let panel = Panel({
-    contentURL: 'data:text/html;charset=utf-8,' +
-                '<div style="width:320px; max-width: 480px!important">css test</div>',
-    contentStyleFile: [
-      // Highlight evaluation order in this list
-      "data:text/css;charset=utf-8,div { border: 1px solid black; }",
-      "data:text/css;charset=utf-8,div { border: 10px solid black; }",
-      // Highlight evaluation order between contentStylesheet & contentStylesheetFile
-      "data:text/css;charset=utf-8s,div { height: 1000px; }",
-      // Highlight precedence between the author and user style sheet
-      "data:text/css;charset=utf-8,div { width: 200px; max-width: 640px!important}",
-    ],
-    contentStyle: [
-      "div { height: 10px; }",
-      "div { height: 100px; }"
-    ],
-    onShow: () => {
-      ready(getContentWindow(panel)).then(({ window, document }) => {
-        let div = document.querySelector('div');
-        let style = window.getComputedStyle(div);
-
-        assert.equal(div.clientHeight, 100,
-          'Panel contentStyle list is evaluated after contentStyleFile');
-
-        assert.equal(div.offsetHeight, 120,
-          'Panel contentStyleFile list works');
-
-        assert.equal(style.width, '320px',
-          'add-on author/page author stylesheet precedence works');
-
-        assert.equal(style.maxWidth, '480px',
-          'add-on author/page author stylesheet !important precedence works');
-
-        loader.unload();
-      }).then(done, assert.fail);
-    }
-  });
-
-  panel.show();
-};
-
-exports['test panel contextmenu validation'] = function(assert) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel');
-
-  let panel = Panel({});
-
-  assert.equal(panel.contextMenu, false,
-    'contextMenu option is `false` by default');
-
-  panel.destroy();
-
-  panel = Panel({
-    contextMenu: false
-  });
-
-  assert.equal(panel.contextMenu, false,
-    'contextMenu option is `false`');
-
-  panel.contextMenu = true;
-
-  assert.equal(panel.contextMenu, true,
-    'contextMenu option accepts boolean values');
-
-  panel.destroy();
-
-  panel = Panel({
-    contextMenu: true
-  });
-
-  assert.equal(panel.contextMenu, true,
-    'contextMenu option is `true`');
-
-  panel.contextMenu = false;
-
-  assert.equal(panel.contextMenu, false,
-    'contextMenu option accepts boolean values');
-
-  assert.throws(() =>
-    Panel({contextMenu: 1}),
-    /The option "contextMenu" must be one of the following types: boolean, undefined, null/,
-    'contextMenu only accepts boolean or nil values');
-
-  panel = Panel();
-
-  assert.throws(() =>
-    panel.contextMenu = 1,
-    /The option "contextMenu" must be one of the following types: boolean, undefined, null/,
-    'contextMenu only accepts boolean or nil values');
-
-  loader.unload();
-}
-
-exports['test panel contextmenu enabled'] = function*(assert) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel');
-  const { getActiveView } = loader.require('sdk/view/core');
-  const { getContentDocument } = loader.require('sdk/panel/utils');
-
-  let contextmenu = getMostRecentBrowserWindow().
-                      document.getElementById("contentAreaContextMenu");
-
-  let panel = Panel({contextMenu: true});
-
-  panel.show();
-
-  yield wait(panel, 'show');
-
-  let view = getActiveView(panel);
-  let window = getContentDocument(view).defaultView;
-
-  let { sendMouseEvent } = window.QueryInterface(Ci.nsIInterfaceRequestor).
-                                    getInterface(Ci.nsIDOMWindowUtils);
-
-  yield ready(window);
-
-  assert.equal(contextmenu.state, 'closed',
-    'contextmenu must be closed');
-
-  sendMouseEvent('contextmenu', 20, 20, 2, 1, 0);
-
-  yield wait(contextmenu, 'popupshown');
-
-  assert.equal(contextmenu.state, 'open',
-    'contextmenu is opened');
-
-  contextmenu.hidePopup();
-
-  loader.unload();
-}
-
-exports['test panel contextmenu disabled'] = function*(assert) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel');
-  const { getActiveView } = loader.require('sdk/view/core');
-  const { getContentDocument } = loader.require('sdk/panel/utils');
-
-  let contextmenu = getMostRecentBrowserWindow().
-                      document.getElementById("contentAreaContextMenu");
-  let listener = () => assert.fail('popupshown should never be called');
-
-  let panel = Panel();
-
-  panel.show();
-
-  yield wait(panel, 'show');
-
-  let view = getActiveView(panel);
-  let window = getContentDocument(view).defaultView;
-
-  let { sendMouseEvent } = window.QueryInterface(Ci.nsIInterfaceRequestor).
-                                    getInterface(Ci.nsIDOMWindowUtils);
-
-  yield ready(window);
-
-  assert.equal(contextmenu.state, 'closed',
-    'contextmenu must be closed');
-
-  sendMouseEvent('contextmenu', 20, 20, 2, 1, 0);
-
-  contextmenu.addEventListener('popupshown', listener);
-
-  yield wait(1000);
-
-  contextmenu.removeEventListener('popupshown', listener);
-
-  assert.equal(contextmenu.state, 'closed',
-    'contextmenu was never open');
-
-  loader.unload();
-}
-
-exports["test panel addon global object"] = function*(assert) {
-  const { merge } = require("sdk/util/object");
-
-  let loader = Loader(module, null, null, {
-    modules: {
-      "sdk/self": merge({}, self, {
-        data: merge({}, self.data, {url: fixtures.url})
-      })
-    }
-  });
-
-  const { Panel } = loader.require('sdk/panel');
-
-  let panel = Panel({
-    contentURL: "./test-trusted-document.html"
-  });
-
-  panel.show();
-
-  yield wait(panel, "show");
-
-  panel.port.emit('addon-to-document', 'ok');
-
-  yield wait(panel.port, "document-to-addon");
-
-  assert.pass("Received an event from the document");
-
-  loader.unload();
-}
-
-exports["test panel load doesn't show"] = function*(assert) {
-  let loader = Loader(module);
-
-  let panel = loader.require("sdk/panel").Panel({
-    contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
-    contentScriptWhen: "start",
-    contentURL: "data:text/html;charset=utf-8,",
-  });
-
-  let shown = defer();
-  let messaged = defer();
-
-  panel.once("show", function() {
-    shown.resolve();
-  });
-
-  panel.once("message", function() {
-    messaged.resolve();
-  });
-
-  panel.show();
-  yield all([shown.promise, messaged.promise]);
-  assert.ok(true, "Saw panel display");
-
-  panel.on("show", function() {
-    assert.fail("Should not have seen another show event")
-  });
-
-  messaged = defer();
-  panel.once("message", function() {
-    assert.ok(true, "Saw panel reload");
-    messaged.resolve();
-  });
-
-  panel.contentURL = "data:text/html;charset=utf-8,<html/>";
-
-  yield messaged.promise;
-  loader.unload();
-}
-
-exports["test Panel without contentURL and contentScriptWhen=start should show"] = function*(assert) {
-  let loader = Loader(module);
-
-  let panel = loader.require("sdk/panel").Panel({
-    contentScriptWhen: "start",
-    // No contentURL, the bug only shows up when contentURL is not explicitly set.
-  });
-
-  yield new Promise(resolve => {
-    panel.once("show", resolve);
-    panel.show();
-  });
-
-  assert.pass("Received show event");
-
-  loader.unload();
-}
-
-exports["test Panel links"] = function*(assert) {
-  const loader = Loader(module);
-
-  const { Panel } = loader.require('sdk/panel');
-  const { getActiveView } = loader.require('sdk/view/core');
-  const tabs = loader.require('sdk/tabs');
-
-  const synthesizeClick = (panel, options) => {
-    let { contentWindow } = getActiveView(panel).querySelector('iframe');
-    let event = new contentWindow.MouseEvent('click', options);
-
-    contentWindow.document.querySelector('a').dispatchEvent(event);
-  }
-
-  const linkURL = 'data:text/html;charset=utf-8,' +
-                  encodeURIComponent('<html><a href="#">foo</a></html>');
-
-  const contentURL = 'data:text/html;charset=utf-8,' +
-          encodeURIComponent(`<html><a href="${linkURL}">page</a></html>`);
-
-  let panel = Panel({
-    contentURL,
-    contentScript: Isolate(() => self.postMessage(document.URL))
-  });
-
-  panel.show();
-
-  let url = yield wait(panel, 'message');
-
-  assert.equal(url, contentURL,
-    'content URL loaded');
-
-  synthesizeClick(panel, { bubbles: true });
-
-  url = yield wait(panel, 'message');
-
-  assert.equal(url, linkURL,
-    'link URL loaded in the panel after click');
-
-  synthesizeClick(panel, {
-    bubbles: true,
-    [platform === 'darwin' ? 'metaKey' : 'ctrlKey']: true
-  });
-
-  let tab = yield wait(tabs, 'ready');
-
-  assert.equal(tab.url, linkURL + '#',
-      'link URL loaded in a new tab after click + accel');
-
-  loader.unload();
-}
-
-exports["test Panel script allow property"] = function*(assert) {
-  const loader = Loader(module);
-  const { Panel } = loader.require('sdk/panel');
-  const { getActiveView } = loader.require('sdk/view/core');
-
-  const contentURL = 'data:text/html;charset=utf-8,' +
-    encodeURIComponent(`<body onclick='postMessage("got script click", "*")'>
-        <script>
-        document.body.appendChild(document.createElement('unwanted'))
-        </script>
-        </body>`);
-  let panel = Panel({
-    contentURL,
-    allow: {script: false},
-  });
-
-  panel.show();
-
-  yield wait(panel, 'show');
-
-  let { contentWindow } = getActiveView(panel).querySelector('iframe');
-
-  assert.equal(contentWindow.document.body.lastElementChild.localName, "script",
-               "Script should not have executed");
-
-  panel.allow.script = true;
-
-  let p = wait(contentWindow, "message");
-  let event = new contentWindow.MouseEvent('click', {});
-  contentWindow.document.body.dispatchEvent(event);
-
-  let msg = yield p;
-  assert.equal(msg.data, "got script click", "Should have seen script click");
-
-  loader.unload();
-};
-
-after(exports, function*(name, assert) {
-  yield cleanUI();
-  assert.pass("ui was cleaned.");
-});
-
-if (isTravisCI) {
-  module.exports = {
-    "test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
-  };
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-passwords-utils.js
+++ /dev/null
@@ -1,141 +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 { store, search, remove } = require("sdk/passwords/utils");
-
-exports["test store requires `password` field"] = function(assert) {
-  assert.throws(function() {
-    store({ username: "foo", realm: "bar" });
-  }, "`password` is required");
-};
-
-exports["test store requires `username` field"] = function(assert) {
-  assert.throws(function() {
-    store({ password: "foo", realm: "bar" });
-  }, "`username` is required");
-};
-
-exports["test store requires `realm` field"] = function(assert) {
-  assert.throws(function() {
-    store({ username: "foo", password: "bar" });
-  }, "`password` is required");
-};
-
-exports["test can't store same login twice"] = function(assert) {
-  let options = { username: "user", password: "pass", realm: "realm" };
-  store(options);
-  assert.throws(function() {
-    store(options);
-  }, "can't store same pass twice");
-  remove(options);
-};
-
-exports["test remove throws if no login found"] = function(assert) {
-  assert.throws(function() {
-    remove({ username: "foo", password: "bar", realm: "baz" });
-  }, "can't remove unstored credentials");
-};
-
-exports["test addon associated credentials"] = function(assert) {
-  let options = { username: "foo", password: "bar", realm: "baz" };
-  store(options);
-
-  assert.ok(search().length, "credential was stored");
-  assert.ok(search(options).length, "stored credential found");
-  assert.ok(search({ username: options.username }).length, "found by username");
-  assert.ok(search({ password: options.password }).length, "found by password");
-  assert.ok(search({ realm: options.realm }).length, "found by realm");
-
-  let credential = search(options)[0];
-  assert.equal(credential.url.indexOf("addon:"), 0,
-               "`addon:` uri is used for add-on associated credentials");
-  assert.equal(credential.username, options.username, "username matches");
-  assert.equal(credential.password, options.password, "password matches");
-  assert.equal(credential.realm, options.realm, "realm matches");
-  assert.equal(credential.formSubmitURL, null,
-               "`formSubmitURL` is `null` for add-on associated credentials");
-  assert.equal(credential.usernameField, "", "usernameField is empty");
-  assert.equal(credential.passwordField, "", "passwordField is empty");
-
-  remove(search(options)[0]);
-  assert.ok(!search(options).length, "remove worked");
-};
-
-exports["test web page associated credentials"] = function(assert) {
-  let options = {
-    url: "http://www.example.com",
-    formSubmitURL: "http://login.example.com",
-    username: "user",
-    password: "pass",
-    usernameField: "user-f",
-    passwordField: "pass-f"
-  };
-  store({
-    url: "http://www.example.com/login",
-    formSubmitURL: "http://login.example.com/foo/authenticate.cgi",
-    username: options.username,
-    password: options.password,
-    usernameField: options.usernameField,
-    passwordField: options.passwordField
-  });
-
-  assert.ok(search().length, "credential was stored");
-  assert.ok(search(options).length, "stored credential found");
-  assert.ok(search({ username: options.username }).length, "found by username");
-  assert.ok(search({ password: options.password }).length, "found by password");
-  assert.ok(search({ formSubmitURL: options.formSubmitURL }).length,
-            "found by formSubmitURL");
-  assert.ok(search({ usernameField: options.usernameField }).length,
-            "found by usernameField");
-  assert.ok(search({ passwordField: options.passwordField }).length,
-            "found by passwordField");
-
-  let credential = search(options)[0];
-  assert.equal(credential.url, options.url, "url matches");
-  assert.equal(credential.username, options.username, "username matches");
-  assert.equal(credential.password, options.password, "password matches");
-  assert.equal(credential.realm, null, "realm is ");
-  assert.equal(credential.formSubmitURL, options.formSubmitURL,
-               "`formSubmitURL` matches");
-  assert.equal(credential.usernameField, options.usernameField,
-               "usernameField matches");
-  assert.equal(credential.passwordField, options.passwordField,
-               "passwordField matches");
-
-  remove(search(options)[0]);
-  assert.ok(!search(options).length, "remove worked");
-};
-
-exports["test site authentication credentials"] = function(assert) {
-  let options = {
-    url: "http://test.authentication.com",
-    username: "u",
-    password: "p",
-    realm: "r"
-  };
-
-  store(options);
-  assert.ok(search().length, "credential was stored");
-  assert.ok(search(options).length, "stored credential found");
-  assert.ok(search({ username: options.username }).length, "found by username");
-  assert.ok(search({ password: options.password }).length, "found by password");
-  assert.ok(search({ realm: options.realm }).length, "found by realm");
-  assert.ok(search({ url: options.url }).length, "found by url");
-
-  let credential = search(options)[0];
-  assert.equal(credential.url, options.url, "url matches");
-  assert.equal(credential.username, options.username, "username matches");
-  assert.equal(credential.password, options.password, "password matches");
-  assert.equal(credential.realm, options.realm, "realm matches");
-  assert.equal(credential.formSubmitURL, null,
-               "`formSubmitURL` is `null` for site authentication credentials");
-  assert.equal(credential.usernameField, "", "usernameField is empty");
-  assert.equal(credential.passwordField, "", "passwordField is empty");
-
-  remove(search(options)[0]);
-  assert.ok(!search(options).length, "remove worked");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-passwords.js
+++ /dev/null
@@ -1,280 +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 { store, search, remove } = require("sdk/passwords");
-
-exports["test store requires `password` field"] = function(assert, done) {
-  store({
-    username: "foo",
-    realm: "bar",
-    onComplete: function onComplete() {
-      assert.fail("onComplete should not be called");
-    },
-    onError: function onError() {
-      assert.pass("'`password` is required");
-      done();
-    }
-  });
-};
-
-exports["test store requires `username` field"] = function(assert, done) {
-  store({
-    password: "foo",
-    realm: "bar",
-    onComplete: function onComplete() {
-      assert.fail("onComplete should not be called");
-    },
-    onError: function onError() {
-      assert.pass("'`username` is required");
-      done();
-    }
-  });
-};
-
-exports["test onComplete is optional"] = function(assert, done) {
-  store({
-    realm: "bla",
-    username: "bla",
-    password: "bla",
-    onError: function onError() {
-      assert.fail("onError was called");
-    }
-  });
-  assert.pass("exception is not thrown if `onComplete is missing")
-  done();
-};
-
-exports["test exceptions in onComplete are reported"] = function(assert, done) {
-  store({
-    realm: "throws",
-    username: "error",
-    password: "boom!",
-    onComplete: function onComplete(error) {
-      throw new Error("Boom!")
-    },
-    onError: function onError(error) {
-      assert.equal(error.message, "Boom!", "Error thrown is reported");
-      done();
-    }
-  });
-};
-
-exports["test store requires `realm` field"] = function(assert, done) {
-  store({
-    username: "foo",
-    password: "bar",
-    onComplete: function onComplete() {
-      assert.fail("onComplete should not be called");
-    },
-    onError: function onError() {
-      assert.pass("'`realm` is required");
-      done();
-    }
-  });
-};
-
-exports["test can't store same login twice"] = function(assert, done) {
-  store({
-    username: "user",
-    password: "pass",
-    realm: "realm",
-    onComplete: function onComplete() {
-      assert.pass("credential saved");
-
-      store({
-        username: "user",
-        password: "pass",
-        realm: "realm",
-        onComplete: function onComplete() {
-          assert.fail("onComplete should not be called");
-        },
-        onError: function onError() {
-          assert.pass("re-saving credential failed");
-
-          remove({
-            username: "user",
-            password: "pass",
-            realm: "realm",
-            onComplete: function onComplete() {
-              assert.pass("credential was removed");
-              done();
-            },
-            onError: function onError() {
-              assert.fail("remove should not fail");
-            }
-          });
-        }
-      });
-    },
-    onError: function onError() {
-      assert.fail("onError should not be called");
-    }
-  });
-};
-
-exports["test remove fails if no login found"] = function(assert, done) {
-  remove({
-    username: "foo",
-    password: "bar",
-    realm: "baz",
-    onComplete: function onComplete() {
-      assert.fail("should not be able to remove unstored credentials");
-    },
-    onError: function onError() {
-      assert.pass("can't remove unstored credentials");
-      done();
-    }
-  });
-};
-
-exports["test addon associated credentials"] = function(assert, done) {
-  store({
-    username: "foo",
-    password: "bar",
-    realm: "baz",
-    onComplete: function onComplete() {
-      search({
-        username: "foo",
-        password: "bar",
-        realm: "baz",
-        onComplete: function onComplete([credential]) {
-          assert.equal(credential.url.indexOf("addon:"), 0,
-                       "`addon:` uri is used for add-on credentials");
-          assert.equal(credential.username, "foo",
-                       "username matches");
-          assert.equal(credential.password, "bar",
-                       "password matches");
-          assert.equal(credential.realm, "baz", "realm matches");
-          assert.equal(credential.formSubmitURL, null,
-                       "`formSubmitURL` is `null` for add-on credentials");
-          assert.equal(credential.usernameField, "", "usernameField is empty");
-          assert.equal(credential.passwordField, "", "passwordField is empty");
-
-          remove({
-            username: credential.username,
-            password: credential.password,
-            realm: credential.realm,
-            onComplete: function onComplete() {
-              assert.pass("credential is removed");
-              done();
-            },
-            onError: function onError() {
-              assert.fail("onError should not be called");
-            }
-          });
-        },
-        onError: function onError() {
-          assert.fail("onError should not be called");
-        }
-      });
-    },
-    onError: function onError() {
-      assert.fail("onError should not be called");
-    }
-  });
-};
-
-exports["test web page associated credentials"] = function(assert, done) {
-  store({
-    url: "http://bar.foo.com/authentication/?login",
-    formSubmitURL: "http://login.foo.com/authenticate.cgi",
-    username: "user",
-    password: "pass",
-    usernameField: "user-f",
-    passwordField: "pass-f",
-    onComplete: function onComplete() {
-      search({
-        username: "user",
-        password: "pass",
-        url: "http://bar.foo.com",
-        formSubmitURL: "http://login.foo.com",
-        onComplete: function onComplete([credential]) {
-          assert.equal(credential.url, "http://bar.foo.com", "url matches");
-          assert.equal(credential.username, "user", "username matches");
-          assert.equal(credential.password, "pass", "password matches");
-          assert.equal(credential.realm, null, "realm is null");
-          assert.equal(credential.formSubmitURL, "http://login.foo.com",
-                       "formSubmitURL matches");
-          assert.equal(credential.usernameField, "user-f",
-                       "usernameField is matches");
-          assert.equal(credential.passwordField, "pass-f",
-                       "passwordField matches");
-
-          remove({
-            url: credential.url,
-            formSubmitURL: credential.formSubmitURL,
-            username: credential.username,
-            password: credential.password,
-            usernameField: credential.usernameField,
-            passwordField: credential.passwordField,
-
-            onComplete: function onComplete() {
-              assert.pass("credential is removed");
-              done();
-            },
-            onError: function onError(e) {
-              assert.fail("onError should not be called");
-            }
-          });
-        },
-        onError: function onError() {
-          assert.fail("onError should not be called");
-        }
-      });
-    },
-    onError: function onError() {
-      assert.fail("onError should not be called");
-    }
-  });
-};
-
-exports["test site authentication credentials"] = function(assert, done) {
-  store({
-    url: "http://authentication.com",
-    username: "U",
-    password: "P",
-    realm: "R",
-    onComplete: function onComplete() {
-      search({
-        url: "http://authentication.com",
-        username: "U",
-        password: "P",
-        realm: "R",
-        onComplete: function onComplete([credential]) {
-          assert.equal(credential.url,"http://authentication.com",
-                       "url matches");
-          assert.equal(credential.username, "U", "username matches");
-          assert.equal(credential.password, "P", "password matches");
-          assert.equal(credential.realm, "R", "realm matches");
-          assert.equal(credential.formSubmitURL, null, "formSubmitURL is null");
-          assert.equal(credential.usernameField, "", "usernameField is empty");
-          assert.equal(credential.passwordField, "", "passwordField is empty");
-
-          remove({
-            url: credential.url,
-            username: credential.username,
-            password: credential.password,
-            realm: credential.realm,
-            onComplete: function onComplete() {
-              assert.pass("credential is removed");
-              done();
-            },
-            onError: function onError() {
-              assert.fail("onError should not be called");
-            }
-          });
-        },
-        onError: function onError() {
-          assert.fail("onError should not be called");
-        }
-      });
-    },
-    onError: function onError() {
-      assert.fail("onError should not be called");
-    }
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-path.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.exports = require("./path/test-path.js");
deleted file mode 100644
--- a/addon-sdk/source/test/test-plain-text-console.js
+++ /dev/null
@@ -1,278 +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 prefs = require("sdk/preferences/service");
-const { id, name } = require("sdk/self");
-const { Cc, Cu, Ci } = require("chrome");
-const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
-                     getService(Ci.mozIJSSubScriptLoader);
-
-const ADDON_LOG_LEVEL_PREF = "extensions." + id + ".sdk.console.logLevel";
-const SDK_LOG_LEVEL_PREF = "extensions.sdk.console.logLevel";
-
-const HAS_ORIGINAL_ADDON_LOG_LEVEL = prefs.has(ADDON_LOG_LEVEL_PREF);
-const ORIGINAL_ADDON_LOG_LEVEL = prefs.get(ADDON_LOG_LEVEL_PREF);
-const HAS_ORIGINAL_SDK_LOG_LEVEL = prefs.has(SDK_LOG_LEVEL_PREF);
-const ORIGINAL_SDK_LOG_LEVEL = prefs.get(SDK_LOG_LEVEL_PREF);
-
-exports.testPlainTextConsole = function(assert) {
-  let prints = [];
-  let tbLines;
-  function print(message) {
-    prints.push(message);
-  }
-  function lastPrint() {
-    let last = prints.slice(-1)[0];
-    prints = [];
-    return last;
-  }
-
-  prefs.set(SDK_LOG_LEVEL_PREF, "all");
-  prefs.reset(ADDON_LOG_LEVEL_PREF);
-
-  let Console = require("sdk/console/plain-text").PlainTextConsole;
-  let con = new Console(print);
-
-  assert.ok("PlainTextConsole instantiates");
-
-  con.log('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.log: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.log() must work.");
-
-  con.info('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.info: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.info() must work.");
-
-  con.warn('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.warn: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.warn() must work.");
-
-  con.error('testing', 1, [2, 3, 4]);
-  assert.equal(prints[0], "console.error: " + name + ": \n",
-                   "PlainTextConsole.error() must work.");
-  assert.equal(prints[1], "  testing\n")
-  assert.equal(prints[2], "  1\n")
-  assert.equal(prints[3], "Array\n    - 0 = 2\n    - 1 = 3\n    - 2 = 4\n    - length = 3\n");
-  prints = [];
-
-  con.debug('testing', 1, [2, 3, 4]);
-  assert.equal(prints[0], "console.debug: " + name + ": \n",
-                   "PlainTextConsole.debug() must work.");
-  assert.equal(prints[1], "  testing\n")
-  assert.equal(prints[2], "  1\n")
-  assert.equal(prints[3], "Array\n    - 0 = 2\n    - 1 = 3\n    - 2 = 4\n    - length = 3\n");
-  prints = [];
-
-  con.log('testing', undefined);
-  assert.equal(lastPrint(), "console.log: " + name + ": testing undefined\n",
-                   "PlainTextConsole.log() must stringify undefined.");
-
-  con.log('testing', null);
-  assert.equal(lastPrint(), "console.log: " + name + ": testing null\n",
-                   "PlainTextConsole.log() must stringify null.");
-
-  // TODO: Fix console.jsm to detect custom toString.
-  con.log("testing", { toString: () => "obj.toString()" });
-  assert.equal(lastPrint(), "console.log: " + name + ": testing {}\n",
-                   "PlainTextConsole.log() doesn't printify custom toString.");
-
-  con.log("testing", { toString: function() { throw "fail!"; } });
-  assert.equal(lastPrint(), "console.log: " + name + ": testing {}\n",
-                   "PlainTextConsole.log() must stringify custom bad toString.");
-
-  con.exception(new Error("blah"));
-
-  assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct");
-  tbLines = prints[1].split("\n");
-  assert.equal(tbLines[0], "  Message: Error: blah", "tbLines[0] is correct");
-  assert.equal(tbLines[1], "  Stack:", "tbLines[1] is correct");
-  let lineNumber = prints[1].match(module.uri + ":(\\d+)")[1];
-  assert.equal(lineNumber, "84", "line number is correct")
-  assert.ok(prints[1].indexOf(module.uri + ":84") !== -1, "line number is correct");
-  prints = []
-
-  try {
-    loadSubScript("invalid-url", {});
-    assert.fail("successed in calling loadSubScript with invalid-url");
-  }
-  catch(e) {
-    con.exception(e);
-  }
-  assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct");
-  assert.equal(prints[1], "  Error creating URI (invalid URL scheme?)\n", "prints[1] is correct");
-  prints = [];
-
-  con.trace();
-  tbLines = prints[0].split("\n");
-  assert.equal(tbLines[0], "console.trace: " + name + ": ", "contains correct console.trace");
-  assert.ok(tbLines[1].indexOf("_ain-text-console.js 106") == 0);
-  prints = [];
-
-  // Whether or not console methods should print at the various log levels,
-  // structured as a hash of levels, each of which contains a hash of methods,
-  // each of whose value is whether or not it should print, i.e.:
-  // { [level]: { [method]: [prints?], ... }, ... }.
-  let levels = {
-    all:   { debug: true,  log: true,  info: true,  warn: true,  error: true  },
-    debug: { debug: true,  log: true,  info: true,  warn: true,  error: true  },
-    info:  { debug: false, log: true,  info: true,  warn: true,  error: true  },
-    warn:  { debug: false, log: false, info: false, warn: true,  error: true  },
-    error: { debug: false, log: false, info: false, warn: false, error: true  },
-    off:   { debug: false, log: false, info: false, warn: false, error: false },
-  };
-
-  // The messages we use to test the various methods, as a hash of methods.
-  let messages = {
-    debug: "console.debug: " + name + ": \n  \n",
-    log: "console.log: " + name + ": \n",
-    info: "console.info: " + name + ": \n",
-    warn: "console.warn: " + name + ": \n",
-    error: "console.error: " + name + ": \n  \n",
-  };
-
-  for (let level in levels) {
-    let methods = levels[level];
-    for (let method in methods) {
-      // We have to reset the log level pref each time we run the test
-      // because the test runner relies on the console to print test output,
-      // and test results would not get printed to the console for some
-      // values of the pref.
-      prefs.set(SDK_LOG_LEVEL_PREF, level);
-      con[method]("");
-      prefs.set(SDK_LOG_LEVEL_PREF, "all");
-      assert.equal(prints.join(""),
-                       (methods[method] ? messages[method] : ""),
-                       "at log level '" + level + "', " + method + "() " +
-                       (methods[method] ? "prints" : "doesn't print"));
-      prints = [];
-    }
-  }
-
-  prefs.set(SDK_LOG_LEVEL_PREF, "off");
-  prefs.set(ADDON_LOG_LEVEL_PREF, "all");
-  con.debug("");
-  assert.equal(prints.join(""), messages["debug"],
-                   "addon log level 'all' overrides SDK log level 'off'");
-  prints = [];
-
-  prefs.set(SDK_LOG_LEVEL_PREF, "all");
-  prefs.set(ADDON_LOG_LEVEL_PREF, "off");
-  con.error("");
-  prefs.reset(ADDON_LOG_LEVEL_PREF);
-  assert.equal(lastPrint(), null,
-                   "addon log level 'off' overrides SDK log level 'all'");
-
-  restorePrefs();
-};
-
-exports.testPlainTextConsoleBoundMethods = function(assert) {
-  let prints = [];
-  let tbLines;
-  function print(message) {
-    prints.push(message);
-  }
-  function lastPrint() {
-    let last = prints.slice(-1)[0];
-    prints = [];
-    return last;
-  }
-
-  prefs.set(SDK_LOG_LEVEL_PREF, "all");
-  prefs.reset(ADDON_LOG_LEVEL_PREF);
-
-  let Console = require("sdk/console/plain-text").PlainTextConsole;
-  let { log, info, warn, error, debug, exception, trace } = new Console(print);
-
-  assert.ok("PlainTextConsole instantiates");
-
-  log('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.log: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.log() must work.");
-
-  info('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.info: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.info() must work.");
-
-  warn('testing', 1, [2, 3, 4]);
-  assert.equal(lastPrint(), "console.warn: " + name + ": testing 1 Array [2,3,4]\n",
-                   "PlainTextConsole.warn() must work.");
-
-  error('testing', 1, [2, 3, 4]);
-  assert.equal(prints[0], "console.error: " + name + ": \n",
-                   "PlainTextConsole.error() must work.");
-  assert.equal(prints[1], "  testing\n")
-  assert.equal(prints[2], "  1\n")
-  assert.equal(prints[3], "Array\n    - 0 = 2\n    - 1 = 3\n    - 2 = 4\n    - length = 3\n");
-  prints = [];
-
-  debug('testing', 1, [2, 3, 4]);
-  assert.equal(prints[0], "console.debug: " + name + ": \n",
-                   "PlainTextConsole.debug() must work.");
-  assert.equal(prints[1], "  testing\n", "prints[1] is correct");
-  assert.equal(prints[2], "  1\n", "prints[2] is correct");
-  assert.equal(prints[3],
-               "Array\n    - 0 = 2\n    - 1 = 3\n    - 2 = 4\n    - length = 3\n",
-               "prints[3] is correct");
-  prints = [];
-
-  exception(new Error("blah"));
-
-  assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct");
-  tbLines = prints[1].split("\n");
-  assert.equal(tbLines[0], "  Message: Error: blah", "tbLines[0] is correct");
-  assert.equal(tbLines[1], "  Stack:", "tbLines[1] is correct");
-  assert.ok(prints[1].indexOf(module.uri + ":219") !== -1, "correct line number");
-  prints = []
-
-  trace();
-  tbLines = prints[0].split("\n");
-  assert.equal(tbLines[0], "console.trace: " + name + ": ", "console.trace is correct");
-  assert.ok(tbLines[1].indexOf("_ain-text-console.js 228") === 0, "correct line number");
-  prints = [];
-
-  restorePrefs();
-};
-
-exports.testConsoleInnerID = function(assert) {
-  let Console = require("sdk/console/plain-text").PlainTextConsole;
-  let { log, info, warn, error, debug, exception, trace } = new Console(function() {}, "test ID");
-
-  prefs.set(SDK_LOG_LEVEL_PREF, "all");
-
-  let messages = [];
-  function onMessage({ subject }) {
-    let message = subject.wrappedJSObject;
-    messages.push({ msg: message.arguments[0], type: message.level, innerID: message.innerID });
-  }
-
-  const system = require("sdk/system/events");
-  system.on("console-api-log-event", onMessage);
-
-  log("Test log");
-  warn("Test warning");
-  error("Test error");
-
-  assert.equal(messages.length, 3, "Should see 3 log events");
-  assert.deepEqual(messages[0], { msg: "Test log", type: "log", innerID: "test ID" }, "Should see the right event");
-  assert.deepEqual(messages[1], { msg: "Test warning", type: "warn", innerID: "test ID" }, "Should see the right event");
-  assert.deepEqual(messages[2], { msg: "Test error", type: "error", innerID: "test ID" }, "Should see the right event");
-
-  system.off("console-api-log-event", onMessage);
-
-  restorePrefs();
-};
-
-function restorePrefs() {
-  if (HAS_ORIGINAL_ADDON_LOG_LEVEL)
-    prefs.set(ADDON_LOG_LEVEL_PREF, ORIGINAL_ADDON_LOG_LEVEL);
-  else
-    prefs.reset(ADDON_LOG_LEVEL_PREF);
-
-  if (HAS_ORIGINAL_SDK_LOG_LEVEL)
-    prefs.set(SDK_LOG_LEVEL_PREF, ORIGINAL_SDK_LOG_LEVEL);
-  else
-    prefs.reset(SDK_LOG_LEVEL_PREF);
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-preferences-service.js
+++ /dev/null
@@ -1,155 +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 prefs = require("sdk/preferences/service");
-const Branch = prefs.Branch;
-const BundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
-
-const specialChars = "!@#$%^&*()_-=+[]{}~`\'\"<>,./?;:";
-
-exports.testReset = function(assert) {
-  prefs.reset("test_reset_pref");
-  assert.equal(prefs.has("test_reset_pref"), false);
-  assert.equal(prefs.isSet("test_reset_pref"), false);
-  prefs.set("test_reset_pref", 5);
-  assert.equal(prefs.has("test_reset_pref"), true);
-  assert.equal(prefs.isSet("test_reset_pref"), true);
-  assert.equal(prefs.keys("test_reset_pref").toString(), "test_reset_pref");
-};
-
-exports.testGetAndSet = function(assert) {
-  let svc = Cc["@mozilla.org/preferences-service;1"].
-            getService(Ci.nsIPrefService).
-            getBranch(null);
-  svc.setCharPref("test_set_get_pref", "a normal string");
-  assert.equal(prefs.get("test_set_get_pref"), "a normal string",
-                   "preferences-service should read from " +
-                   "application-wide preferences service");
-
-  // test getting a pref that does not exist,
-  // and where we provide no default
-  assert.equal(
-      prefs.get("test_dne_get_pref", "default"),
-      "default",
-      "default was used for a pref that does not exist");
-  assert.equal(
-      prefs.get("test_dne_get_pref"),
-      undefined,
-      "undefined was returned for a pref that does not exist with no default");
-
-  prefs.set("test_set_get_pref.integer", 1);
-  assert.equal(prefs.get("test_set_get_pref.integer"), 1,
-                   "set/get integer preference should work");
-
-  assert.equal(
-      prefs.keys("test_set_get_pref").sort().toString(),
-      ["test_set_get_pref.integer","test_set_get_pref"].sort().toString(),
-      "the key list is correct");
-
-  prefs.set("test_set_get_number_pref", 42);
-  assert.throws(
-    () => prefs.set("test_set_get_number_pref", 3.14159),
-    /cannot store non-integer number: 3.14159/,
-    "setting a float preference should raise an error"
-  );
-  assert.equal(prefs.get("test_set_get_number_pref"),
-               42,
-               "bad-type write attempt should not overwrite");
-
-  // 0x80000000 (bad), 0x7fffffff (ok), -0x80000000 (ok), -0x80000001 (bad)
-  assert.throws(
-    () => prefs.set("test_set_get_number_pref", 0x80000000),
-    /32\-bit/,
-    "setting an int pref above 2^31-1 shouldn't work"
-  );
-
-  assert.equal(prefs.get("test_set_get_number_pref"), 42,
-                   "out-of-range write attempt should not overwrite 1");
-
-  prefs.set("test_set_get_number_pref", 0x7fffffff);
-  assert.equal(prefs.get("test_set_get_number_pref"),
-               0x7fffffff,
-               "in-range write attempt should work 1");
-
-  prefs.set("test_set_get_number_pref", -0x80000000);
-  assert.equal(prefs.get("test_set_get_number_pref"),
-               -0x80000000,
-               "in-range write attempt should work 2");
-  assert.throws(
-    () => prefs.set("test_set_get_number_pref", -0x80000001),
-    /32\-bit/,
-    "setting an int pref below -(2^31) shouldn't work"
-  );
-  assert.equal(prefs.get("test_set_get_number_pref"), -0x80000000,
-                   "out-of-range write attempt should not overwrite 2");
-
-
-  prefs.set("test_set_get_pref.string", "foo");
-  assert.equal(prefs.get("test_set_get_pref.string"), "foo",
-                   "set/get string preference should work");
-
-  prefs.set("test_set_get_pref.boolean", true);
-  assert.equal(prefs.get("test_set_get_pref.boolean"), true,
-                   "set/get boolean preference should work");
-
-  prefs.set("test_set_get_unicode_pref", String.fromCharCode(960));
-  assert.equal(prefs.get("test_set_get_unicode_pref"),
-                   String.fromCharCode(960),
-                   "set/get unicode preference should work");
-
-  [ null, [], undefined ].forEach((value) => {
-    assert.throws(
-      () => prefs.set("test_set_pref", value),
-      new RegExp("can't set pref test_set_pref to value '" + value + "'; " +
-       "it isn't a string, number, or boolean", "i"),
-      "Setting a pref to " + uneval(value) + " should raise error"
-    );
-  });
-};
-
-exports.testPrefClass = function(assert) {
-  var branch = Branch("test_foo");
-
-  assert.equal(branch.test, undefined, "test_foo.test is undefined");
-  branch.test = true;
-  assert.equal(branch.test, true, "test_foo.test is true");
-  delete branch.test;
-  assert.equal(branch.test, undefined, "test_foo.test is undefined");
-};
-
-exports.testGetSetLocalized = function(assert) {
-  let prefName = "general.useragent.locale";
-
-  // Ensure that "general.useragent.locale" is a 'localized' pref
-  let bundleURL = "chrome://global/locale/intl.properties";
-  prefs.setLocalized(prefName, bundleURL);
-
-  // Fetch the expected value directly from the property file
-  let expectedValue = BundleService.createBundle(bundleURL).
-    GetStringFromName(prefName).
-    toLowerCase();
-
-  assert.equal(prefs.getLocalized(prefName).toLowerCase(),
-                   expectedValue,
-                   "get localized preference");
-
-  // Undo our modification
-  prefs.reset(prefName);
-}
-
-// TEST: setting and getting preferences with special characters work
-exports.testSpecialChars = function(assert) {
-  let chars = specialChars.split('');
-  const ROOT = "test.";
-
-  chars.forEach((char) => {
-    let rand = Math.random() + "";
-    prefs.set(ROOT + char, rand);
-    assert.equal(prefs.get(ROOT+char), rand, "setting pref with a name that is a special char, " + char + ", worked!");
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-preferences-target.js
+++ /dev/null
@@ -1,42 +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 { PrefsTarget } = require('sdk/preferences/event-target');
-const { get, set, reset } = require('sdk/preferences/service');
-const { Loader } = require('sdk/test/loader');
-const { setTimeout } = require('sdk/timers');
-
-const root = PrefsTarget();
-
-exports.testPrefsTarget = function(assert, done) {
-  let loader = Loader(module);
-  let pt = loader.require('sdk/preferences/event-target').PrefsTarget({});
-  let name = 'test';
-
-  assert.equal(get(name, ''), '', 'test pref is blank');
-
-  pt.once(name, function() {
-    assert.equal(pt.prefs[name], 2, 'test pref is 2');
-
-    pt.once(name, function() {
-      assert.fail('should not have heard a pref change');
-    });
-    loader.unload();
-    root.once(name, function() {
-      assert.pass('test pref was changed');
-      reset(name);
-
-      // NOTE: using setTimeout to make sure that the other listener had
-      //       a chance to fail
-      // end test
-      setTimeout(done);
-    });
-    set(name, 3);
-  });
-
-  pt.prefs[name] = 2;
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-private-browsing.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Ci, Cu } = require('chrome');
-const { safeMerge } = require('sdk/util/object');
-const windows = require('sdk/windows').browserWindows;
-const tabs = require('sdk/tabs');
-const winUtils = require('sdk/window/utils');
-const { isWindowPrivate } = winUtils;
-const { isPrivateBrowsingSupported } = require('sdk/self');
-const { is } = require('sdk/system/xul-app');
-const { isPrivate } = require('sdk/private-browsing');
-const { LoaderWithHookedConsole } = require("sdk/test/loader");
-const { getMode, isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
-const { pb } = require('./private-browsing/helper');
-const prefs = require('sdk/preferences/service');
-
-const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-
-const kAutoStartPref = "browser.privatebrowsing.autostart";
-
-if (isWindowPBSupported) {
-  safeMerge(module.exports, require('./private-browsing/windows'));
-
-  exports.testPWOnlyOnFirefox = function(assert) {
-    assert.ok(is("Firefox"), "isWindowPBSupported is only true on Firefox");
-  }
-}
-// only on Fennec
-else if (isTabPBSupported) {
-  safeMerge(module.exports, require('./private-browsing/tabs'));
-
-  exports.testPTOnlyOnFennec = function(assert) {
-    assert.ok(is("Fennec"), "isTabPBSupported is only true on Fennec");
-  }
-}
-
-exports.testIsPrivateDefaults = function(assert) {
-  assert.equal(isPrivate(), false, 'undefined is not private');
-  assert.equal(isPrivate('test'), false, 'strings are not private');
-  assert.equal(isPrivate({}), false, 'random objects are not private');
-  assert.equal(isPrivate(4), false, 'numbers are not private');
-  assert.equal(isPrivate(/abc/), false, 'regex are not private');
-  assert.equal(isPrivate(function() {}), false, 'functions are not private');
-};
-
-exports.testWindowDefaults = function(assert) {
-  // Ensure that browserWindow still works while being deprecated
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let windows = loader.require("sdk/windows").browserWindows;
-  assert.equal(windows.activeWindow.isPrivateBrowsing, undefined,
-              'window.isPrivateBrowsing is undefined');
-  assert.equal(undefined, messages[0],
-               'isPrivateBrowsing is deprecated');
-
-  let chromeWin = winUtils.getMostRecentBrowserWindow();
-  assert.equal(getMode(chromeWin), false);
-  assert.equal(isWindowPrivate(chromeWin), false);
-};
-
-exports.testIsPrivateBrowsingFalseDefault = function(assert) {
-  assert.equal(isPrivateBrowsingSupported, false,
-  	               'isPrivateBrowsingSupported property is false by default');
-};
-
-exports.testNSIPrivateBrowsingChannel = function(assert) {
-  let channel = NetUtil.newChannel({
-    uri: "about:blank",
-    loadUsingSystemPrincipal: true
-  });
-  channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
-  assert.equal(isPrivate(channel), false, 'isPrivate detects non-private channels');
-  channel.setPrivate(true);
-  assert.ok(isPrivate(channel), 'isPrivate detects private channels');
-}
-
-exports.testNewGlobalPBService = function(assert) {
-  assert.equal(isPrivate(), false, 'isPrivate() is false by default');
-  prefs.set(kAutoStartPref, true);
-  assert.equal(prefs.get(kAutoStartPref, false), true, kAutoStartPref + ' is true now');
-  assert.equal(isPrivate(), true, 'isPrivate() is true now');
-  prefs.set(kAutoStartPref, false);
-  assert.equal(isPrivate(), false, 'isPrivate() is false again');
-};
-
-require('sdk/test').run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-promise.js
+++ /dev/null
@@ -1,461 +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, Cu, Ci } = require('chrome');
-const { setTimeout } = require('sdk/timers');
-const { prefixURI, name } = require('@loader/options');
-const addonPromiseURI = prefixURI + name + '/lib/sdk/core/promise.js';
-const builtPromiseURI = 'resource://gre/modules/commonjs/sdk/core/promise.js';
-var { Promise, defer, resolve, reject, all, promised } = require('sdk/core/promise');
-
-exports['test all observers are notified'] = function(assert, done) {
-  let expected = 'Taram pam param!';
-  let deferred = defer();
-  let pending = 10, i = 0;
-
-  function resolved(value) {
-    assert.equal(value, expected, 'value resolved as expected: #' + pending);
-    if (!--pending) done();
-  }
-
-  while (i++ < pending) deferred.promise.then(resolved);
-
-  deferred.resolve(expected);
-};
-
-exports['test exceptions dont stop notifications'] = function(assert, done) {
-  let threw = false, boom = Error('Boom!');
-  let deferred = defer();
-
-  let promise2 = deferred.promise.then(function() {
-    threw = true;
-    throw boom;
-  });
-
-  deferred.promise.then(function() {
-    assert.ok(threw, 'observer is called even though previos one threw');
-    promise2.then(function() {
-      assert.fail('should not resolve');
-    }, function(reason) {
-      assert.equal(reason, boom, 'rejects to thrown error');
-      done();
-    });
-  });
-
-  deferred.resolve('go!');
-};
-
-exports['test subsequent resolves are ignored'] = function(assert, done) {
-  let deferred = defer();
-  deferred.resolve(1);
-  deferred.resolve(2);
-  deferred.reject(3);
-
-  deferred.promise.then(function(actual) {
-    assert.equal(actual, 1, 'resolves to first value');
-  }, function() {
-    assert.fail('must not reject');
-  });
-  deferred.promise.then(function(actual) {
-    assert.equal(actual, 1, 'subsequent resolutions are ignored');
-    done();
-  }, function() {
-    assert.fail('must not reject');
-  });
-};
-
-exports['test subsequent rejections are ignored'] = function(assert, done) {
-  let deferred = defer();
-  deferred.reject(1);
-  deferred.resolve(2);
-  deferred.reject(3);
-
-  deferred.promise.then(function(actual) {
-    assert.fail('must not resolve');
-  }, function(actual) {
-    assert.equal(actual, 1, 'must reject to first');
-  });
-  deferred.promise.then(function(actual) {
-    assert.fail('must not resolve');
-  }, function(actual) {
-    assert.equal(actual, 1, 'must reject to first');
-    done();
-  });
-};
-
-exports['test error recovery'] = function(assert, done) {
-  let boom = Error('Boom!');
-  let deferred = defer();
-
-  deferred.promise.then(function() {
-    assert.fail('rejected promise should not resolve');
-  }, function(reason) {
-    assert.equal(reason, boom, 'rejection reason delivered');
-    return 'recovery';
-  }).then(function(value) {
-    assert.equal(value, 'recovery', 'error handled by a handler');
-    done();
-  });
-
-  deferred.reject(boom);
-};
-
-exports['test error recovery with promise'] = function(assert, done) {
-  let deferred = defer();
-
-  deferred.promise.then(function() {
-    assert.fail('must reject');
-  }, function(actual) {
-    assert.equal(actual, 'reason', 'rejected');
-    let deferred = defer();
-    deferred.resolve('recovery');
-    return deferred.promise;
-  }).then(function(actual) {
-    assert.equal(actual, 'recovery', 'recorvered via promise');
-    let deferred = defer();
-    deferred.reject('error');
-    return deferred.promise;
-  }).catch(function(actual) {
-    assert.equal(actual, 'error', 'rejected via promise');
-    let deferred = defer();
-    deferred.reject('end');
-    return deferred.promise;
-  }).catch(function(actual) {
-    assert.equal(actual, 'end', 'rejeced via promise');
-    done();
-  });
-
-  deferred.reject('reason');
-};
-
-exports['test propagation'] = function(assert, done) {
-  let d1 = defer(), d2 = defer(), d3 = defer();
-
-  d1.promise.then(function(actual) {
-    assert.equal(actual, 'expected', 'resolves to expected value');
-    done();
-  });
-
-  d1.resolve(d2.promise);
-  d2.resolve(d3.promise);
-  d3.resolve('expected');
-};
-
-exports['test chaining'] = function(assert, done) {
-  let boom = Error('boom'), brax = Error('braxXXx');
-  let deferred = defer();
-
-  deferred.promise.then().then().then(function(actual) {
-    assert.equal(actual, 2, 'value propagates unchanged');
-    return actual + 2;
-  }).catch(function(reason) {
-    assert.fail('should not reject');
-  }).then(function(actual) {
-    assert.equal(actual, 4, 'value propagates through if not handled');
-    throw boom;
-  }).then(function(actual) {
-    assert.fail('exception must reject promise');
-  }).then().catch(function(actual) {
-    assert.equal(actual, boom, 'reason propagates unchanged');
-    throw brax;
-  }).then().catch(function(actual) {
-    assert.equal(actual, brax, 'reason changed becase of exception');
-    return 'recovery';
-  }).then(function(actual) {
-    assert.equal(actual, 'recovery', 'recovered from error');
-    done();
-  });
-
-  deferred.resolve(2);
-};
-
-exports['test reject'] = function(assert, done) {
-  let expected = Error('boom');
-
-  reject(expected).then(function() {
-    assert.fail('should reject');
-  }, function(actual) {
-    assert.equal(actual, expected, 'rejected with expected reason');
-  }).then(done, assert.fail);
-};
-
-exports['test resolve to rejected'] = function(assert, done) {
-  let expected = Error('boom');
-  let deferred = defer();
-
-  deferred.promise.then(function() {
-    assert.fail('should reject');
-  }, function(actual) {
-    assert.equal(actual, expected, 'rejected with expected failure');
-  }).then(done, assert.fail);
-
-  deferred.resolve(reject(expected));
-};
-
-exports['test resolve'] = function(assert, done) {
-  let expected = 'value';
-  resolve(expected).then(function(actual) {
-    assert.equal(actual, expected, 'resolved as expected');
-  }).catch(assert.fail).then(done);
-};
-
-exports['test promised with normal args'] = function(assert, done) {
-  let sum = promised((x, y) => x + y );
-
-  sum(7, 8).then(function(actual) {
-    assert.equal(actual, 7 + 8, 'resolves as expected');
-  }).catch(assert.fail).then(done);
-};
-
-exports['test promised with promise args'] = function(assert, done) {
-  let sum = promised((x, y) => x + y );
-  let deferred = defer();
-
-  sum(11, deferred.promise).then(function(actual) {
-    assert.equal(actual, 11 + 24, 'resolved as expected');
-  }).catch(assert.fail).then(done);
-
-  deferred.resolve(24);
-};
-
-exports['test promised error handling'] = function(assert, done) {
-  let expected = Error('boom');
-  let f = promised(function() {
-    throw expected;
-  });
-
-  f().then(function() {
-    assert.fail('should reject');
-  }, function(actual) {
-    assert.equal(actual, expected, 'rejected as expected');
-  }).catch(assert.fail).then(done);
-};
-
-exports['test errors in promise resolution handlers are propagated'] = function(assert, done) {
-  var expected = Error('Boom');
-  var { promise, resolve } = defer();
-
-  promise.then(function() {
-    throw expected;
-  }).then(function() {
-    return undefined;
-  }).catch(function(actual) {
-    assert.equal(actual, expected, 'rejected as expected');
-  }).then(done, assert.fail);
-
-  resolve({});
-};
-
-exports['test return promise form promised'] = function(assert, done) {
-  let f = promised(function() {
-    return resolve(17);
-  });
-
-  f().then(function(actual) {
-    assert.equal(actual, 17, 'resolves to a promise resolution');
-  }).catch(assert.fail).then(done);
-};
-
-exports['test promised returning failure'] = function(assert, done) {
-  let expected = Error('boom');
-  let f = promised(function() {
-    return reject(expected);
-  });
-
-  f().then(function() {
-    assert.fail('must reject');
-  }, function(actual) {
-    assert.equal(actual, expected, 'rejects with expected reason');
-  }).catch(assert.fail).then(done);
-};
-
-/*
- * Changed for compliance in Bug 881047, promises are now always async
- */
-exports['test promises are always async'] = function (assert, done) {
-  let runs = 0;
-  resolve(1)
-    .then(val => ++runs)
-    .catch(assert.fail).then(done);
-  assert.equal(runs, 0, 'resolutions are called in following tick');
-};
-
-/*
- * Changed for compliance in Bug 881047, promised's are now non greedy
- */
-exports['test promised are not greedy'] = function(assert, done) {
-  let runs = 0;
-  promised(() => ++runs)()
-    .catch(assert.fail).then(done);
-  assert.equal(runs, 0, 'promised does not run task right away');
-};
-
-exports['test promised does not flatten arrays'] = function(assert, done) {
-  let p = promised(function(empty, one, two, nested) {
-    assert.equal(empty.length, 0, "first argument is empty");
-    assert.deepEqual(one, ['one'], "second has one");
-    assert.deepEqual(two, ['two', 'more'], "third has two more");
-    assert.deepEqual(nested, [[]], "forth is properly nested");
-    done();
-  });
-
-  p([], ['one'], ['two', 'more'], [[]]);
-};
-
-exports['test arrays should not flatten'] = function(assert, done) {
-  let a = defer();
-  let b = defer();
-
-  let combine = promised(function(str, arr) {
-    assert.equal(str, 'Hello', 'Array was not flattened');
-    assert.deepEqual(arr, [ 'my', 'friend' ]);
-  });
-
-  combine(a.promise, b.promise).catch(assert.fail).then(done);
-
-
-  a.resolve('Hello');
-  b.resolve([ 'my', 'friend' ]);
-};
-
-exports['test `all` for all promises'] = function (assert, done) {
-  all([
-    resolve(5), resolve(7), resolve(10)
-  ]).then(function (val) {
-    assert.equal(
-      val[0] === 5 &&
-      val[1] === 7 &&
-      val[2] === 10
-    , true, 'return value contains resolved promises values');
-    done();
-  }, function () {
-    assert.fail('should not call reject function');
-  });
-};
-
-exports['test `all` aborts upon first reject'] = function (assert, done) {
-  all([
-    resolve(5), reject('error'), delayedResolve()
-  ]).then(function (val) {
-    assert.fail('Successful resolve function should not be called');
-  }, function (reason) {
-    assert.equal(reason, 'error', 'should reject the `all` promise');
-    done();
-  });
-
-  function delayedResolve () {
-    let deferred = defer();
-    setTimeout(deferred.resolve, 50);
-    return deferred.promise;
-  }
-};
-
-exports['test `all` with array containing non-promise'] = function (assert, done) {
-  all([
-    resolve(5), resolve(10), 925
-  ]).then(function (val) {
-    assert.equal(val[2], 925, 'non-promises should pass-through value');
-    done();
-  }, function () {
-    assert.fail('should not be rejected');
-  });
-};
-
-exports['test `all` should resolve with an empty array'] = function (assert, done) {
-  all([]).then(function (val) {
-    assert.equal(Array.isArray(val), true, 'should return array in resolved');
-    assert.equal(val.length, 0, 'array should be empty in resolved');
-    done();
-  }, function () {
-    assert.fail('should not be rejected');
-  });
-};
-
-exports['test `all` with multiple rejected'] = function (assert, done) {
-  all([
-    reject('error1'), reject('error2'), reject('error3')
-  ]).then(function (value) {
-    assert.fail('should not be successful');
-  }, function (reason) {
-    assert.equal(reason, 'error1', 'should reject on first promise reject');
-    done();
-  });
-};
-
-exports['test Promise constructor resolve'] = function (assert, done) {
-  var isAsync = true;
-  new Promise(function (resolve, reject) {
-    resolve(5);
-  }).then(x => {
-    isAsync = false;
-    assert.equal(x, 5, 'Promise constructor resolves correctly');
-  }).catch(assert.fail).then(done);
-  assert.ok(isAsync, 'Promise constructor runs async');
-};
-
-exports['test Promise constructor reject'] = function (assert, done) {
-  new Promise(function (resolve, reject) {
-    reject(new Error('deferred4life'));
-  }).then(assert.fail, (err) => {
-    assert.equal(err.message, 'deferred4life', 'Promise constructor rejects correctly');
-  }).catch(assert.fail).then(done);
-};
-
-exports['test JSM Load and API'] = function (assert, done) {
-  // Use addon URL when loading from cfx/local:
-  // resource://90111c90-c31e-4dc7-ac35-b65947434435-at-jetpack/addon-sdk/lib/sdk/core/promise.js
-  // Use built URL when testing on try, etc.
-  // resource://gre/modules/commonjs/sdk/core/promise.js
-  try {
-    var { Promise } = Cu.import(addonPromiseURI, {});
-  } catch (e) {
-    var { Promise } = Cu.import(builtPromiseURI, {});
-  }
-  testEnvironment(Promise, assert, done, 'JSM');
-};
-
-exports['test mozIJSSubScriptLoader exporting'] = function (assert, done) {
-  let { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
-  let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
-  let Promise = new Cu.Sandbox(systemPrincipal);
-  let loader = Cc['@mozilla.org/moz/jssubscript-loader;1']
-                 .getService(Ci.mozIJSSubScriptLoader);
-
-  // Use addon URL when loading from cfx/local:
-  // resource://90111c90-c31e-4dc7-ac35-b65947434435-at-jetpack/addon-sdk/lib/sdk/core/promise.js
-  // Use built URL when testing on try, etc.
-  // resource://gre/modules/commonjs/sdk/core/promise.js
-  try {
-    loader.loadSubScript(addonPromiseURI, Promise);
-  } catch (e) {
-    loader.loadSubScript(builtPromiseURI, Promise);
-  }
-
-  testEnvironment(Promise, assert, done, 'mozIJSSubScript');
-};
-
-function testEnvironment ({all, resolve, defer, reject, promised}, assert, done, type) {
-  all([resolve(5), resolve(10), 925]).then(val => {
-    assert.equal(val[0], 5, 'promise#all works ' + type);
-    assert.equal(val[1], 10, 'promise#all works ' + type);
-    assert.equal(val[2], 925, 'promise#all works ' + type);
-    return resolve(1000);
-  }).then(value => {
-    assert.equal(value, 1000, 'promise#resolve works ' + type);
-    return reject('testing reject');
-  }).catch(reason => {
-    assert.equal(reason, 'testing reject', 'promise#reject works ' + type);
-    let deferred = defer();
-    setTimeout(() => deferred.resolve('\\m/'), 10);
-    return deferred.promise;
-  }).then(value => {
-    assert.equal(value, '\\m/', 'promise#defer works ' + type);
-    return promised(x => x * x)(5);
-  }).then(value => {
-    assert.equal(value, 25, 'promise#promised works ' + type);
-  }).then(done, assert.fail);
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-querystring.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.exports = require("./querystring/test-querystring.js");
deleted file mode 100644
--- a/addon-sdk/source/test/test-reference.js
+++ /dev/null
@@ -1,99 +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 { isWeak, WeakReference } = require("sdk/core/reference");
-const { Class } = require("sdk/core/heritage");
-
-exports["test non WeakReferences"] = assert => {
-  assert.equal(isWeak({}), false,
-               "regular objects aren't weak");
-
-  assert.equal(isWeak([]), false,
-               "arrays aren't weak");
-};
-
-exports["test a WeakReference"] = assert => {
-  assert.equal(isWeak(new WeakReference()), true,
-               "instances of WeakReferences are weak");
-};
-
-exports["test a subclass"] = assert => {
-  const SubType = Class({
-    extends: WeakReference,
-    foo: function() {
-    }
-  });
-
-  const x = new SubType();
-  assert.equal(isWeak(x), true,
-               "subtypes of WeakReferences are weak");
-
-  const SubSubType = Class({
-    extends: SubType
-  });
-
-  const y = new SubSubType();
-  assert.equal(isWeak(y), true,
-               "sub subtypes of WeakReferences are weak");
-};
-
-exports["test a mixin"] = assert => {
-  const Mixer = Class({
-    implements: [WeakReference]
-  });
-
-  assert.equal(isWeak(new Mixer()), true,
-               "instances with mixed WeakReference are weak");
-
-  const Mux = Class({});
-  const MixMux = Class({
-    extends: Mux,
-    implements: [WeakReference]
-  });
-
-  assert.equal(isWeak(new MixMux()), true,
-               "instances with mixed WeakReference that " +
-               "inheret from other are weak");
-
-
-  const Base = Class({});
-  const ReMix = Class({
-    extends: Base,
-    implements: [MixMux]
-  });
-
-  assert.equal(isWeak(new ReMix()), true,
-               "subtime of mix is still weak");
-};
-
-exports["test an override"] = assert => {
-  const SubType = Class({ extends: WeakReference });
-  isWeak.define(SubType, x => false);
-
-  assert.equal(isWeak(new SubType()), false,
-               "behavior of isWeak can still be overrided on subtype");
-
-  const Mixer = Class({ implements: [WeakReference] });
-  const SubMixer = Class({ extends: Mixer });
-  isWeak.define(SubMixer, x => false);
-  assert.equal(isWeak(new SubMixer()), false,
-               "behavior of isWeak can still be overrided on mixed type");
-};
-
-exports["test an opt-in"] = assert => {
-  var BaseType = Class({});
-  var SubType = Class({ extends: BaseType });
-
-  isWeak.define(SubType, x => true);
-  assert.equal(isWeak(new SubType()), true,
-               "isWeak can be just implemented");
-
-  var x = {};
-  isWeak.implement(x, x => true);
-  assert.equal(isWeak(x), true,
-               "isWeak can be implemented per instance");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-request.js
+++ /dev/null
@@ -1,548 +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 { Request } = require("sdk/request");
-const { pathFor } = require("sdk/system");
-const file = require("sdk/io/file");
-const { URL } = require("sdk/url");
-const { extend } = require("sdk/util/object");
-const { Loader } = require("sdk/test/loader");
-const options = require("sdk/test/options");
-
-const loader = Loader(module);
-const httpd = loader.require("./lib/httpd");
-if (options.parseable || options.verbose)
-  loader.sandbox("./lib/httpd").DEBUG = true;
-const { startServerAsync } = httpd;
-
-const { Cc, Ci, Cu } = require("chrome");
-const { Services } = Cu.import("resource://gre/modules/Services.jsm");
-
-// Use the profile directory for the temporary files as that will be deleted
-// when tests are complete
-const basePath = pathFor("ProfD");
-const port = 8099;
-
-
-exports.testOptionsValidator = function(assert) {
-  // First, a simple test to make sure we didn't break normal functionality.
-  assert.throws(function () {
-    Request({
-      url: null
-    });
-  }, /The option "url" is invalid./);
-
-  // Next we'll have a Request that doesn't throw from c'tor, but from a setter.
-  let req = Request({
-    url: "http://playground.zpao.com/jetpack/request/text.php",
-    onComplete: function () {}
-  });
-  assert.throws(function () {
-    req.url = 'www.mozilla.org';
-  }, /The option "url" is invalid/);
-  // The url shouldn't have changed, so check that
-  assert.equal(req.url, "http://playground.zpao.com/jetpack/request/text.php");
-
-  // Test default anonymous parameter value
-  assert.equal(req.anonymous, false);
-  // Test set anonymous parameter value
-  req = Request({
-    url: "http://playground.zpao.com/jetpack/request/text.php",
-    anonymous: true,
-    onComplete: function () {}
-  });
-  assert.equal(req.anonymous, true);
-  // Test wrong value as anonymous parameter value
-  assert.throws(function() {
-    Request({
-      url: "http://playground.zpao.com/jetpack/request/text.php",
-      anonymous: "invalidvalue"
-    });
-  }, /The option "anonymous" must be one of the following types/);
-};
-
-exports.testContentValidator = function(assert, done) {
-  runMultipleURLs(null, assert, done, {
-    url: "data:text/html;charset=utf-8,response",
-    content: { 'key1' : null, 'key2' : 'some value' },
-    onComplete: function(response) {
-      assert.equal(response.text, "response?key1=null&key2=some+value");
-    }
-  });
-};
-
-// This is a request to a file that exists.
-exports.testStatus200 = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-  let content = "Look ma, no hands!\n";
-  let basename = "test-request.txt"
-  let requestURL = "http://localhost:" + port + "/" + basename;
-
-  prepareFile(basename, content);
-
-  var req = Request({
-    url: requestURL,
-    onComplete: function (response) {
-      assert.equal(this, req, "`this` should be request");
-      assert.equal(response.status, 200);
-      assert.equal(response.statusText, "OK");
-      assert.equal(response.headers["Content-Type"], "text/plain");
-      assert.equal(response.text, content);
-      assert.strictEqual(response.url, requestURL);
-      srv.stop(done);
-    }
-  }).get();
-};
-
-// Should return the location to which have been automatically redirected
-exports.testRedirection = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-  
-  let moveLocation = "test-request-302-located.txt";
-  let movedContent = "here now\n";
-  let movedUrl = "http://localhost:" + port + "/" + moveLocation;
-  prepareFile(moveLocation, movedContent);
-
-  let content = "The document has moved!\n";
-  let contentHeaders = "HTTP 302 Found\nLocation: "+moveLocation+"\n";
-  let basename = "test-request-302.txt"
-  let requestURL = "http://localhost:" + port + "/" + basename;
-  prepareFile(basename, content);
-  prepareFile(basename+"^headers^", contentHeaders);
-
-  var req = Request({
-    url: requestURL,
-    onComplete: function (response) {
-      assert.equal(this, req, "`this` should be request");
-      assert.equal(response.status, 200);
-      assert.equal(response.statusText, "OK");
-      assert.equal(response.headers["Content-Type"], "text/plain");
-      assert.equal(response.text, movedContent);
-      assert.strictEqual(response.url, movedUrl);
-      srv.stop(done);
-    }
-  }).get();
-};
-
-// This tries to get a file that doesn't exist
-exports.testStatus404 = function (assert, done) {
-  var srv = startServerAsync(port, basePath);
-  let requestURL = "http://localhost:" + port + "/test-request-404.txt";
-
-  runMultipleURLs(srv, assert, done, {
-    // the following URL doesn't exist
-    url: requestURL,
-    onComplete: function (response) {
-      assert.equal(response.status, 404);
-      assert.equal(response.statusText, "Not Found");
-      assert.strictEqual(response.url, requestURL);
-    }
-  });
-};
-
-// a simple file with a known header
-exports.testKnownHeader = function (assert, done) {
-  var srv = startServerAsync(port, basePath);
-
- // Create the file that will be requested with the associated headers file
-  let content = "This tests adding headers to the server's response.\n";
-  let basename = "test-request-headers.txt";
-  let headerContent = "x-jetpack-header: Jamba Juice\n";
-  let headerBasename = "test-request-headers.txt^headers^";
-  prepareFile(basename, content);
-  prepareFile(headerBasename, headerContent);
-
-  runMultipleURLs(srv, assert, done, {
-    url: "http://localhost:" + port + "/test-request-headers.txt",
-    onComplete: function (response) {
-      assert.equal(response.headers["x-jetpack-header"], "Jamba Juice");
-    }
-  });
-};
-
-// complex headers
-exports.testComplexHeader = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-
-  let basename = "test-request-complex-headers.sjs";
-  let content = handleRequest.toString();
-  prepareFile(basename, content);
-
-  let headers = {
-    "x-jetpack-header": "Jamba Juice is: delicious",
-    "x-jetpack-header-2": "foo,bar",
-    "x-jetpack-header-3": "sup dawg, i heard you like x, so we put a x in " +
-      "yo x so you can y while you y",
-    "Set-Cookie": "foo=bar\nbaz=foo"
-  };
-
-  runMultipleURLs(srv, assert, done, {
-    url: "http://localhost:" + port + "/test-request-complex-headers.sjs",
-    onComplete: function (response) {
-      for (k in headers) {
-        assert.equal(response.headers[k], headers[k]);
-      }
-    }
-  });
-};
-
-// Force Allow Third Party cookies
-exports.test3rdPartyCookies = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-
-  let basename = "test-request-3rd-party-cookies.sjs";
-
-  // Function to handle the requests in the server
-  let content = function handleRequest(request, response) {
-    var cookiePresent = request.hasHeader("Cookie");
-    // If no cookie, set it
-    if(!cookiePresent) {
-      response.setHeader("Set-Cookie", "cookie=monster;", "true");
-      response.setHeader("x-jetpack-3rd-party", "false", "true");
-    } else {
-      // We got the cookie, say so
-      response.setHeader("x-jetpack-3rd-party", "true", "true");
-    }
-
-    response.write("<html><body>This tests 3rd party cookies.</body></html>");
-  }.toString();
-
-  prepareFile(basename, content);
-
-  // Disable the 3rd party cookies
-  Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
-
-  Request({
-    url: "http://localhost:" + port + "/test-request-3rd-party-cookies.sjs",
-    onComplete: function (response) {
-      // Check that the server created the cookie
-      assert.equal(response.headers['Set-Cookie'], 'cookie=monster;');
-
-      // Check it wasn't there before
-      assert.equal(response.headers['x-jetpack-3rd-party'], 'false');
-
-      // Make a second request, and check that the server this time
-      // got the cookie
-      Request({
-        url: "http://localhost:" + port + "/test-request-3rd-party-cookies.sjs",
-        onComplete: function (response) {
-          assert.equal(response.headers['x-jetpack-3rd-party'], 'true');
-          srv.stop(done);
-        }
-      }).get();
-    }
-  }).get();
-};
-
-// Test anonymous request behavior
-exports.testAnonymousRequest = function(assert, done) {
-  let srv = startServerAsync(port, basePath);
-  let basename = "test-anonymous-request.sjs";
-  let testUrl = "http://localhost:" + port + "/" + basename;
-  // Function to handle the requests in the server
-  let content = function handleRequest(request, response) {
-    // Request to store cookie
-    response.setHeader("Set-Cookie", "anonymousKey=anonymousValue;", "true");
-    // Set response content type
-    response.setHeader("Content-Type", "application/json");
-    // Check if cookie was send during request
-    var cookiePresent = request.hasHeader("Cookie");
-    // Create server respone content
-    response.write(JSON.stringify({ "hasCookie": cookiePresent }));
-  }.toString();
-  prepareFile(basename, content);
-  // Create request callbacks
-  var checkCookieCreated = function (response) {
-    // Check that the server created the cookie
-    assert.equal(response.headers['Set-Cookie'], 'anonymousKey=anonymousValue;');
-    // Make an other request and check that the server this time got the cookie
-    Request({
-      url: testUrl,
-      onComplete: checkCookieSend
-    }).get();
-  },
-  checkCookieSend = function (response) {
-    // Check the response sent headers and cookies
-    assert.equal(response.anonymous, false);
-    // Check the server got the created cookie
-    assert.equal(response.json.hasCookie, true);
-    // Make a anonymous request and check the server did not get the cookie
-    Request({
-      url: testUrl,
-      anonymous: true,
-      onComplete: checkCookieNotSend
-    }).get();
-  },
-  checkCookieNotSend = function (response) {
-    // Check the response is anonymous
-    assert.equal(response.anonymous, true);
-    // Check the server did not get the cookie
-    assert.equal(response.json.hasCookie, false);
-    // Stop the server
-    srv.stop(done);
-  };
-  // Make the first request to create cookie
-  Request({
-    url: testUrl,
-    onComplete: checkCookieCreated
-  }).get();
-};
-
-exports.testSimpleJSON = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-  let json = { foo: "bar" };
-  let basename = "test-request.json";
-  prepareFile(basename, JSON.stringify(json));
-
-  runMultipleURLs(srv, assert, done, {
-    url: "http://localhost:" + port + "/" + basename,
-    onComplete: function (response) {
-      assert.deepEqual(response.json, json);
-    }
-  });
-};
-
-exports.testInvalidJSON = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-  let basename = "test-request-invalid.json";
-  prepareFile(basename, '"this": "isn\'t JSON"');
-
-  runMultipleURLs(srv, assert, done, {
-    url: "http://localhost:" + port + "/" + basename,
-    onComplete: function (response) {
-      assert.equal(response.json, null);
-    }
-  });
-};
-
-exports.testDelete = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-
-  srv.registerPathHandler("/test-delete",
-      function handle(request, response) {
-    response.setHeader("Content-Type", "text/plain", false);
-  });
-
-  Request({
-    url: "http://localhost:" + port + "/test-delete",
-    onComplete: function (response) {
-      // We cannot access the METHOD of the request to verify it's set
-      // correctly.
-      assert.equal(response.text, "");
-      assert.equal(response.statusText, "OK");
-      assert.equal(response.headers["Content-Type"], "text/plain");
-      srv.stop(done);
-    }
-  }).delete();
-};
-
-exports.testHead = function (assert, done) {
-  let srv = startServerAsync(port, basePath);
-
-  srv.registerPathHandler("/test-head",
-      function handle(request, response) {
-    response.setHeader("Content-Type", "text/plain", false);
-  });
-
-  Request({
-    url: "http://localhost:" + port + "/test-head",
-    onComplete: function (response) {
-      assert.equal(response.text, "");
-      assert.equal(response.statusText, "OK");
-      assert.equal(response.headers["Content-Type"], "text/plain");
-      srv.stop(done);
-    }
-  }).head();
-};
-
-function runMultipleURLs (srv, assert, done, options) {
-  let urls = [options.url, URL(options.url)];
-  let cb = options.onComplete;
-  let ran = 0;
-  let onComplete = function (res) {
-    cb(res);
-    if (++ran === urls.length)
-      srv ? srv.stop(done) : done();
-  };
-  urls.forEach(function (url) {
-    Request(extend(options, { url: url, onComplete: onComplete })).get();
-  });
-}
-
-// All tests below here require a network connection. They will be commented out
-// when checked in. If you'd like to run them, simply uncomment them.
-//
-// When we have the means, these tests will be converted so that they don't
-// require an external server nor a network connection.
-
-/*
-exports.testGetWithParamsNotContent = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar",
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: "bar" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testGetWithContent = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: { foo: "bar" },
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: "bar" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testGetWithParamsAndContent = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar",
-    content: { baz: "foo" },
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: "bar", baz: "foo" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testSimplePost = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: { foo: "bar" },
-    onComplete: function (response) {
-      let expected = {
-        "POST": { foo: "bar" },
-        "GET" : []
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).post();
-}
-
-exports.testEncodedContent = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: "foo=bar&baz=foo",
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: "bar", baz: "foo" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testEncodedContentWithSpaces = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: "foo=bar+hop!&baz=foo",
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: "bar hop!", baz: "foo" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testGetWithArray = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: { foo: [1, 2], baz: "foo" },
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : { foo: [1, 2], baz: "foo" }
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testGetWithNestedArray = function (assert, done) {
-  Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: { foo: [1, 2, [3, 4]], bar: "baz" },
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : this.content
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-
-exports.testGetWithNestedArray = function (assert, done) {
-  let request = Request({
-    url: "http://playground.zpao.com/jetpack/request/getpost.php",
-    content: {
-      foo: [1, 2, {
-        omg: "bbq",
-        "all your base!": "are belong to us"
-      }],
-      bar: "baz"
-    },
-    onComplete: function (response) {
-      let expected = {
-        "POST": [],
-        "GET" : request.content
-      };
-      assert.deepEqual(response.json, expected);
-      done();
-    }
-  }).get();
-}
-*/
-
-function prepareFile(basename, content) {
-  let filePath = file.join(basePath, basename);
-  let fileStream = file.open(filePath, 'w');
-  fileStream.write(content);
-  fileStream.close();
-}
-
-// Helper function for testComplexHeaders
-function handleRequest(request, response) {
-  // Test header with an extra colon
-  response.setHeader("x-jetpack-header", "Jamba Juice is: delicious", "true");
-
-  // Test that multiple headers with the same name coalesce
-  response.setHeader("x-jetpack-header-2", "foo", "true");
-  response.setHeader("x-jetpack-header-2", "bar", "true");
-
-  // Test that headers with commas work
-  response.setHeader("x-jetpack-header-3", "sup dawg, i heard you like x, " +
-    "so we put a x in yo x so you can y while you y", "true");
-
-  // Test that multiple cookies work
-  response.setHeader("Set-Cookie", "foo=bar", "true");
-  response.setHeader("Set-Cookie", "baz=foo", "true");
-
-  response.write("<html><body>This file tests more complex headers.</body></html>");
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-require.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/. */
-'use strict';
-
-const traceback = require('sdk/console/traceback');
-const REQUIRE_LINE_NO = 29;
-
-exports.test_no_args = function(assert) {
-  let passed = tryRequireModule(assert);
-  assert.ok(passed, 'require() with no args should raise helpful error');
-};
-
-exports.test_invalid_sdk_module = function (assert) {
-  let passed = tryRequireModule(assert, 'sdk/does-not-exist');
-  assert.ok(passed, 'require() with an invalid sdk module should raise');
-};
-
-exports.test_invalid_relative_module = function (assert) {
-  let passed = tryRequireModule(assert, './does-not-exist');
-  assert.ok(passed, 'require() with an invalid relative module should raise');
-};
-
-
-function tryRequireModule(assert, module) {
-  let passed = false;
-  try {
-    // This line number is important, referenced in REQUIRE_LINE_NO
-    let doesNotExist = require(module);
-  }
-  catch(e) {
-    checkError(assert, module, e);
-    passed = true;
-  }
-  return passed;
-}
-
-function checkError (assert, name, e) {
-  let msg = e.toString();
-  if (name) {
-    assert.ok(/is not found at/.test(msg),
-      'Error message indicates module not found');
-    assert.ok(msg.indexOf(name.replace(/\./g,'')) > -1,
-      'Error message has the invalid module name in the message');
-  }
-  else {
-    assert.equal(msg.indexOf('Error: You must provide a module name when calling require() from '), 0);
-    assert.ok(msg.indexOf("test-require") !== -1, msg);
-  }
-
-  // we'd also like to assert that the right filename
-  // and linenumber is in the stacktrace
-  let tb = traceback.fromException(e);
-
-  // The last frame may be inside a loader
-  let lastFrame = tb[tb.length - 1];
-  if (lastFrame.fileName.indexOf("toolkit/loader.js") !== -1 ||
-      lastFrame.fileName.indexOf("sdk/loader/cuddlefish.js") !== -1)
-    lastFrame = tb[tb.length - 2];
-
-  assert.ok(lastFrame.fileName.indexOf("test-require.js") !== -1,
-                          'Filename found in stacktrace');
-  assert.equal(lastFrame.lineNumber, REQUIRE_LINE_NO,
-                          'stacktrace has correct line number');
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-rules.js
+++ /dev/null
@@ -1,79 +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 { Rules } = require('sdk/util/rules');
-const { on, off, emit } = require('sdk/event/core');
-
-exports.testAdd = function (test, done) {
-  let rules = Rules();
-  let urls = [
-    'http://www.firefox.com',
-    '*.mozilla.org',
-    '*.html5audio.org'
-  ];
-  let count = 0;
-  on(rules, 'add', function (rule) {
-    if (count < urls.length) {
-      test.ok(rules.get(rule), 'rule added to internal registry');
-      test.equal(rule, urls[count], 'add event fired with proper params');
-      if (++count < urls.length) rules.add(urls[count]);
-      else done();
-    }
-  });
-  rules.add(urls[0]);
-};
-
-exports.testRemove = function (test, done) {
-  let rules = Rules();
-  let urls = [
-    'http://www.firefox.com',
-    '*.mozilla.org',
-    '*.html5audio.org'
-  ];
-  let count = 0;
-  on(rules, 'remove', function (rule) {
-    if (count < urls.length) {
-      test.ok(!rules.get(rule), 'rule removed to internal registry');
-      test.equal(rule, urls[count], 'remove event fired with proper params');
-      if (++count < urls.length) rules.remove(urls[count]);
-      else done();
-    }
-  });
-  urls.forEach(url => rules.add(url));
-  rules.remove(urls[0]);
-};
-
-exports.testMatchesAny = function(test) {
-  let rules = Rules();
-  rules.add('*.mozilla.org');
-  rules.add('data:*');
-  matchTest('http://mozilla.org', true);
-  matchTest('http://www.mozilla.org', true);
-  matchTest('http://www.google.com', false);
-  matchTest('data:text/html;charset=utf-8,', true);
-
-  function matchTest(string, expected) {
-    test.equal(rules.matchesAny(string), expected,
-      'Expected to find ' + string + ' in rules');
-  }
-};
-
-exports.testIterable = function(test) {
-  let rules = Rules();
-  rules.add('*.mozilla.org');
-  rules.add('data:*');
-  rules.add('http://google.com');
-  rules.add('http://addons.mozilla.org');
-  rules.remove('http://google.com');
-
-  test.equal(rules.length, 3, 'has correct length of keys');
-  Array.forEach(rules, function (rule, i) {
-    test.equal(rule, ['*.mozilla.org', 'data:*', 'http://addons.mozilla.org'][i]);
-  });
-  for (let i in rules)
-    test.equal(rules[i], ['*.mozilla.org', 'data:*', 'http://addons.mozilla.org'][i]);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-sandbox.js
+++ /dev/null
@@ -1,161 +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 { sandbox, load, evaluate, nuke } = require('sdk/loader/sandbox');
-const xulApp = require("sdk/system/xul-app");
-const fixturesURI = module.uri.split('test-sandbox.js')[0] + 'fixtures/';
-
-// The following adds Debugger constructor to the global namespace.
-const { Cu } = require('chrome');
-const { addDebuggerToGlobal } =
-  Cu.import('resource://gre/modules/jsdebugger.jsm', {});
-addDebuggerToGlobal(this);
-
-exports['test basics'] = function(assert) {
-  let fixture = sandbox('http://example.com');
-  assert.equal(evaluate(fixture, 'var a = 1;'), undefined,
-               'returns expression value');
-  assert.equal(evaluate(fixture, 'b = 2;'), 2,
-               'returns expression value');
-  assert.equal(fixture.b, 2, 'global is defined as property');
-  assert.equal(fixture.a, 1, 'global is defined as property');
-  assert.equal(evaluate(fixture, 'a + b;'), 3, 'returns correct sum');
-};
-
-exports['test non-privileged'] = function(assert) {
-  let fixture = sandbox('http://example.com');
-  if (xulApp.versionInRange(xulApp.platformVersion, "15.0a1", "18.*")) {
-    let rv = evaluate(fixture, 'Compo' + 'nents.utils');
-    assert.equal(rv, undefined,
-                 "Components's attributes are undefined in content sandboxes");
-  }
-  else {
-    assert.throws(function() {
-      evaluate(fixture, 'Compo' + 'nents.utils');
-    }, 'Access to components is restricted');
-  }
-  fixture.sandbox = sandbox;
-  assert.throws(function() {
-    evaluate(fixture, sandbox('http://foo.com'));
-  }, 'Can not call privileged code');
-};
-
-exports['test injection'] = function(assert) {
-  let fixture = sandbox();
-  fixture.hi = name => 'Hi ' + name;
-  assert.equal(evaluate(fixture, 'hi("sandbox");'), 'Hi sandbox',
-                'injected functions are callable');
-};
-
-exports['test exceptions'] = function(assert) {
-  let fixture = sandbox();
-  try {
-    evaluate(fixture, '!' + function() {
-      var message = 'boom';
-      throw Error(message);
-    } + '();');
-  }
-  catch (error) {
-    assert.equal(error.fileName, '[System Principal]', 'No specific fileName reported');
-    assert.equal(error.lineNumber, 3, 'reports correct line number');
-  }
-
-  try {
-    evaluate(fixture, '!' + function() {
-      var message = 'boom';
-      throw Error(message);
-    } + '();', 'foo.js');
-  }
-  catch (error) {
-    assert.equal(error.fileName, 'foo.js', 'correct fileName reported');
-    assert.equal(error.lineNumber, 3, 'reports correct line number');
-  }
-
-  try {
-    evaluate(fixture, '!' + function() {
-      var message = 'boom';
-      throw Error(message);
-    } + '();', 'foo.js', 2);
-  }
-  catch (error) {
-    assert.equal(error.fileName, 'foo.js', 'correct fileName reported');
-    assert.equal(error.lineNumber, 4, 'line number was opted');
-  }
-};
-
-exports['test load'] = function(assert) {
-  let fixture = sandbox();
-  load(fixture, fixturesURI + 'sandbox-normal.js');
-  assert.equal(fixture.a, 1, 'global variable defined');
-  assert.equal(fixture.b, 2, 'global via `this` property was set');
-  assert.equal(fixture.f(), 4, 'function was defined');
-};
-
-exports['test load with data: URL'] = function(assert) {
-  let code = "var a = 1; this.b = 2; function f() { return 4; }";
-  let fixture = sandbox();
-  load(fixture, "data:," + encodeURIComponent(code));
-
-  assert.equal(fixture.a, 1, 'global variable defined');
-  assert.equal(fixture.b, 2, 'global via `this` property was set');
-  assert.equal(fixture.f(), 4, 'function was defined');
-};
-
-exports['test load script with complex char'] = function(assert) {
-  let fixture = sandbox();
-  load(fixture, fixturesURI + 'sandbox-complex-character.js');
-  assert.equal(fixture.chars, 'გამარჯობა', 'complex chars were loaded correctly');
-};
-
-exports['test load script with data: URL and complex char'] = function(assert) {
-  let code = "var chars = 'გამარჯობა';";
-  let fixture = sandbox();
-  load(fixture, "data:," + encodeURIComponent(code));
-
-  assert.equal(fixture.chars, 'გამარჯობა', 'complex chars were loaded correctly');
-};
-
-exports['test metadata']  = function(assert) {
-  let self = require('sdk/self');
-
-  let dbg = new Debugger();
-  dbg.onNewGlobalObject = function(global) {
-    let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
-    assert.ok(metadata, 'this global has attached metadata');
-    assert.equal(metadata.addonID, self.id, 'addon ID is set');
-
-    dbg.onNewGlobalObject = undefined;
-  }
-
-  let fixture = sandbox();
-  assert.equal(dbg.onNewGlobalObject, undefined, 'Should have reset the handler');
-}
-
-exports['test nuke sandbox'] = function(assert) {
-
-  let fixture = sandbox('http://example.com');
-  fixture.foo = 'foo';
-
-  let ref = evaluate(fixture, 'let a = {bar: "bar"}; a');
-
-  nuke(fixture);
-
-  assert.ok(Cu.isDeadWrapper(fixture), 'sandbox should be dead');
-
-  assert.throws(
-    () => fixture.foo,
-    /can't access dead object/,
-    'property of nuked sandbox should not be accessible'
-  );
-
-  assert.ok(Cu.isDeadWrapper(ref), 'ref to object from sandbox should be dead');
-
-  assert.throws(
-    () => ref.bar,
-    /can't access dead object/,
-    'object from nuked sandbox should not be alive'
-  );
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-selection.js
+++ /dev/null
@@ -1,985 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const HTML = "<html>\
-  <body>\
-    <div>foo</div>\
-    <div>and</div>\
-    <textarea>noodles</textarea>\
-  </body>\
-</html>";
-
-const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
-
-const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
-const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
-
-const { Cu } = require("chrome");
-const { defer } = require("sdk/core/promise");
-const tabs = require("sdk/tabs");
-const { getActiveTab, getTabContentWindow, setTabURL } = require("sdk/tabs/utils")
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-const { open: openNewWindow } = require("sdk/window/helpers");
-const { Loader } = require("sdk/test/loader");
-const { setTimeout } = require("sdk/timers");
-const { merge } = require("sdk/util/object");
-const { isPrivate } = require("sdk/private-browsing");
-const events = require("sdk/system/events");
-const { viewFor } = require("sdk/view/core");
-const { cleanUI } = require("sdk/test/utils");
-// General purpose utility functions
-
-/**
- * Opens the url given and return a promise, that will be resolved with the
- * content window when the document is ready.
- *
- * I believe this approach could be useful in most of our unit test, that
- * requires to open a tab and need to access to its content.
- */
-function open(url, options) {
-  let { promise, resolve } = defer();
-
-  if (options && typeof(options) === "object") {
-    openNewWindow("", {
-      features: merge({ toolbar: true }, options)
-    }).then(function(chromeWindow) {
-      if (isPrivate(chromeWindow) !== !!options.private)
-        throw new Error("Window should have Private set to " + !!options.private);
-
-      let tab = getActiveTab(chromeWindow);
-
-      tab.linkedBrowser.addEventListener("load", function ready(event) {
-        let { document } = getTabContentWindow(tab);
-
-        if (document.readyState === "complete" && document.URL === url) {
-          this.removeEventListener(event.type, ready);
-
-          resolve(document.defaultView);
-        }
-      }, true);
-
-      setTabURL(tab, url);
-    });
-
-    return promise;
-  };
-
-  tabs.open({
-    url: url,
-    onReady: (tab) => {
-      let window = getTabContentWindow(viewFor(tab));
-      resolve(window);
-    }
-  });
-
-  return promise;
-};
-
-/**
- * Reload the window given and return a promise, that will be resolved with the
- * content window after a small delay.
- */
-function reload(window) {
-  let { promise, resolve } = defer();
-
-  // Here we assuming that the most recent browser window is the one we're
-  // doing the test, and the active tab is the one we just opened.
-  let tab = tabs.activeTab;
-
-  tab.once("ready", function () {
-    resolve(window);
-  });
-
-  window.location.reload(true);
-
-  return promise;
-}
-
-// Selection's unit test utility function
-
-/**
- * Returns the frame's window once the document is loaded
- */
-function getFrameWindow(window) {
-  let { promise, resolve } = defer();
-
-  let frame = window.frames[0];
-  let { document } = frame;
-
-  frame.focus();
-
-  if (document.readyState === "complete")
-    return frame;
-
-  document.addEventListener("readystatechange", function readystate() {
-    if (this.readyState === "complete") {
-      this.removeEventListener("readystatechange", readystate);
-      frame.focus();
-      resolve(frame);
-    }
-  });
-
-  return promise;
-}
-
-/**
- * Hide the frame in order to destroy the selection object, and show it again
- * after ~500 msec, to give time to attach the code on `document-shown`
- * notification.
- * In the process, call `Cu.forgeGC` to ensure that the `document-shown` code
- * is not garbaged.
- */
-function hideAndShowFrame(window) {
-  let { promise, resolve } = defer();
-  let iframe = window.document.querySelector("iframe");
-
-  iframe.style.display = "none";
-
-  Cu.schedulePreciseGC(function() {
-    events.on("document-shown", function shown(event) {
-      if (iframe.contentWindow !== event.subject.defaultView)
-        return;
-
-      events.off("document-shown", shown);
-      setTimeout(resolve, 0, window);
-    }, true);
-
-    iframe.style.display = "";
-  });
-
-  return promise;
-}
-
-/**
- * Select the first div in the page, adding the range to the selection.
- */
-function selectFirstDiv(window) {
-  let div = window.document.querySelector("div");
-  let selection = window.getSelection();
-  let range = window.document.createRange();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  range.selectNode(div);
-  selection.addRange(range);
-
-  return window;
-}
-
-/**
- * Select all divs in the page, adding the ranges to the selection.
- */
-function selectAllDivs(window) {
-  let divs = window.document.getElementsByTagName("div");
-  let selection = window.getSelection();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  for (let i = 0; i < divs.length; i++) {
-    let range = window.document.createRange();
-
-    range.selectNode(divs[i]);
-    selection.addRange(range);
-  }
-
-  return window;
-}
-
-/**
- * Select the textarea content
- */
-function selectTextarea(window) {
-  let selection = window.getSelection();
-  let textarea = window.document.querySelector("textarea");
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  textarea.setSelectionRange(0, textarea.value.length);
-  textarea.focus();
-
-  return window;
-}
-
-/**
- * Select the content of the first div
- */
-function selectContentFirstDiv(window) {
-  let div = window.document.querySelector("div");
-  let selection = window.getSelection();
-  let range = window.document.createRange();
-
-  if (selection.rangeCount > 0)
-    selection.removeAllRanges();
-
-  range.selectNodeContents(div);
-  selection.addRange(range);
-
-  return window;
-}
-
-/**
- * Dispatch the selection event for the selection listener added by
- * `nsISelectionPrivate.addSelectionListener`
- */
-function dispatchSelectionEvent(window) {
-  // We modify the selection in order to dispatch the selection's event, by
-  // contract the selection by one character. So if the text selected is "foo"
-  // will be "fo".
-  window.getSelection().modify("extend", "backward", "character");
-
-  return window;
-}
-
-/**
- * Dispatch the selection event for the selection listener added by
- * `window.onselect` / `window.addEventListener`
- */
-function dispatchOnSelectEvent(window) {
-  let { document } = window;
-  let textarea = document.querySelector("textarea");
-  let event = document.createEvent("UIEvents");
-
-  event.initUIEvent("select", true, true, window, 1);
-
-  textarea.dispatchEvent(event);
-
-  return window;
-}
-
-/**
- * Creates empty ranges and add them to selections
- */
-function createEmptySelections(window) {
-  selectAllDivs(window);
-
-  let selection = window.getSelection();
-
-  for (let i = 0; i < selection.rangeCount; i++)
-    selection.getRangeAt(i).collapse(true);
-}
-
-// Test cases
-
-exports["test No Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-
-  assert.equal(selection.isContiguous, false,
-    "selection.isContiguous without selection works.");
-
-  assert.strictEqual(selection.text, null,
-    "selection.text without selection works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html without selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection)
-    selectionCount++;
-
-  assert.equal(selectionCount, 0, "No iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Single DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-
-  selectFirstDiv(window)
-
-  assert.equal(selection.isContiguous, true,
-    "selection.isContiguous with single DOM Selection works.");
-
-  assert.equal(selection.text, "foo",
-    "selection.text with single DOM Selection works.");
-
-  assert.equal(selection.html, "<div>foo</div>",
-    "selection.html with single DOM Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    selectionCount++;
-
-    assert.equal(sel.text, "foo",
-      "iterable selection.text with single DOM Selection works.");
-
-    assert.equal(sel.html, "<div>foo</div>",
-      "iterable selection.html with single DOM Selection works.");
-  }
-
-  assert.equal(selectionCount, 1, "One iterable selection");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Multiple DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let expectedText = ["foo", "and"];
-  let expectedHTML = ["<div>foo</div>", "<div>and</div>"];
-  let window = yield open(URL);
-
-  selectAllDivs(window);
-
-  assert.equal(selection.isContiguous, false,
-    "selection.isContiguous with multiple DOM Selection works.");
-
-  assert.equal(selection.text, expectedText[0],
-    "selection.text with multiple DOM Selection works.");
-
-  assert.equal(selection.html, expectedHTML[0],
-    "selection.html with multiple DOM Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    assert.equal(sel.text, expectedText[selectionCount],
-      "iterable selection.text with multiple DOM Selection works.");
-
-    assert.equal(sel.html, expectedHTML[selectionCount],
-      "iterable selection.text with multiple DOM Selection works.");
-
-    selectionCount++;
-  }
-
-  assert.equal(selectionCount, 2, "Two iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Textarea Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-
-  selectTextarea(window);
-
-  assert.equal(selection.isContiguous, true,
-    "selection.isContiguous with Textarea Selection works.");
-
-  assert.equal(selection.text, "noodles",
-    "selection.text with Textarea Selection works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html with Textarea Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    selectionCount++;
-
-    assert.equal(sel.text, "noodles",
-      "iterable selection.text with Textarea Selection works.");
-
-    assert.strictEqual(sel.html, null,
-      "iterable selection.html with Textarea Selection works.");
-  }
-
-  assert.equal(selectionCount, 1, "One iterable selection");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Set Text in Multiple DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let expectedText = ["bar", "and"];
-  let expectedHTML = ["bar", "<div>and</div>"];
-  let window = yield open(URL);
-
-  selectAllDivs(window);
-
-  selection.text = "bar";
-
-  assert.equal(selection.text, expectedText[0],
-    "set selection.text with single DOM Selection works.");
-
-  assert.equal(selection.html, expectedHTML[0],
-    "selection.html with single DOM Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    assert.equal(sel.text, expectedText[selectionCount],
-      "iterable selection.text with multiple DOM Selection works.");
-
-    assert.equal(sel.html, expectedHTML[selectionCount],
-      "iterable selection.html with multiple DOM Selection works.");
-
-    selectionCount++;
-  }
-
-  assert.equal(selectionCount, 2, "Two iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Set HTML in Multiple DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let html = "<span>b<b>a</b>r</span>";
-  let expectedText = ["bar", "and"];
-  let expectedHTML = [html, "<div>and</div>"];
-  let window = yield open(URL);
-
-  selectAllDivs(window);
-
-  selection.html = html;
-
-  assert.equal(selection.text, expectedText[0],
-    "set selection.text with DOM Selection works.");
-
-  assert.equal(selection.html, expectedHTML[0],
-    "selection.html with DOM Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    assert.equal(sel.text, expectedText[selectionCount],
-      "iterable selection.text with multiple DOM Selection works.");
-
-    assert.equal(sel.html, expectedHTML[selectionCount],
-      "iterable selection.html with multiple DOM Selection works.");
-
-    selectionCount++;
-  }
-
-  assert.equal(selectionCount, 2, "Two iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Set HTML as text in Multiple DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let text = "<span>b<b>a</b>r</span>";
-  let html = "&lt;span&gt;b&lt;b&gt;a&lt;/b&gt;r&lt;/span&gt;";
-  let expectedText = [text, "and"];
-  let expectedHTML = [html, "<div>and</div>"];
-  let window = yield open(URL);
-
-  selectAllDivs(window);
-
-  selection.text = text;
-
-  assert.equal(selection.text, expectedText[0],
-    "set selection.text with DOM Selection works.");
-
-  assert.equal(selection.html, expectedHTML[0],
-    "selection.html with DOM Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    assert.equal(sel.text, expectedText[selectionCount],
-      "iterable selection.text with multiple DOM Selection works.");
-
-    assert.equal(sel.html, expectedHTML[selectionCount],
-      "iterable selection.html with multiple DOM Selection works.");
-
-    selectionCount++;
-  }
-
-  assert.equal(selectionCount, 2, "Two iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Set Text in Textarea Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let text = "bar";
-  let window = yield open(URL);
-
-  selectTextarea(window);
-
-  selection.text = text;
-
-  assert.equal(selection.text, text,
-    "set selection.text with Textarea Selection works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html with Textarea Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    selectionCount++;
-
-    assert.equal(sel.text, text,
-      "iterable selection.text with Textarea Selection works.");
-
-    assert.strictEqual(sel.html, null,
-      "iterable selection.html with Textarea Selection works.");
-  }
-
-  assert.equal(selectionCount, 1, "One iterable selection");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Set HTML in Textarea Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let html = "<span>b<b>a</b>r</span>";
-  let window = yield open(URL);
-
-  selectTextarea(window);
-
-  // Textarea can't have HTML so set `html` property is equals to set `text`
-  // property
-  selection.html = html;
-
-  assert.equal(selection.text, html,
-    "set selection.text with Textarea Selection works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html with Textarea Selection works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    selectionCount++;
-
-    assert.equal(sel.text, html,
-      "iterable selection.text with Textarea Selection works.");
-
-    assert.strictEqual(sel.html, null,
-      "iterable selection.html with Textarea Selection works.");
-  }
-
-  assert.equal(selectionCount, 1, "One iterable selection");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Empty Selections"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-
-  createEmptySelections(window);
-
-  assert.equal(selection.isContiguous, false,
-    "selection.isContiguous with empty selections works.");
-
-  assert.strictEqual(selection.text, null,
-    "selection.text with empty selections works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html with empty selections works.");
-
-  let selectionCount = 0;
-  for (let sel of selection)
-    selectionCount++;
-
-  assert.equal(selectionCount, 0, "No iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-}
-
-
-exports["test No Selection Exception"] = function*(assert) {
-  const NO_SELECTION = /It isn't possible to change the selection/;
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-
-  // We're trying to change a selection when there is no selection
-  assert.throws(function() {
-    selection.text = "bar";
-  }, NO_SELECTION);
-
-  assert.throws(function() {
-    selection.html = "bar";
-  }, NO_SELECTION);
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test for...of without selections"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL);
-  let selectionCount = 0;
-
-  for (let sel of selection)
-    selectionCount++;
-
-  assert.equal(selectionCount, 0, "No iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-}
-
-exports["test for...of with selections"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let expectedText = ["foo", "and"];
-  let expectedHTML = ["<div>foo</div>", "<div>and</div>"];
-  let window = yield open(URL);
-
-  selectAllDivs(window);
-
-  let selectionCount = 0;
-
-  for (let sel of selection) {
-    assert.equal(sel.text, expectedText[selectionCount],
-      "iterable selection.text with for...of works.");
-
-    assert.equal(sel.html, expectedHTML[selectionCount],
-      "iterable selection.text with for...of works.");
-
-    selectionCount++;
-  }
-
-  assert.equal(selectionCount, 2, "Two iterable selections");
-
-  yield cleanUI();
-  loader.unload();
-}
-
-exports["test Selection Listener"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  yield open(URL).
-    then(selectContentFirstDiv).
-    then(dispatchSelectionEvent);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "fo");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Textarea OnSelect Listener"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  yield open(URL).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "noodles", "selection is noodles");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Selection listener removed on unload"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  selection.once("select", function() {
-    assert.fail("Shouldn't be never called");
-  });
-
-  loader.unload();
-  assert.pass("unload was a success");
-
-  yield open(URL).
-    then(selectContentFirstDiv).
-    then(dispatchSelectionEvent).
-    then(cleanUI);
-};
-
-exports["test Textarea onSelect Listener removed on unload"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  selection.once("select", function() {
-    assert.fail("Shouldn't be never called");
-  });
-
-  loader.unload();
-  assert.pass("unload was a success");
-
-  yield open(URL).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent).
-    then(cleanUI);
-};
-
-
-exports["test Selection Listener on existing document"] = function*(assert) {
-  let loader = Loader(module);
-  let selected = defer();
-
-  let window = yield open(URL);
-  let selection = loader.require("sdk/selection");
-
-  selection.once("select", selected.resolve);
-
-  selectContentFirstDiv(window);
-  dispatchSelectionEvent(window);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "fo");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-
-exports["test Textarea OnSelect Listener on existing document"] = function*(assert) {
-  let loader = Loader(module);
-  let selected = defer();
-
-  let selection = loader.require("sdk/selection");
-
-  let window = yield open(URL);
-
-  selection.once("select", selected.resolve);
-  selectTextarea(window)
-  dispatchOnSelectEvent(window);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "noodles");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Selection Listener on document reload"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  yield open(URL).
-    then(reload).
-    then(selectContentFirstDiv).
-    then(dispatchSelectionEvent);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "fo");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Textarea OnSelect Listener on document reload"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  yield open(URL).
-    then(reload).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "noodles");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test Selection Listener on frame"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  let window = yield open(FRAME_URL);
-  yield hideAndShowFrame(window);
-  let frame = yield getFrameWindow(window);
-  yield selectContentFirstDiv(frame);
-  yield dispatchSelectionEvent(frame);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "fo");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-
-// TODO: re-enable and fix intermittent test below
-// See Bug 970062 https://bugzilla.mozilla.org/show_bug.cgi?id=970062
-/*
-exports["test Textarea onSelect Listener on frame"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let selected = defer();
-
-  selection.once("select", selected.resolve);
-
-  yield open(FRAME_URL).
-    then(hideAndShowFrame).
-    then(getFrameWindow).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent);
-
-  yield selected.promise;
-
-  assert.equal(selection.text, "noodles");
-
-  yield cleanUI();
-  loader.unload();
-};
-*/
-
-
-exports["test PBPW Selection Listener"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  selection.once("select", function() {
-    assert.fail("Shouldn't be never called");
-  });
-
-  assert.pass();
-
-  yield open(URL, { private: true }).
-    then(selectContentFirstDiv).
-    then(dispatchSelectionEvent).
-    then(cleanUI);
-
-  loader.unload();
-};
-
-exports["test PBPW Textarea OnSelect Listener"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-
-  selection.once("select", () => {
-    assert.fail("Shouldn't be never called");
-  });
-
-  assert.pass("opening private test content window");
-
-  yield open(URL, { private: true }).
-    then(selectTextarea).
-    then(dispatchOnSelectEvent).
-    then(cleanUI);
-
-  loader.unload();
-};
-
-
-exports["test PBPW Single DOM Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL, { private: true });
-
-  selectFirstDiv(window);
-
-  assert.equal(selection.isContiguous, false,
-    "selection.isContiguous with single DOM Selection in PBPW works.");
-
-  assert.equal(selection.text, null,
-    "selection.text with single DOM Selection in PBPW works.");
-
-  assert.equal(selection.html, null,
-    "selection.html with single DOM Selection in PBPW works.");
-
-  let selectionCount = 0;
-  for (let sel of selection)
-    selectionCount++;
-
-  assert.equal(selectionCount, 0, "No iterable selection in PBPW");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-exports["test PBPW Textarea Selection"] = function*(assert) {
-  let loader = Loader(module);
-  let selection = loader.require("sdk/selection");
-  let window = yield open(URL, { private: true });
-
-  selectTextarea(window);
-
-  assert.equal(selection.isContiguous, false,
-    "selection.isContiguous with Textarea Selection in PBPW works.");
-
-  assert.equal(selection.text, null,
-    "selection.text with Textarea Selection in PBPW works.");
-
-  assert.strictEqual(selection.html, null,
-    "selection.html with Textarea Selection in PBPW works.");
-
-  let selectionCount = 0;
-  for (let sel of selection) {
-    selectionCount++;
-
-    assert.equal(sel.text, null,
-      "iterable selection.text with Textarea Selection in PBPW works.");
-
-    assert.strictEqual(sel.html, null,
-      "iterable selection.html with Textarea Selection in PBPW works.");
-  }
-
-  assert.equal(selectionCount, 0, "No iterable selection in PBPW");
-
-  yield cleanUI();
-  loader.unload();
-};
-
-// TODO: test Selection Listener on long-held connection (Bug 661884)
-//
-//  I didn't find a way to do so with httpd, using `processAsync` I'm able to
-//  Keep the connection but not to flush the buffer to the client in two steps,
-//  that is what I need for this test (e.g. flush "Hello" to the client, makes
-//  selection when the connection is still hold, and check that the listener
-//  is executed before the server send "World" and close the connection).
-//
-//  Because this test is needed to the refactoring of context-menu as well, I
-//  believe we will find a proper solution quickly.
-/*
-exports["test Selection Listener on long-held connection"] = function(assert, done) {
-
-};
-*/
-
-// If the platform doesn't support the PBPW, we're replacing PBPW tests
-if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
-  Object.keys(module.exports).forEach((key) => {
-    if (key.indexOf("test PBPW") === 0) {
-      module.exports[key] = function Unsupported (assert) {
-        assert.pass("Private Window Per Browsing is not supported on this platform.");
-      }
-    }
-  });
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-self.js
+++ /dev/null
@@ -1,79 +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 xulApp = require("sdk/system/xul-app");
-const self = require("sdk/self");
-const { Loader, main, unload, override } = require("toolkit/loader");
-const { PlainTextConsole } = require("sdk/console/plain-text");
-const { Loader: CustomLoader } = require("sdk/test/loader");
-const loaderOptions = require("@loader/options");
-
-exports.testSelf = function(assert) {
-  // Likewise, we can't assert anything about the full URL, because that
-  // depends on self.id . We can only assert that it ends in the right
-  // thing.
-  var url = self.data.url("test.html");
-  assert.equal(typeof(url), "string", "self.data.url('x') returns string");
-  assert.equal(/\/test\.html$/.test(url), true);
-
-  // Make sure 'undefined' is not in url when no string is provided.
-  url = self.data.url();
-  assert.equal(typeof(url), "string", "self.data.url() returns string");
-  assert.equal(/\/undefined$/.test(url), false);
-
-  // When tests are run on just the api-utils package, self.name is
-  // api-utils. When they're run as 'cfx testall', self.name is testpkgs.
-  assert.equal(self.name, "addon-sdk", "self.name is addon-sdk");
-
-  // loadReason may change here, as we change the way tests addons are installed
-  // Bug 854937 fixed loadReason and is now install
-  let testLoadReason = xulApp.versionInRange(xulApp.platformVersion,
-                                             "23.0a1", "*") ? "install"
-                                                            : "startup";
-  assert.equal(self.loadReason, testLoadReason,
-               "self.loadReason is either startup or install on test runs");
-
-  assert.equal(self.isPrivateBrowsingSupported, false,
-               'usePrivateBrowsing property is false by default');
-};
-
-exports.testSelfHandlesLackingLoaderOptions = function (assert) {
-  let root = module.uri.substr(0, module.uri.lastIndexOf('/'));
-  let uri = root + '/fixtures/loader/self/';
-  let sdkPath = loaderOptions.paths[''] + 'sdk';
-  let loader = Loader({ paths: { '': uri, 'sdk': sdkPath }});
-  let program = main(loader, 'main');
-  let self = program.self;
-  assert.pass("No errors thrown when including sdk/self without loader options");
-  assert.equal(self.isPrivateBrowsingSupported, false,
-    "safely checks sdk/self.isPrivateBrowsingSupported");
-  assert.equal(self.packed, false,
-    "safely checks sdk/self.packed");
-  unload(loader);
-};
-
-exports.testPreferencesBranch = function (assert) {
-  let options = override(loaderOptions, {
-    preferencesBranch: 'human-readable',
-  });
-  let loader = CustomLoader(module, { }, options);
-  let { preferencesBranch } = loader.require('sdk/self');
-  assert.equal(preferencesBranch, 'human-readable',
-    'preferencesBranch is human-readable');
-}
-
-exports.testInvalidPreferencesBranch = function (assert) {
-  let console = new PlainTextConsole(_ => void _);
-  let options = override(loaderOptions, {
-    preferencesBranch: 'invalid^branch*name',
-    id: 'simple@jetpack'
-  });
-  let loader = CustomLoader(module, { console }, options);
-  let { preferencesBranch } = loader.require('sdk/self');
-  assert.equal(preferencesBranch, 'simple@jetpack',
-    'invalid preferencesBranch value ignored');
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-sequence.js
+++ /dev/null
@@ -1,1245 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var { seq, iterate, filter, map, reductions, reduce, count,
-      isEmpty, every, isEvery, some, take, takeWhile, drop,
-      dropWhile, concat, first, rest, nth, last, dropLast,
-      distinct, remove, mapcat, fromEnumerator, string,
-      object, pairs, keys, values, each, names, symbols
-    } = require("sdk/util/sequence");
-
-const boom = () => { throw new Error("Boom!"); };
-const broken = seq(function*() {
-  yield 1;
-  throw new Error("Boom!");
-});
-
-exports["test seq"] = assert => {
-  let xs = seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-  });
-
-  assert.deepEqual([...seq(null)], [], "seq of null is empty");
-  assert.deepEqual([...seq(void(0))], [], "seq of void is empty");
-  assert.deepEqual([...xs], [1, 2, 3], "seq of 1 2 3");
-  assert.deepEqual([...seq(xs)], [1, 2, 3], "seq of seq is seq");
-
-  assert.deepEqual([...seq([])], [], "seq of emtpy array is empty");
-  assert.deepEqual([...seq([1])], [1], "seq of lonly array is single element");
-  assert.deepEqual([...seq([1, 2, 3])], [1, 2, 3], "seq of array is it's elements");
-
-  assert.deepEqual([...seq("")], [], "seq of emtpy string is empty");
-  assert.deepEqual([...seq("o")], ["o"], "seq of char is single char seq");
-  assert.deepEqual([...seq("hello")], ["h", "e", "l", "l", "o"],
-                   "seq of string are chars");
-
-  assert.deepEqual([...seq(new Set())], [], "seq of emtpy set is empty");
-  assert.deepEqual([...seq(new Set([1]))], [1], "seq of lonely set is single");
-  assert.deepEqual([...seq(new Set([1, 2, 3]))], [1, 2, 3], "seq of lonely set is single");
-
-  assert.deepEqual([...seq(new Map())], [], "seq of emtpy map is empty");
-  assert.deepEqual([...seq(new Map([[1, 2]]))], [[1, 2]], "seq single mapping is that mapping");
-  assert.deepEqual([...seq(new Map([[1, 2], [3, 4], [5, 6]]))],
-                   [[1, 2], [3, 4], [5, 6]],
-                   "seq of map is key value mappings");
-
-  [function(){}, 1, /foo/, true].forEach(x => {
-    assert.throws(() => seq(x), "Type is not seq-able");
-  });
-
-  assert.throws(() => [...broken],
-                /Boom/,
-                "broken sequence errors propagate");
-};
-
-exports["test seq casting"] = assert => {
-  const xs = seq(function*() { yield 1; yield 2; yield 3; });
-  const ys = seq(function*() { yield 1; });
-  const zs = seq(function*() {});
-  const kvs = seq(function*() { yield ["a", 1]; yield ["b", 2]; });
-  const kv = seq(function*() { yield ["a", 1]; });
-
-  assert.deepEqual([...xs], [1, 2, 3], "cast to array");
-  assert.deepEqual([...ys], [1], "cast to of one element");
-  assert.deepEqual([...zs], [], "cast empty array");
-
-  assert.deepEqual(string(...xs), "123", "cast to string");
-  assert.deepEqual(string(...ys), "1", "cast to char");
-  assert.deepEqual(string(...zs), "", "cast to empty string");
-
-  assert.deepEqual(new Set(xs), new Set([1, 2, 3]),
-                   "cast to set of items");
-  assert.deepEqual(new Set(ys), new Set([1]),
-                   "cast to set of one item");
-  assert.deepEqual(new Set(zs), new Set(),
-                   "cast to set of one item");
-
-  assert.deepEqual(new Map(kvs), new Map([["a", 1], ["b", 2]]),
-                   "cast to map");
-  assert.deepEqual(new Map(kv), new Map([["a", 1]]),
-                   "cast to single mapping");
-  assert.deepEqual(new Map(zs), new Map(),
-                   "cast to empty map");
-
-  assert.deepEqual(object(...kvs), {a: 1, b: 2},
-                  "cast to object");
-  assert.deepEqual(object(...kv), {a: 1},
-                  "cast to single pair");
-  assert.deepEqual(object(...zs), {},
-                  "cast to empty object");
-};
-
-exports["test pairs"] = assert => {
-  assert.deepEqual([...pairs(null)], [], "pairs on null is empty");
-  assert.deepEqual([...pairs(void(0))], [], "pairs on void is empty");
-  assert.deepEqual([...pairs({})], [], "empty sequence");
-  assert.deepEqual([...pairs({a: 1})], [["a", 1]], "single pair");
-  assert.deepEqual([...pairs({a: 1, b: 2, c: 3})].sort(),
-                   [["a", 1], ["b", 2], ["c", 3]],
-                   "creates pairs");
-  let items = [];
-  for (let [key, value] of pairs({a: 1, b: 2, c: 3}))
-    items.push([key, value]);
-
-  assert.deepEqual(items.sort(),
-                   [["a", 1], ["b", 2], ["c", 3]],
-                   "for of works on pairs");
-
-
-  assert.deepEqual([...pairs([])], [], "pairs on empty array is empty");
-  assert.deepEqual([...pairs([1])], [[0, 1]], "pairs on array is [index, element]");
-  assert.deepEqual([...pairs([1, 2, 3])],
-                   [[0, 1], [1, 2], [2, 3]],
-                   "for arrays it pair of [index, element]");
-
-  assert.deepEqual([...pairs("")], [], "pairs on empty string is empty");
-  assert.deepEqual([...pairs("a")], [[0, "a"]], "pairs on char is [0, char]");
-  assert.deepEqual([...pairs("hello")],
-                   [[0, "h"], [1, "e"], [2, "l"], [3, "l"], [4, "o"]],
-                   "for strings it's pair of [index, char]");
-
-  assert.deepEqual([...pairs(new Map())],
-                   [],
-                   "pairs on empty map is empty");
-  assert.deepEqual([...pairs(new Map([[1, 3]]))],
-                   [[1, 3]],
-                   "pairs on single mapping single mapping");
-  assert.deepEqual([...pairs(new Map([[1, 2], [3, 4]]))],
-                   [[1, 2], [3, 4]],
-                   "pairs on map returs key vaule pairs");
-
-  assert.throws(() => pairs(new Set()),
-                "can't pair set");
-
-  assert.throws(() => pairs(4),
-                "can't pair number");
-
-  assert.throws(() => pairs(true),
-                "can't pair boolean");
-};
-
-exports["test keys"] = assert => {
-  assert.deepEqual([...keys(null)], [], "keys on null is empty");
-  assert.deepEqual([...keys(void(0))], [], "keys on void is empty");
-  assert.deepEqual([...keys({})], [], "empty sequence");
-  assert.deepEqual([...keys({a: 1})], ["a"], "single key");
-  assert.deepEqual([...keys({a: 1, b: 2, c: 3})].sort(),
-                   ["a", "b", "c"],
-                   "all keys");
-  assert.deepEqual([...keys(Object.create({}, {
-                              a: {value: 1, enumerable: true},
-                              b: {value: 2, enumerable: false},
-                              c: {value: 3, enumerable: false}
-                            }))].sort(),
-                 ["a"],
-                 "only enumerable keys");
-
-  let items = [];
-  for (let key of keys({a: 1, b: 2, c: 3}))
-    items.push(key);
-
-  assert.deepEqual(items.sort(),
-                   ["a", "b", "c"],
-                   "for of works on keys");
-
-
-  assert.deepEqual([...keys([])], [], "keys on empty array is empty");
-  assert.deepEqual([...keys([1])], [0], "keys on array is indexes");
-  assert.deepEqual([...keys([1, 2, 3])],
-                   [0, 1, 2],
-                   "keys on arrays returns indexes");
-
-  assert.deepEqual([...keys("")], [], "keys on empty string is empty");
-  assert.deepEqual([...keys("a")], [0], "keys on char is 0");
-  assert.deepEqual([...keys("hello")],
-                   [0, 1, 2, 3, 4],
-                   "keys on strings is char indexes");
-
-  assert.deepEqual([...keys(new Map())],
-                   [],
-                   "keys on empty map is empty");
-  assert.deepEqual([...keys(new Map([[1, 3]]))],
-                   [1],
-                   "keys on single mapping single mapping is single key");
-  assert.deepEqual([...keys(new Map([[1, 2], [3, 4]]))],
-                   [1, 3],
-                   "keys on map is keys from map");
-
-  assert.throws(() => keys(new Set()),
-                "can't keys set");
-
-  assert.throws(() => keys(4),
-                "can't keys number");
-
-  assert.throws(() => keys(true),
-                "can't keys boolean");
-};
-
-exports["test names"] = assert => {
-  assert.deepEqual([...names(null)], [], "names on null is empty");
-  assert.deepEqual([...names(void(0))], [], "names on void is empty");
-  assert.deepEqual([...names({})], [], "empty sequence");
-  assert.deepEqual([...names({a: 1})], ["a"], "single key");
-  assert.deepEqual([...names({a: 1, b: 2, c: 3})].sort(),
-                   ["a", "b", "c"],
-                   "all keys");
-  assert.deepEqual([...names(Object.create({}, {
-                              a: {value: 1, enumerable: true},
-                              b: {value: 2, enumerable: false},
-                              c: {value: 3, enumerable: false}
-                            }))].sort(),
-                   ["a", "b", "c"],
-                   "all enumerable & non-enumerable keys");
-
-
-  assert.throws(() => names([1, 2, 3]),
-                "can't names array");
-
-  assert.throws(() => names(""),
-                "can't names string");
-
-  assert.throws(() => names(new Map()),
-                "can't names map");
-
-  assert.throws(() => names(new Set()),
-                "can't names set");
-
-  assert.throws(() => names(4),
-                "can't names number");
-
-  assert.throws(() => names(true),
-                "can't names boolean");
-};
-
-exports["test symbols"] = assert => {
-  assert.deepEqual([...symbols(null)], [], "symbols on null is empty");
-  assert.deepEqual([...symbols(void(0))], [], "symbols on void is empty");
-  assert.deepEqual([...symbols({})], [], "symbols on empty is empty");
-  assert.deepEqual([...symbols({a: 1})], [], "symbols is empty if not owned");
-
-  const b = Symbol("b");
-  assert.deepEqual([...symbols({a: 1, [b]: 2, c: 3})].sort(),
-                   [b],
-                   "only symbols");
-
-  assert.deepEqual([...symbols(Object.create({}, {
-                                a: {value: 1, enumerable: true},
-                                [b]: {value: 2, enumerable: false},
-                                c: {value: 3, enumerable: false}
-                              }))].sort(),
-                   [b],
-                   "includes non-enumerable symbols");
-
-
-  assert.throws(() => symbols([1, 2, 3]),
-                "can't symbols array");
-
-  assert.throws(() => symbols(""),
-                "can't symbols string");
-
-  assert.throws(() => symbols(new Map()),
-                "can't symbols map");
-
-  assert.throws(() => symbols(new Set()),
-                "can't symbols set");
-
-  assert.throws(() => symbols(4),
-                "can't symbols number");
-
-  assert.throws(() => symbols(true),
-                "can't symbols boolean");
-};
-
-exports["test values"] = assert => {
-  assert.deepEqual([...values({})], [], "empty sequence");
-  assert.deepEqual([...values({a: 1})], [1], "single value");
-  assert.deepEqual([...values({a: 1, b: 2, c: 3})].sort(),
-                   [1, 2, 3],
-                   "all values");
-
-  let items = [];
-  for (let value of values({a: 1, b: 2, c: 3}))
-    items.push(value);
-
-  assert.deepEqual(items.sort(),
-                   [1, 2, 3],
-                   "for of works on values");
-
-  assert.deepEqual([...values([])], [], "values on empty array is empty");
-  assert.deepEqual([...values([1])], [1], "values on array elements");
-  assert.deepEqual([...values([1, 2, 3])],
-                   [1, 2, 3],
-                   "values on arrays returns elements");
-
-  assert.deepEqual([...values("")], [], "values on empty string is empty");
-  assert.deepEqual([...values("a")], ["a"], "values on char is char");
-  assert.deepEqual([...values("hello")],
-                   ["h", "e", "l", "l", "o"],
-                   "values on strings is chars");
-
-  assert.deepEqual([...values(new Map())],
-                   [],
-                   "values on empty map is empty");
-  assert.deepEqual([...values(new Map([[1, 3]]))],
-                   [3],
-                   "keys on single mapping single mapping is single key");
-  assert.deepEqual([...values(new Map([[1, 2], [3, 4]]))],
-                   [2, 4],
-                   "values on map is values from map");
-
-  assert.deepEqual([...values(new Set())], [], "values on empty set is empty");
-  assert.deepEqual([...values(new Set([1]))], [1], "values on set is it's items");
-  assert.deepEqual([...values(new Set([1, 2, 3]))],
-                   [1, 2, 3],
-                   "values on set is it's items");
-
-
-  assert.throws(() => values(4),
-                "can't values number");
-
-  assert.throws(() => values(true),
-                "can't values boolean");
-};
-
-exports["test fromEnumerator"] = assert => {
-  const { Cc, Ci } = require("chrome");
-  const { enumerateObservers,
-          addObserver,
-          removeObserver } = Cc["@mozilla.org/observer-service;1"].
-                               getService(Ci.nsIObserverService);
-
-
-  const topic = "sec:" + Math.random().toString(32).substr(2);
-  const [a, b, c] = [{wrappedJSObject: {}},
-                     {wrappedJSObject: {}},
-                     {wrappedJSObject: {}}];
-  const unwrap = x => x.wrappedJSObject;
-
-  [a, b, c].forEach(x => addObserver(x, topic, false));
-
-  const xs = fromEnumerator(() => enumerateObservers(topic));
-  const ys = map(unwrap, xs);
-
-  assert.deepEqual([...ys], [a, b, c].map(unwrap),
-                   "all observers are there");
-
-  removeObserver(b, topic);
-
-  assert.deepEqual([...ys], [a, c].map(unwrap),
-                   "b was removed");
-
-  removeObserver(a, topic);
-
-  assert.deepEqual([...ys], [c].map(unwrap),
-                   "a was removed");
-
-  removeObserver(c, topic);
-
-  assert.deepEqual([...ys], [],
-                   "c was removed, now empty");
-
-  addObserver(a, topic, false);
-
-  assert.deepEqual([...ys], [a].map(unwrap),
-                   "a was added");
-
-  removeObserver(a, topic);
-
-  assert.deepEqual([...ys], [].map(unwrap),
-                   "a was removed, now empty");
-
-};
-
-exports["test filter"] = assert => {
-  const isOdd = x => x % 2;
-  const odds = seq(function*() { yield 1; yield 3; yield 5; });
-  const evens = seq(function*() { yield 2; yield 4; yield 6; });
-  const mixed = seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-    yield 4;
-  });
-
-  assert.deepEqual([...filter(isOdd, mixed)], [1, 3],
-                   "filtered odds");
-  assert.deepEqual([...filter(isOdd, odds)], [1, 3, 5],
-                   "kept all");
-  assert.deepEqual([...filter(isOdd, evens)], [],
-                   "kept none");
-
-
-  let xs = filter(boom, mixed);
-  assert.throws(() => [...xs], /Boom/, "errors propagate");
-
-  assert.throws(() => [...filter(isOdd, broken)], /Boom/,
-                "sequence errors propagate");
-};
-
-exports["test filter array"] = assert => {
-  let isOdd = x => x % 2;
-  let xs = filter(isOdd, [1, 2, 3, 4]);
-  let ys = filter(isOdd, [1, 3, 5]);
-  let zs = filter(isOdd, [2, 4, 6]);
-
-  assert.deepEqual([...xs], [1, 3], "filteres odds");
-  assert.deepEqual([...ys], [1, 3, 5], "kept all");
-  assert.deepEqual([...zs], [], "kept none");
-  assert.ok(!Array.isArray(xs));
-};
-
-exports["test filter set"] = assert => {
-  let isOdd = x => x % 2;
-  let xs = filter(isOdd, new Set([1, 2, 3, 4]));
-  let ys = filter(isOdd, new Set([1, 3, 5]));
-  let zs = filter(isOdd, new Set([2, 4, 6]));
-
-  assert.deepEqual([...xs], [1, 3], "filteres odds");
-  assert.deepEqual([...ys], [1, 3, 5], "kept all");
-  assert.deepEqual([...zs], [], "kept none");
-};
-
-exports["test filter string"] = assert => {
-  let isUpperCase = x => x.toUpperCase() === x;
-  let xs = filter(isUpperCase, "aBcDe");
-  let ys = filter(isUpperCase, "ABC");
-  let zs = filter(isUpperCase, "abcd");
-
-  assert.deepEqual([...xs], ["B", "D"], "filteres odds");
-  assert.deepEqual([...ys], ["A", "B", "C"], "kept all");
-  assert.deepEqual([...zs], [], "kept none");
-};
-
-exports["test filter lazy"] = assert => {
-  const x = 1;
-  let y = 2;
-
-  const xy = seq(function*() { yield x; yield y; });
-  const isOdd = x => x % 2;
-  const actual = filter(isOdd, xy);
-
-  assert.deepEqual([...actual], [1], "only one odd number");
-  y = 3;
-  assert.deepEqual([...actual], [1, 3], "filter is lazy");
-};
-
-exports["test filter non sequences"] = assert => {
-  const False = _ => false;
-  assert.throws(() => [...filter(False, 1)],
-                "can't iterate number");
-  assert.throws(() => [...filter(False, {a: 1, b:2})],
-                "can't iterate object");
-};
-
-exports["test map"] = assert => {
-  let inc = x => x + 1;
-  let xs = seq(function*() { yield 1; yield 2; yield 3; });
-  let ys = map(inc, xs);
-
-  assert.deepEqual([...ys], [2, 3, 4], "incremented each item");
-
-  assert.deepEqual([...map(inc, null)], [], "mapping null is empty");
-  assert.deepEqual([...map(inc, void(0))], [], "mapping void is empty");
-  assert.deepEqual([...map(inc, new Set([1, 2, 3]))], [2, 3, 4], "maps set items");
-};
-
-exports["test map two inputs"] = assert => {
-  let sum = (x, y) => x + y;
-  let xs = seq(function*() { yield 1; yield 2; yield 3; });
-  let ys = seq(function*() { yield 4; yield 5; yield 6; });
-
-  let zs = map(sum, xs, ys);
-
-  assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
-};
-
-exports["test map diff sized inputs"] = assert => {
-  let sum = (x, y) => x + y;
-  let xs = seq(function*() { yield 1; yield 2; yield 3; });
-  let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
-
-  let zs = map(sum, xs, ys);
-
-  assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
-  assert.deepEqual([...map(sum, ys, xs)], [5, 7, 9],
-                   "index of exhasting input is irrelevant");
-};
-
-exports["test map multi"] = assert => {
-  let sum = (x, y, z, w) => x + y + z + w;
-  let xs = seq(function*() { yield 1; yield 2; yield 3; yield 4; });
-  let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
-  let zs = seq(function*() { yield 10; yield 11; yield 12; });
-  let ws = seq(function*() { yield 0; yield 20; yield 40; yield 60; });
-
-  let actual = map(sum, xs, ys, zs, ws);
-
-  assert.deepEqual([...actual], [15, 38, 61], "summed numbers");
-};
-
-exports["test map errors"] = assert => {
-  assert.deepEqual([...map(boom, [])], [],
-                   "won't throw if empty");
-
-  const xs = map(boom, [1, 2, 4]);
-
-  assert.throws(() => [...xs], /Boom/, "propagates errors");
-
-  assert.throws(() => [...map(x => x, broken)], /Boom/,
-                "sequence errors propagate");
-};
-
-exports["test reductions"] = assert => {
-  let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
-
-  assert.deepEqual([...reductions(sum, [1, 1, 1, 1])],
-                   [1, 2, 3, 4],
-                   "works with arrays");
-  assert.deepEqual([...reductions(sum, 5, [1, 1, 1, 1])],
-                   [5, 6, 7, 8, 9],
-                   "array with initial");
-
-  assert.deepEqual([...reductions(sum, seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-  }))],
-  [1, 3, 6],
-  "works with sequences");
-
-  assert.deepEqual([...reductions(sum, 10, seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-  }))],
-  [10, 11, 13, 16],
-  "works with sequences");
-
-  assert.deepEqual([...reductions(sum, [])], [0],
-                   "invokes accumulator with no args");
-
-  assert.throws(() => [...reductions(boom, 1, [1])],
-                /Boom/,
-                "arg errors errors propagate");
-  assert.throws(() => [...reductions(sum, 1, broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-exports["test reduce"] = assert => {
- let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
-
-  assert.deepEqual(reduce(sum, [1, 2, 3, 4, 5]),
-                   15,
-                   "works with arrays");
-
-  assert.deepEqual(reduce(sum, seq(function*() {
-                     yield 1;
-                     yield 2;
-                     yield 3;
-                   })),
-                   6,
-                   "works with sequences");
-
-  assert.deepEqual(reduce(sum, 10, [1, 2, 3, 4, 5]),
-                   25,
-                   "works with array & initial");
-
-  assert.deepEqual(reduce(sum, 5, seq(function*() {
-                     yield 1;
-                     yield 2;
-                     yield 3;
-                   })),
-                   11,
-                   "works with sequences & initial");
-
-  assert.deepEqual(reduce(sum, []), 0, "reduce with no args");
-  assert.deepEqual(reduce(sum, "a", []), "a", "reduce with initial");
-  assert.deepEqual(reduce(sum, 1, [1]), 2, "reduce with single & initial");
-
-  assert.throws(() => [...reduce(boom, 1, [1])],
-                /Boom/,
-                "arg errors errors propagate");
-  assert.throws(() => [...reduce(sum, 1, broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-exports["test each"] = assert => {
-  const collect = xs => {
-    let result = [];
-    each((...etc) => result.push(...etc), xs);
-    return result;
-  };
-
-  assert.deepEqual(collect(null), [], "each ignores null");
-  assert.deepEqual(collect(void(0)), [], "each ignores void");
-
-  assert.deepEqual(collect([]), [], "each ignores empty");
-  assert.deepEqual(collect([1]), [1], "each works on single item arrays");
-  assert.deepEqual(collect([1, 2, 3, 4, 5]),
-                   [1, 2, 3, 4, 5],
-                   "works with arrays");
-
-  assert.deepEqual(collect(seq(function*() {
-                     yield 1;
-                     yield 2;
-                     yield 3;
-                   })),
-                   [1, 2, 3],
-                   "works with sequences");
-
-  assert.deepEqual(collect(""), [], "ignores empty strings");
-  assert.deepEqual(collect("a"), ["a"], "works on chars");
-  assert.deepEqual(collect("hello"), ["h", "e", "l", "l", "o"],
-                   "works on strings");
-
-  assert.deepEqual(collect(new Set()), [], "ignores empty sets");
-  assert.deepEqual(collect(new Set(["a"])), ["a"],
-                   "works on single item sets");
-  assert.deepEqual(collect(new Set([1, 2, 3])), [1, 2, 3],
-                   "works on muti item tests");
-
-  assert.deepEqual(collect(new Map()), [], "ignores empty maps");
-  assert.deepEqual(collect(new Map([["a", 1]])), [["a", 1]],
-                   "works on single mapping maps");
-  assert.deepEqual(collect(new Map([[1, 2], [3, 4], [5, 6]])),
-                   [[1, 2], [3, 4], [5, 6]],
-                   "works on muti mapping maps");
-
-  assert.throws(() => collect({}), "objects arn't supported");
-  assert.throws(() => collect(1), "numbers arn't supported");
-  assert.throws(() => collect(true), "booleas arn't supported");
-};
-
-exports["test count"] = assert => {
-  assert.equal(count(null), 0, "null counts to 0");
-  assert.equal(count(), 0, "undefined counts to 0");
-  assert.equal(count([]), 0, "empty array");
-  assert.equal(count([1, 2, 3]), 3, "non-empty array");
-  assert.equal(count(""), 0, "empty string");
-  assert.equal(count("hello"), 5, "non-empty string");
-  assert.equal(count(new Map()), 0, "empty map");
-  assert.equal(count(new Map([[1, 2], [2, 3]])), 2, "non-empty map");
-  assert.equal(count(new Set()), 0, "empty set");
-  assert.equal(count(new Set([1, 2, 3, 4])), 4, "non-empty set");
-  assert.equal(count(seq(function*() {})), 0, "empty sequence");
-  assert.equal(count(seq(function*() { yield 1; yield 2; })), 2,
-               "non-empty sequence");
-
-  assert.throws(() => count(broken),
-                /Boom/,
-                "sequence errors propagate");
-};
-
-exports["test isEmpty"] = assert => {
-  assert.equal(isEmpty(null), true, "null is empty");
-  assert.equal(isEmpty(), true, "undefined is empty");
-  assert.equal(isEmpty([]), true, "array is array");
-  assert.equal(isEmpty([1, 2, 3]), false, "array isn't empty");
-  assert.equal(isEmpty(""), true, "string is empty");
-  assert.equal(isEmpty("hello"), false, "non-empty string");
-  assert.equal(isEmpty(new Map()), true, "empty map");
-  assert.equal(isEmpty(new Map([[1, 2], [2, 3]])), false, "non-empty map");
-  assert.equal(isEmpty(new Set()), true, "empty set");
-  assert.equal(isEmpty(new Set([1, 2, 3, 4])), false , "non-empty set");
-  assert.equal(isEmpty(seq(function*() {})), true, "empty sequence");
-  assert.equal(isEmpty(seq(function*() { yield 1; yield 2; })), false,
-               "non-empty sequence");
-
-  assert.equal(isEmpty(broken), false, "hasn't reached error");
-};
-
-exports["test isEvery"] = assert => {
-  let isOdd = x => x % 2;
-  let isTrue = x => x === true;
-  let isFalse = x => x === false;
-
-  assert.equal(isEvery(isOdd, seq(function*() {
-    yield 1;
-    yield 3;
-    yield 5;
-  })), true, "all are odds");
-
-  assert.equal(isEvery(isOdd, seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-  })), false, "contains even");
-
-  assert.equal(isEvery(isTrue, seq(function*() {})), true, "true if empty");
-  assert.equal(isEvery(isFalse, seq(function*() {})), true, "true if empty");
-
-  assert.equal(isEvery(isTrue, null), true, "true for null");
-  assert.equal(isEvery(isTrue, undefined), true, "true for undefined");
-
-  assert.throws(() => isEvery(boom, [1, 2]),
-                /Boom/,
-                "arg errors errors propagate");
-  assert.throws(() => isEvery(x => true, broken),
-                /Boom/,
-                "sequence errors propagate");
-
-  assert.equal(isEvery(x => false, broken), false,
-              "hasn't reached error");
-};
-
-exports["test some"] = assert => {
-  let isOdd = x => x % 2;
-  let isTrue = x => x === true;
-  let isFalse = x => x === false;
-
-  assert.equal(some(isOdd, seq(function*() {
-    yield 2;
-    yield 4;
-    yield 6;
-  })), null, "all are even");
-
-  assert.equal(some(isOdd, seq(function*() {
-    yield 2;
-    yield 3;
-    yield 4;
-  })), true, "contains odd");
-
-  assert.equal(some(isTrue, seq(function*() {})), null,
-               "null if empty")
-  assert.equal(some(isFalse, seq(function*() {})), null,
-               "null if empty")
-
-  assert.equal(some(isTrue, null), null, "null for null");
-  assert.equal(some(isTrue, undefined), null, "null for undefined");
-
-  assert.throws(() => some(boom, [1, 2]),
-                /Boom/,
-                "arg errors errors propagate");
-  assert.throws(() => some(x => false, broken),
-                /Boom/,
-                "sequence errors propagate");
-
-  assert.equal(some(x => true, broken), true,
-              "hasn't reached error");
-};
-
-exports["test take"] = assert => {
-  let xs = seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-    yield 4;
-    yield 5;
-    yield 6;
-  });
-
-  assert.deepEqual([...take(3, xs)], [1, 2, 3], "took 3 items");
-  assert.deepEqual([...take(3, [1, 2, 3, 4, 5])], [1, 2, 3],
-                   "took 3 from array");
-
-  let ys = seq(function*() { yield 1; yield 2; });
-  assert.deepEqual([...take(3, ys)], [1, 2], "takes at max n");
-  assert.deepEqual([...take(3, [1, 2])], [1, 2],
-                   "takes at max n from arary");
-
-  let empty = seq(function*() {});
-  assert.deepEqual([...take(5, empty)], [], "nothing to take");
-
-  assert.throws(() => [...take(3, broken)],
-                /Boom/,
-                "sequence errors propagate");
-
-  assert.deepEqual([...take(1, broken)], [1],
-                   "hasn't reached error");
-};
-
-exports["test iterate"] = assert => {
-  let inc = x => x + 1;
-  let nums = iterate(inc, 0);
-
-  assert.deepEqual([...take(5, nums)], [0, 1, 2, 3, 4], "took 5");
-  assert.deepEqual([...take(10, nums)], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "took 10");
-
-  let xs = iterate(x => x * 3, 2);
-  assert.deepEqual([...take(4, xs)], [2, 6, 18, 54], "took 4");
-
-  assert.throws(() => [...iterate(boom, 0)],
-                /Boom/,
-                "function exceptions propagate");
-};
-
-exports["test takeWhile"] = assert => {
-  let isNegative = x => x < 0;
-  let xs = seq(function*() {
-    yield -2;
-    yield -1;
-    yield 0;
-    yield 1;
-    yield 2;
-    yield 3;
-  });
-
-  assert.deepEqual([...takeWhile(isNegative, xs)], [-2, -1],
-                   "took until 0");
-
-  let ys = seq(function*() {});
-  assert.deepEqual([...takeWhile(isNegative, ys)], [],
-                   "took none");
-
-  let zs = seq(function*() {
-    yield 0;
-    yield 1;
-    yield 2;
-    yield 3;
-  });
-
-  assert.deepEqual([...takeWhile(isNegative, zs)], [],
-                   "took none");
-
-  assert.throws(() => [...takeWhile(boom, zs)],
-                /Boom/,
-                "function errors errors propagate");
-  assert.throws(() => [...takeWhile(x => true, broken)],
-                /Boom/,
-                "sequence errors propagate");
-
-  assert.deepEqual([...takeWhile(x => false, broken)],
-                   [],
-                   "hasn't reached error");
-};
-
-exports["test drop"] = assert => {
-  let testDrop = xs => {
-    assert.deepEqual([...drop(2, xs)],
-                     [3, 4],
-                     "dropped two elements");
-
-    assert.deepEqual([...drop(1, xs)],
-                     [2, 3, 4],
-                     "dropped one");
-
-    assert.deepEqual([...drop(0, xs)],
-                     [1, 2, 3, 4],
-                     "dropped 0");
-
-    assert.deepEqual([...drop(-2, xs)],
-                     [1, 2, 3, 4],
-                     "dropped 0 on negative `n`");
-
-    assert.deepEqual([...drop(5, xs)],
-                     [],
-                     "dropped all items");
-  };
-
-  testDrop([1, 2, 3, 4]);
-  testDrop(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-    yield 4;
-  }));
-
-  assert.throws(() => [...drop(1, broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test dropWhile"] = assert => {
-  let isNegative = x => x < 0;
-  let True = _ => true;
-  let False = _ => false;
-
-  let test = xs => {
-    assert.deepEqual([...dropWhile(isNegative, xs)],
-                     [0, 1, 2],
-                     "dropped negative");
-
-    assert.deepEqual([...dropWhile(True, xs)],
-                     [],
-                     "drop all");
-
-    assert.deepEqual([...dropWhile(False, xs)],
-                     [-2, -1, 0, 1, 2],
-                     "keep all");
-  };
-
-  test([-2, -1, 0, 1, 2]);
-  test(seq(function*() {
-    yield -2;
-    yield -1;
-    yield 0;
-    yield 1;
-    yield 2;
-  }));
-
-  assert.throws(() => [...dropWhile(boom, [1, 2, 3])],
-                /Boom/,
-                "function errors errors propagate");
-  assert.throws(() => [...dropWhile(x => true, broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test concat"] = assert => {
-  let test = (a, b, c, d) => {
-    assert.deepEqual([...concat()],
-                     [],
-                     "nothing to concat");
-    assert.deepEqual([...concat(a)],
-                     [1, 2, 3],
-                     "concat with nothing returns same as first");
-    assert.deepEqual([...concat(a, b)],
-                     [1, 2, 3, 4, 5],
-                     "concat items from both");
-    assert.deepEqual([...concat(a, b, a)],
-                     [1, 2, 3, 4, 5, 1, 2, 3],
-                     "concat itself");
-    assert.deepEqual([...concat(c)],
-                     [],
-                     "concat of empty is empty");
-    assert.deepEqual([...concat(a, c)],
-                     [1, 2, 3],
-                     "concat with empty");
-    assert.deepEqual([...concat(c, c, c)],
-                     [],
-                     "concat of empties is empty");
-    assert.deepEqual([...concat(c, b)],
-                     [4, 5],
-                     "empty can be in front");
-    assert.deepEqual([...concat(d)],
-                     [7],
-                     "concat singular");
-    assert.deepEqual([...concat(d, d)],
-                     [7, 7],
-                     "concat singulars");
-
-    assert.deepEqual([...concat(a, a, b, c, d, c, d, d)],
-                     [1, 2, 3, 1, 2, 3, 4, 5, 7, 7, 7],
-                     "many concats");
-
-    let ab = concat(a, b);
-    let abcd = concat(ab, concat(c, d));
-    let cdabcd = concat(c, d, abcd);
-
-    assert.deepEqual([...cdabcd],
-                     [7, 1, 2, 3, 4, 5, 7],
-                     "nested concats");
-  };
-
-  test([1, 2, 3],
-       [4, 5],
-       [],
-       [7]);
-
-  test(seq(function*() { yield 1; yield 2; yield 3; }),
-       seq(function*() { yield 4; yield 5; }),
-       seq(function*() { }),
-       seq(function*() { yield 7; }));
-
-  assert.throws(() => [...concat(broken, [1, 2, 3])],
-                /Boom/,
-                "function errors errors propagate");
-};
-
-
-exports["test first"] = assert => {
-  let test = (xs, empty) => {
-    assert.equal(first(xs), 1, "returns first");
-    assert.equal(first(empty), null, "returns null empty");
-  };
-
-  test("1234", "");
-  test([1, 2, 3], []);
-  test([1, 2, 3], null);
-  test([1, 2, 3], undefined);
-  test(seq(function*() { yield 1; yield 2; yield 3; }),
-       seq(function*() { }));
-  assert.equal(first(broken), 1, "did not reached error");
-};
-
-exports["test rest"] = assert => {
-  let test = (xs, x, nil) => {
-    assert.deepEqual([...rest(xs)], ["b", "c"],
-                     "rest items");
-    assert.deepEqual([...rest(x)], [],
-                     "empty when singular");
-    assert.deepEqual([...rest(nil)], [],
-                     "empty when empty");
-  };
-
-  test("abc", "a", "");
-  test(["a", "b", "c"], ["d"], []);
-  test(seq(function*() { yield "a"; yield "b"; yield "c"; }),
-       seq(function*() { yield "d"; }),
-       seq(function*() {}));
-  test(["a", "b", "c"], ["d"], null);
-  test(["a", "b", "c"], ["d"], undefined);
-
-  assert.throws(() => [...rest(broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test nth"] = assert => {
-  let notFound = {};
-  let test = xs => {
-    assert.equal(nth(xs, 0), "h", "first");
-    assert.equal(nth(xs, 1), "e", "second");
-    assert.equal(nth(xs, 5), void(0), "out of bound");
-    assert.equal(nth(xs, 5, notFound), notFound, "out of bound");
-    assert.equal(nth(xs, -1), void(0), "out of bound");
-    assert.equal(nth(xs, -1, notFound), notFound, "out of bound");
-    assert.equal(nth(xs, 4), "o", "5th");
-  };
-
-  let testEmpty = xs => {
-    assert.equal(nth(xs, 0), void(0), "no first in empty");
-    assert.equal(nth(xs, 5), void(0), "no 5th in empty");
-    assert.equal(nth(xs, 0, notFound), notFound, "notFound on out of bound");
-  };
-
-  test("hello");
-  test(["h", "e", "l", "l", "o"]);
-  test(seq(function*() {
-    yield "h";
-    yield "e";
-    yield "l";
-    yield "l";
-    yield "o";
-  }));
-  testEmpty(null);
-  testEmpty(undefined);
-  testEmpty([]);
-  testEmpty("");
-  testEmpty(seq(function*() {}));
-
-
-  assert.throws(() => nth(broken, 1),
-                /Boom/,
-                "sequence errors propagate");
-  assert.equal(nth(broken, 0), 1, "have not reached error");
-};
-
-
-exports["test last"] = assert => {
-  assert.equal(last(null), null, "no last in null");
-  assert.equal(last(void(0)), null, "no last in undefined");
-  assert.equal(last([]), null, "no last in []");
-  assert.equal(last(""), null, "no last in ''");
-  assert.equal(last(seq(function*() { })), null, "no last in empty");
-
-  assert.equal(last("hello"), "o", "last from string");
-  assert.equal(last([1, 2, 3]), 3, "last from array");
-  assert.equal(last([1]), 1, "last from singular");
-  assert.equal(last(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-  })), 3, "last from sequence");
-
-  assert.throws(() => last(broken),
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test dropLast"] = assert => {
-  let test = xs => {
-    assert.deepEqual([...dropLast(xs)],
-                     [1, 2, 3, 4],
-                     "dropped last");
-    assert.deepEqual([...dropLast(0, xs)],
-                     [1, 2, 3, 4, 5],
-                     "dropped none on 0");
-    assert.deepEqual([...dropLast(-3, xs)],
-                     [1, 2, 3, 4, 5],
-                     "drop none on negative");
-    assert.deepEqual([...dropLast(3, xs)],
-                     [1, 2],
-                     "dropped given number");
-    assert.deepEqual([...dropLast(5, xs)],
-                     [],
-                     "dropped all");
-  };
-
-  let testEmpty = xs => {
-    assert.deepEqual([...dropLast(xs)],
-                     [],
-                     "nothing to drop");
-    assert.deepEqual([...dropLast(0, xs)],
-                     [],
-                     "dropped none on 0");
-    assert.deepEqual([...dropLast(-3, xs)],
-                     [],
-                     "drop none on negative");
-    assert.deepEqual([...dropLast(3, xs)],
-                     [],
-                     "nothing to drop");
-  };
-
-  test([1, 2, 3, 4, 5]);
-  test(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-    yield 4;
-    yield 5;
-  }));
-  testEmpty([]);
-  testEmpty("");
-  testEmpty(seq(function*() {}));
-
-  assert.throws(() => [...dropLast(broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test distinct"] = assert => {
-  let test = (xs, message) => {
-    assert.deepEqual([...distinct(xs)],
-                     [1, 2, 3, 4, 5],
-                     message);
-  };
-
-  test([1, 2, 1, 3, 1, 4, 1, 5], "works with arrays");
-  test(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 1;
-    yield 3;
-    yield 1;
-    yield 4;
-    yield 1;
-    yield 5;
-  }), "works with sequences");
-  test(new Set([1, 2, 1, 3, 1, 4, 1, 5]),
-       "works with sets");
-  test(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 2;
-    yield 2;
-    yield 1;
-    yield 3;
-    yield 1;
-    yield 4;
-    yield 4;
-    yield 4;
-    yield 1;
-    yield 5;
-  }), "works with multiple repeatitions");
-  test([1, 2, 3, 4, 5], "work with distinct arrays");
-  test(seq(function*() {
-    yield 1;
-    yield 2;
-    yield 3;
-    yield 4;
-    yield 5;
-  }), "works with distinct seqs");
-};
-
-
-exports["test remove"] = assert => {
-  let isPositive = x => x > 0;
-  let test = xs => {
-    assert.deepEqual([...remove(isPositive, xs)],
-                     [-2, -1, 0],
-                     "removed positives");
-  };
-
-  test([1, -2, 2, -1, 3, 7, 0]);
-  test(seq(function*() {
-    yield 1;
-    yield -2;
-    yield 2;
-    yield -1;
-    yield 3;
-    yield 7;
-    yield 0;
-  }));
-
-  assert.throws(() => [...distinct(broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-
-exports["test mapcat"] = assert => {
-  let upto = n => seq(function* () {
-    let index = 0;
-    while (index < n) {
-      yield index;
-      index = index + 1;
-    }
-  });
-
-  assert.deepEqual([...mapcat(upto, [1, 2, 3, 4])],
-                   [0, 0, 1, 0, 1, 2, 0, 1, 2, 3],
-                   "expands given sequence");
-
-  assert.deepEqual([...mapcat(upto, [0, 1, 2, 0])],
-                   [0, 0, 1],
-                   "expands given sequence");
-
-  assert.deepEqual([...mapcat(upto, [0, 0, 0])],
-                   [],
-                   "expands given sequence");
-
-  assert.deepEqual([...mapcat(upto, [])],
-                   [],
-                   "nothing to expand");
-
-  assert.deepEqual([...mapcat(upto, null)],
-                   [],
-                   "nothing to expand");
-
-  assert.deepEqual([...mapcat(upto, void(0))],
-                   [],
-                   "nothing to expand");
-
-  let xs = seq(function*() {
-    yield 0;
-    yield 1;
-    yield 0;
-    yield 2;
-    yield 0;
-  });
-
-  assert.deepEqual([...mapcat(upto, xs)],
-                   [0, 0, 1],
-                   "expands given sequence");
-
-  assert.throws(() => [...mapcat(boom, xs)],
-                /Boom/,
-                "function errors errors propagate");
-  assert.throws(() => [...mapcat(upto, broken)],
-                /Boom/,
-                "sequence errors propagate");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-set-exports.js
+++ /dev/null
@@ -1,37 +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 four = require("./modules/exportsEquals");
-exports.testExportsEquals = function(assert) {
-  assert.equal(four, 4);
-};
-
-/* TODO: Discuss idea of dropping support for this feature that was alternative
-         to `module.exports = ..` that failed.
-var five = require("./modules/setExports");
-exports.testSetExports = function(assert) {
-  assert.equal(five, 5);
-}
-
-exports.testDupeSetExports = function(assert) {
-  var passed = false;
-  try {
-    var dupe = require('./modules/dupeSetExports');
-  } catch(e) {
-    passed = /define\(\) was used, so module\.exports= and module\.setExports\(\) may not be used/.test(e.toString());
-  }
-  assert.equal(passed, true, 'define() or setExports(), not both');
-}
-*/
-
-exports.testModule = function(assert) {
-  // module.id is not cast in stone yet. In the future, it may include the
-  // package name, or may possibly be a/ URL of some sort. For now, it's a
-  // URL that starts with resource: and ends with this module name, but the
-  // part in between varies depending upon how the test is run.
-  var found = /test-set-exports$/.test(module.id);
-  assert.equal(found, true, module.id+" ends with test-set-exports.js");
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-shared-require.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require("chrome");
-
-const requireURI = require.resolve("toolkit/require.js");
-
-const jsm = Cu.import(requireURI, {});
-
-exports.testRequire = assert => {
-  assert.equal(typeof(jsm.require), "function",
-               "require is a function");
-  assert.equal(typeof(jsm.require.resolve), "function",
-               "require.resolve is a function");
-
-  assert.equal(typeof(jsm.require("method/core")), "function",
-               "can import modules that aren't under sdk");
-
-  assert.equal(typeof(jsm.require("sdk/base64").encode), "function",
-               "can import module from sdk");
-};
-
-const required = require("toolkit/require")
-
-exports.testSameRequire = (assert) => {
-  assert.equal(jsm.require("method/core"),
-               required.require("method/core"),
-               "jsm and module return same instance");
-
-  assert.equal(jsm.require, required.require,
-               "require function is same in both contexts");
-};
-
-require("sdk/test").run(exports)
deleted file mode 100644
--- a/addon-sdk/source/test/test-simple-prefs.js
+++ /dev/null
@@ -1,331 +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 { Loader } = require("sdk/test/loader");
-const { setTimeout } = require("sdk/timers");
-const { emit } = require("sdk/system/events");
-const simplePrefs = require("sdk/simple-prefs");
-const { prefs: sp } = simplePrefs;
-const { defer, resolve, reject, all } = require("sdk/core/promise");
-const AddonInstaller = require("sdk/addon/installer");
-const fixtures = require("./fixtures");
-const { pathFor } = require("sdk/system");
-const file = require("sdk/io/file");
-const { install, uninstall } = require("sdk/addon/installer");
-const { open } = require('sdk/preferences/utils');
-const { toFilename } = require('sdk/url');
-const { getAddonByID } = require('sdk/addon/manager');
-const { ZipWriter } = require('./zip/utils');
-const { getTabForId } = require('sdk/tabs/utils');
-const { preferencesBranch, id } = require('sdk/self');
-const { modelFor } = require('sdk/model/core');
-require('sdk/tabs');
-
-const prefsrv = Cc['@mozilla.org/preferences-service;1'].
-                    getService(Ci.nsIPrefService);
-
-const specialChars = "!@#$%^&*()_-=+[]{}~`\'\"<>,./?;:";
-
-exports.testIterations = function(assert) {
-  sp["test"] = true;
-  sp["test.test"] = true;
-  let prefAry = [];
-  for (var name in sp ) {
-    prefAry.push(name);
-  }
-  assert.ok("test" in sp);
-  assert.ok(!sp.getPropertyDescriptor);
-  assert.ok(Object.prototype.hasOwnProperty.call(sp, "test"));
-  assert.equal(["test", "test.test"].toString(), prefAry.filter((i) => !/^sdk\./.test(i)).sort().toString(), "for (x in y) part 1/2 works");
-  assert.equal(["test", "test.test"].toString(), Object.keys(sp).filter((i) => !/^sdk\./.test(i)).sort().toString(), "Object.keys works");
-
-  delete sp["test"];
-  delete sp["test.test"];
-  prefAry = [];
-  for (var name in sp ) {
-    prefAry.push(name);
-  }
-  assert.equal([].toString(), prefAry.filter((i) => !/^sdk\./.test(i)).toString(), "for (x in y) part 2/2 works");
-}
-
-exports.testSetGetBool = function(assert) {
-  assert.equal(sp.test, undefined, "Value should not exist");
-  sp.test = true;
-  assert.ok(sp.test, "Value read should be the value previously set");
-  delete sp.test;
-};
-
-// TEST: setting and getting preferences with special characters work
-exports.testSpecialChars = function(assert, done) {
-  let chars = specialChars.split("");
-  let len = chars.length;
-
-  let count = 0;
-  chars.forEach(function(char) {
-    let rand = Math.random() + "";
-    simplePrefs.on(char, function onPrefChanged() {
-      simplePrefs.removeListener(char, onPrefChanged);
-      assert.equal(sp[char], rand, "setting pref with a name that is a special char, " + char + ", worked!");
-      delete sp[char];
-
-      // end test
-      if (++count == len)
-        done();
-    })
-    sp[char] = rand;
-  });
-};
-
-exports.testSetGetInt = function(assert) {
-  assert.equal(sp["test-int"], undefined, "Value should not exist");
-  sp["test-int"] = 1;
-  assert.equal(sp["test-int"], 1, "Value read should be the value previously set");
-  delete sp["test-int"];
-};
-
-exports.testSetComplex = function(assert) {
-  try {
-    sp["test-complex"] = {test: true};
-    assert.fail("Complex values are not allowed");
-  }
-  catch (e) {
-    assert.pass("Complex values are not allowed");
-  }
-};
-
-exports.testSetGetString = function(assert) {
-  assert.equal(sp["test-string"], undefined, "Value should not exist");
-  sp["test-string"] = "test";
-  assert.equal(sp["test-string"], "test", "Value read should be the value previously set");
-  delete sp["test-string"];
-};
-
-exports.testHasAndRemove = function(assert) {
-  sp.test = true;
-  assert.ok(("test" in sp), "Value exists");
-  delete sp.test;
-  assert.equal(sp.test, undefined, "Value should be undefined");
-};
-
-exports.testPrefListener = function(assert, done) {
-  let listener = function(prefName) {
-    simplePrefs.removeListener('test-listener', listener);
-    assert.equal(prefName, "test-listen", "The prefs listener heard the right event");
-    delete sp["test-listen"];
-    done();
-  };
-
-  simplePrefs.on("test-listen", listener);
-
-  sp["test-listen"] = true;
-
-  // Wildcard listen
-  let toSet = ['wildcard1','wildcard.pref2','wildcard.even.longer.test'];
-  let observed = [];
-
-  let wildlistener = function(prefName) {
-    if (toSet.indexOf(prefName) > -1) observed.push(prefName);
-  };
-
-  simplePrefs.on('',wildlistener);
-
-  toSet.forEach(function(pref) {
-    sp[pref] = true;
-    delete sp[pref];
-  });
-
-  assert.ok((observed.length === 6 && toSet.length === 3),
-      "Wildcard lengths inconsistent" + JSON.stringify([observed.length, toSet.length]));
-
-  toSet.forEach(function(pref,ii) {
-    assert.equal(observed[2*ii], pref, "Wildcard observed " + pref);
-  });
-
-  simplePrefs.removeListener('',wildlistener);
-
-};
-
-exports.testBtnListener = function(assert, done) {
-  let name = "test-btn-listen";
-  simplePrefs.on(name, function listener() {
-    simplePrefs.removeListener(name, listener);
-    assert.pass("Button press event was heard");
-    done();
-  });
-  emit((id + "-cmdPressed"), { subject: "", data: name });
-};
-
-exports.testPrefRemoveListener = function(assert, done) {
-  let counter = 0;
-
-  let listener = function() {
-    assert.pass("The prefs listener was not removed yet");
-
-    if (++counter > 1)
-      assert.fail("The prefs listener was not removed");
-
-    simplePrefs.removeListener("test-listen2", listener);
-
-    sp["test-listen2"] = false;
-
-    setTimeout(function() {
-      assert.pass("The prefs listener was removed");
-      delete sp["test-listen2"];
-      done();
-    }, 250);
-  };
-
-  simplePrefs.on("test-listen2", listener);
-
-  // emit change
-  sp["test-listen2"] = true;
-};
-
-// Bug 710117: Test that simple-pref listeners are removed on unload
-exports.testPrefUnloadListener = function(assert, done) {
-  let loader = Loader(module);
-  let sp = loader.require("sdk/simple-prefs");
-  let counter = 0;
-
-  let listener = function() {
-    assert.equal(++counter, 1, "This listener should only be called once");
-
-    loader.unload();
-
-    // this may not execute after unload, but definitely shouldn't fire listener
-    sp.prefs["test-listen3"] = false;
-    // this should execute, but also definitely shouldn't fire listener
-    require("sdk/simple-prefs").prefs["test-listen3"] = false;
-
-    delete sp.prefs["test-listen3"];
-    done();
-  };
-
-  sp.on("test-listen3", listener);
-
-  // emit change
-  sp.prefs["test-listen3"] = true;
-};
-
-
-// Bug 710117: Test that simple-pref listeners are removed on unload
-exports.testPrefUnloadWildcardListener = function(assert, done) {
-  let testpref = "test-wildcard-unload-listener";
-  let loader = Loader(module);
-  let sp = loader.require("sdk/simple-prefs");
-  let counter = 0;
-
-  let listener = function() {
-    assert.equal(++counter, 1, "This listener should only be called once");
-
-    loader.unload();
-
-    // this may not execute after unload, but definitely shouldn't fire listener
-    sp.prefs[testpref] = false;
-    // this should execute, but also definitely shouldn't fire listener
-    require("sdk/simple-prefs").prefs[testpref] = false;
-
-    delete sp.prefs[testpref];
-    done();
-  };
-
-  sp.on("", listener);
-  // emit change
-  sp.prefs[testpref] = true;
-};
-
-
-// Bug 732919 - JSON.stringify() fails on simple-prefs.prefs
-exports.testPrefJSONStringification = function(assert) {
-  var sp = require("sdk/simple-prefs").prefs;
-  assert.equal(
-      Object.keys(sp).join(),
-      Object.keys(JSON.parse(JSON.stringify(sp))).join(),
-      "JSON stringification should work.");
-};
-
-exports.testUnloadOfDynamicPrefGeneration = function*(assert) {
-  let loader = Loader(module);
-  let branch = prefsrv.getDefaultBranch('extensions.' + preferencesBranch);
-
-  let { enable } = loader.require("sdk/preferences/native-options");
-
-  let addon_id = "test-bootstrap-addon@mozilla.com";
-  let xpi_path = file.join(pathFor("ProfD"), addon_id + ".xpi");
-
-  // zip the add-on
-  let zip = new ZipWriter(xpi_path);
-  assert.pass("start creating the blank xpi");
-  zip.addFile("", toFilename(fixtures.url("bootstrap-addon/")));
-  yield zip.close();
-
-  // insatll the add-on
-  let id = yield install(xpi_path);
-  assert.pass('installed');
-
-  // get the addon
-  let addon = yield getAddonByID(id);
-  assert.equal(id, addon.id, 'addon id: ' + id);
-
-  addon.userDisabled = false;
-  assert.ok(!addon.userDisabled, 'the add-on is enabled');
-  assert.ok(addon.isActive, 'the add-on is active');
-
-  // setup dynamic prefs
-  yield enable({
-    id: addon.id,
-    preferences: [{
-      "name": "test",
-      "description": "test",
-      "title": "Test",
-      "type": "string",
-      "value": "default"
-    }, {
-      "name": "test-int",
-      "description": "test",
-      "type": "integer",
-      "value": 5,
-      "title": "How Many?"
-    }]
-  });
-
-  assert.pass('enabled prefs');
-
-  // show inline prefs
-  let { tabId, document } = yield open(addon);
-  assert.pass('opened');
-
-  // confirm dynamic pref generation did occur
-  let results = document.querySelectorAll("*[data-jetpack-id=\"" + id + "\"]");
-  assert.ok(results.length > 0, "the prefs were setup");
-
-  // unload dynamic prefs
-  loader.unload();
-  assert.pass('unload');
-
-  // hide and show the inline prefs
-  let { promise, resolve } = defer();
-  modelFor(getTabForId(tabId)).close(resolve);
-  yield promise;
-
-  // reopen the add-on prefs page
-  ({ tabId, document } = yield open(addon));
-
-  // confirm dynamic pref generation did not occur
-  ({ promise, resolve } = defer());
-  results = document.querySelectorAll("*[data-jetpack-id=\"" + id + "\"]");
-  assert.equal(0, results.length, "the prefs were not setup after unload");
-  modelFor(getTabForId(tabId)).close(resolve);
-  yield promise;
-
-  // uninstall the add-on
-  yield uninstall(id);
-
-  // delete the pref branch
-  branch.deleteBranch('');
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-simple-storage.js
+++ /dev/null
@@ -1,322 +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 file = require("sdk/io/file");
-const prefs = require("sdk/preferences/service");
-
-const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
-
-var {Cc,Ci} = require("chrome");
-
-const { Loader } = require("sdk/test/loader");
-const { id } = require("sdk/self");
-
-var storeFile = Cc["@mozilla.org/file/directory_service;1"].
-                getService(Ci.nsIProperties).
-                get("ProfD", Ci.nsIFile);
-storeFile.append("jetpack");
-storeFile.append(id);
-storeFile.append("simple-storage");
-file.mkpath(storeFile.path);
-storeFile.append("store.json");
-var storeFilename = storeFile.path;
-
-function manager(loader) {
-  return loader.sandbox("sdk/simple-storage").manager;
-}
-
-exports.testSetGet = function (assert, done) {
-  // Load the module once, set a value.
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  manager(loader).jsonStore.onWrite = function (storage) {
-    assert.ok(file.exists(storeFilename), "Store file should exist");
-
-    // Load the module again and make sure the value stuck.
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    manager(loader).jsonStore.onWrite = function (storage) {
-      file.remove(storeFilename);
-      done();
-    };
-    assert.equal(ss.storage.foo, val, "Value should persist");
-    loader.unload();
-  };
-  let val = "foo";
-  ss.storage.foo = val;
-  assert.equal(ss.storage.foo, val, "Value read should be value set");
-  loader.unload();
-};
-
-exports.testSetGetRootArray = function (assert, done) {
-  setGetRoot(assert, done, [1, 2, 3], function (arr1, arr2) {
-    if (arr1.length !== arr2.length)
-      return false;
-    for (let i = 0; i < arr1.length; i++) {
-      if (arr1[i] !== arr2[i])
-        return false;
-    }
-    return true;
-  });
-};
-
-exports.testSetGetRootBool = function (assert, done) {
-  setGetRoot(assert, done, true);
-};
-
-exports.testSetGetRootFunction = function (assert, done) {
-  setGetRootError(assert, done, function () {},
-                  "Setting storage to a function should fail");
-};
-
-exports.testSetGetRootNull = function (assert, done) {
-  setGetRoot(assert, done, null);
-};
-
-exports.testSetGetRootNumber = function (assert, done) {
-  setGetRoot(assert, done, 3.14);
-};
-
-exports.testSetGetRootObject = function (assert, done) {
-  setGetRoot(assert, done, { foo: 1, bar: 2 }, function (obj1, obj2) {
-    for (let prop in obj1) {
-      if (!(prop in obj2) || obj2[prop] !== obj1[prop])
-        return false;
-    }
-    for (let prop in obj2) {
-      if (!(prop in obj1) || obj1[prop] !== obj2[prop])
-        return false;
-    }
-    return true;
-  });
-};
-
-exports.testSetGetRootString = function (assert, done) {
-  setGetRoot(assert, done, "sho' 'nuff");
-};
-
-exports.testSetGetRootUndefined = function (assert, done) {
-  setGetRootError(assert, done, undefined, "Setting storage to undefined should fail");
-};
-
-exports.testEmpty = function (assert) {
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  loader.unload();
-  assert.ok(!file.exists(storeFilename), "Store file should not exist");
-};
-
-exports.testStorageDataRecovery = function(assert) {
-  const data = { 
-    a: true,
-    b: [3, 13],
-    c: "guilty!",
-    d: { e: 1, f: 2 }
-  };
-  let stream = file.open(storeFilename, "w");
-  stream.write(JSON.stringify(data));
-  stream.close();
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  assert.deepEqual(ss.storage, data, "Recovered data should be the same as written");
-  file.remove(storeFilename);
-  loader.unload();
-}
-
-exports.testMalformed = function (assert) {
-  let stream = file.open(storeFilename, "w");
-  stream.write("i'm not json");
-  stream.close();
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  let empty = true;
-  for (let key in ss.storage) {
-    empty = false;
-    break;
-  }
-  assert.ok(empty, "Malformed storage should cause root to be empty");
-  file.remove(storeFilename);
-  loader.unload();
-};
-
-// Go over quota and handle it by listener.
-exports.testQuotaExceededHandle = function (assert, done) {
-  prefs.set(QUOTA_PREF, 18);
-
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  ss.on("OverQuota", function () {
-    assert.pass("OverQuota was emitted as expected");
-    assert.equal(this, ss, "`this` should be simple storage");
-    ss.storage = { x: 4, y: 5 };
-
-    manager(loader).jsonStore.onWrite = function () {
-      loader = Loader(module);
-      ss = loader.require("sdk/simple-storage");
-      let numProps = 0;
-      for (let prop in ss.storage)
-        numProps++;
-      assert.ok(numProps, 2,
-                  "Store should contain 2 values: " + ss.storage.toSource());
-      assert.equal(ss.storage.x, 4, "x value should be correct");
-      assert.equal(ss.storage.y, 5, "y value should be correct");
-      manager(loader).jsonStore.onWrite = function (storage) {
-        prefs.reset(QUOTA_PREF);
-        done();
-      };
-      loader.unload();
-    };
-    loader.unload();
-  });
-  // This will be JSON.stringify()ed to: {"a":1,"b":2,"c":3} (19 bytes)
-  ss.storage = { a: 1, b: 2, c: 3 };
-  manager(loader).jsonStore.write();
-};
-
-// Go over quota but don't handle it.  The last good state should still persist.
-exports.testQuotaExceededNoHandle = function (assert, done) {
-  prefs.set(QUOTA_PREF, 5);
-
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-
-  manager(loader).jsonStore.onWrite = function (storage) {
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    assert.equal(ss.storage, val,
-                     "Value should have persisted: " + ss.storage);
-    ss.storage = "some very long string that is very long";
-    ss.on("OverQuota", function () {
-      assert.pass("OverQuota emitted as expected");
-      manager(loader).jsonStore.onWrite = function () {
-        assert.fail("Over-quota value should not have been written");
-      };
-      loader.unload();
-
-      loader = Loader(module);
-      ss = loader.require("sdk/simple-storage");
-      assert.equal(ss.storage, val,
-                       "Over-quota value should not have been written, " +
-                       "old value should have persisted: " + ss.storage);
-      loader.unload();
-      prefs.reset(QUOTA_PREF);
-      done();
-    });
-    manager(loader).jsonStore.write();
-  };
-
-  let val = "foo";
-  ss.storage = val;
-  loader.unload();
-};
-
-exports.testQuotaUsage = function (assert, done) {
-  let quota = 21;
-  prefs.set(QUOTA_PREF, quota);
-
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-
-  // {"a":1} (7 bytes)
-  ss.storage = { a: 1 };
-  assert.equal(ss.quotaUsage, 7 / quota, "quotaUsage should be correct");
-
-  // {"a":1,"bb":2} (14 bytes)
-  ss.storage = { a: 1, bb: 2 };
-  assert.equal(ss.quotaUsage, 14 / quota, "quotaUsage should be correct");
-
-  // {"a":1,"bb":2,"cc":3} (21 bytes)
-  ss.storage = { a: 1, bb: 2, cc: 3 };
-  assert.equal(ss.quotaUsage, 21 / quota, "quotaUsage should be correct");
-
-  manager(loader).jsonStore.onWrite = function () {
-    prefs.reset(QUOTA_PREF);
-    done();
-  };
-  loader.unload();
-};
-
-exports.testUninstall = function (assert, done) {
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  manager(loader).jsonStore.onWrite = function () {
-    assert.ok(file.exists(storeFilename), "Store file should exist");
-
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    loader.unload("uninstall");
-    assert.ok(!file.exists(storeFilename), "Store file should be removed");
-    done();
-  };
-  ss.storage.foo = "foo";
-  loader.unload();
-};
-
-exports.testSetNoSetRead = function (assert, done) {
-  // Load the module, set a value.
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  manager(loader).jsonStore.onWrite = function (storage) {
-    assert.ok(file.exists(storeFilename), "Store file should exist");
-
-    // Load the module again but don't access ss.storage.
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    manager(loader).jsonStore.onWrite = function (storage) {
-      assert.fail("Nothing should be written since `storage` was not accessed.");
-    };
-    loader.unload();
-
-    // Load the module a third time and make sure the value stuck.
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    manager(loader).jsonStore.onWrite = function (storage) {
-      file.remove(storeFilename);
-      done();
-    };
-    assert.equal(ss.storage.foo, val, "Value should persist");
-    loader.unload();
-  };
-  let val = "foo";
-  ss.storage.foo = val;
-  assert.equal(ss.storage.foo, val, "Value read should be value set");
-  loader.unload();
-};
-
-
-function setGetRoot(assert, done, val, compare) {
-  compare = compare || ((a, b) => a === b);
-
-  // Load the module once, set a value.
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  manager(loader).jsonStore.onWrite = function () {
-    assert.ok(file.exists(storeFilename), "Store file should exist");
-
-    // Load the module again and make sure the value stuck.
-    loader = Loader(module);
-    ss = loader.require("sdk/simple-storage");
-    manager(loader).jsonStore.onWrite = function () {
-      file.remove(storeFilename);
-      done();
-    };
-    assert.ok(compare(ss.storage, val), "Value should persist");
-    loader.unload();
-  };
-  ss.storage = val;
-  assert.ok(compare(ss.storage, val), "Value read should be value set");
-  loader.unload();
-}
-
-function setGetRootError(assert, done, val, msg) {
-  let pred = new RegExp("storage must be one of the following types: " +
-             "array, boolean, null, number, object, string");
-  let loader = Loader(module);
-  let ss = loader.require("sdk/simple-storage");
-  assert.throws(() => ss.storage = val, pred, msg);
-  done();
-  loader.unload();
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-system-events.js
+++ /dev/null
@@ -1,280 +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 events = require("sdk/system/events");
-const self = require("sdk/self");
-const { Cc, Ci, Cu } = require("chrome");
-const { setTimeout } = require("sdk/timers");
-const { Loader, LoaderWithHookedConsole2 } = require("sdk/test/loader");
-const nsIObserverService = Cc["@mozilla.org/observer-service;1"].
-                           getService(Ci.nsIObserverService);
-
-var isConsoleEvent = (topic) =>
-  !!~["console-api-log-event", "console-storage-cache-event"].indexOf(topic)
-
-exports["test basic"] = function(assert) {
-  let type = Date.now().toString(32);
-
-  let timesCalled = 0;
-  function handler({subject, data}) { timesCalled++; };
-
-  events.on(type, handler);
-  events.emit(type, { data: "yo yo" });
-
-  assert.equal(timesCalled, 1, "event handler was called");
-
-  events.off(type, handler);
-  events.emit(type, { data: "no way" });
-
-  assert.equal(timesCalled, 1, "removed handler is no longer called");
-
-  events.once(type, handler);
-  events.emit(type, { data: "and we meet again" });
-  events.emit(type, { data: "it's always hard to say bye" });
-
-  assert.equal(timesCalled, 2, "handlers added via once are triggered once");
-}
-
-exports["test simple argument passing"] = function (assert) {
-  let type = Date.now().toString(32);
-
-  let lastArg;
-  function handler({data}) { lastArg = data; }
-  events.on(type, handler);
-
-  [true, false, 100, 0, 'a string', ''].forEach(arg => {
-    events.emit(type, arg);
-    assert.strictEqual(lastArg, arg + '',
-      'event emitted for ' + arg + ' has correct data value');
-
-    events.emit(type, { data: arg });
-    assert.strictEqual(lastArg, arg + '',
-      'event emitted for ' + arg + ' has correct data value when a property on an object');
-  });
-
-  [null, undefined, {}].forEach(arg => {
-    events.emit(type, arg);
-    assert.strictEqual(lastArg, null,
-      'emitting ' + arg + ' gets null data');
-  });
-
-  events.off(type, handler);
-};
-
-exports["test error reporting"] = function(assert) {
-  let { loader, messages } = LoaderWithHookedConsole2(module);
-
-  let events = loader.require("sdk/system/events");
-  function brokenHandler(subject, data) { throw new Error("foo"); };
-
-  let lineNumber;
-  try { brokenHandler() } catch (error) { lineNumber = error.lineNumber }
-
-  let errorType = Date.now().toString(32);
-
-  events.on(errorType, brokenHandler);
-  events.emit(errorType, { data: "yo yo" });
-
-  assert.equal(messages.length, 2, "Got an exception");
-  assert.equal(messages[0], "console.error: " + self.name + ": \n",
-               "error is logged");
-  let text = messages[1];
-  assert.ok(text.indexOf("Error: foo") >= 0, "error message is logged");
-  assert.ok(text.indexOf(module.uri) >= 0, "module uri is logged");
-  assert.ok(text.indexOf(lineNumber) >= 0, "error line is logged");
-
-  events.off(errorType, brokenHandler);
-
-  loader.unload();
-};
-
-exports["test listeners are GC-ed"] = function(assert, done) {
-  let receivedFromWeak = [];
-  let receivedFromStrong = [];
-  let loader = Loader(module);
-  let events = loader.require('sdk/system/events');
-
-  let type = 'test-listeners-are-garbage-collected';
-  function handler(event) { receivedFromStrong.push(event); }
-  function weakHandler(event) { receivedFromWeak.push(event); }
-
-  events.on(type, handler, true);
-  events.on(type, weakHandler);
-
-  events.emit(type, { data: 1 });
-  assert.equal(receivedFromStrong.length, 1, "strong listener invoked");
-  assert.equal(receivedFromWeak.length, 1, "weak listener invoked");
-
-  handler = weakHandler = null;
-
-  Cu.schedulePreciseGC(function() {
-    events.emit(type, { data: 2 });
-
-    assert.equal(receivedFromWeak.length, 1, "weak listener was GC-ed");
-    assert.equal(receivedFromStrong.length, 2, "strong listener was invoked");
-
-    loader.unload();
-    done();
-  });
-};
-
-exports["test alive listeners are removed on unload"] = function*(assert) {
-  let receivedFromWeak = [];
-  let receivedFromStrong = [];
-  let loader = Loader(module);
-  let events = loader.require('sdk/system/events');
-
-  let type = 'test-alive-listeners-are-removed';
-  const handler = (event) => receivedFromStrong.push(event);
-  const weakHandler = (event) => receivedFromWeak.push(event);
-
-  events.on(type, handler, true);
-  events.on(type, weakHandler);
-
-  events.emit(type, { data: 1 });
-  assert.equal(receivedFromStrong.length, 1, "strong listener invoked");
-  assert.equal(receivedFromWeak.length, 1, "weak listener invoked");
-
-  loader.unload();
-  // Give the cleanup code a chance to run.
-  yield Promise.resolve();
-  events.emit(type, { data: 2 });
-
-  assert.equal(receivedFromWeak.length, 1, "weak listener was removed");
-  assert.equal(receivedFromStrong.length, 1, "strong listener was removed");
-};
-
-exports["test handle nsIObserverService notifications"] = function(assert) {
-  let ios = Cc['@mozilla.org/network/io-service;1']
-            .getService(Ci.nsIIOService);
-
-  let uri = ios.newURI("http://www.foo.com");
-
-  let type = Date.now().toString(32);
-  let timesCalled = 0;
-  let lastSubject = null;
-  let lastData = null;
-  let lastType = null;
-
-  function handler({ subject, data, type }) {
-    // Ignores internal console events
-    if (isConsoleEvent(type))
-      return;
-    timesCalled++;
-    lastSubject = subject;
-    lastData = data;
-    lastType = type;
-  };
-
-  events.on(type, handler);
-  nsIObserverService.notifyObservers(uri, type, "some data");
-
-  assert.equal(timesCalled, 1, "notification invokes handler");
-  assert.equal(lastType, type, "event.type is notification topic");
-  assert.equal(lastSubject, uri, "event.subject is notification subject");
-  assert.equal(lastData, "some data", "event.data is notification data");
-
-  function customSubject() {}
-  function customData() {}
-
-  events.emit(type, { data: customData, subject: customSubject });
-
-  assert.equal(timesCalled, 2, "notification invokes handler");
-  assert.equal(lastType, type, "event.type is notification topic");
-  assert.equal(lastSubject, customSubject,
-               "event.subject is wrapped & unwrapped");
-  assert.equal(lastData, customData, "event.data is wrapped & unwrapped");
-
-  events.off(type, handler);
-
-  nsIObserverService.notifyObservers(null, type, "some data");
-
-  assert.equal(timesCalled, 2, "event handler is removed");
-
-  events.on("*", handler);
-
-  nsIObserverService.notifyObservers(null, type, "more data");
-
-  assert.equal(timesCalled, 3, "notification invokes * handler");
-  assert.equal(lastType, type, "event.type is notification topic");
-  assert.equal(lastSubject, null,
-               "event.subject is notification subject");
-  assert.equal(lastData, "more data", "event.data is notification data");
-
-  events.off("*", handler);
-
-  nsIObserverService.notifyObservers(null, type, "last data");
-
-  assert.equal(timesCalled, 3, "* event handler is removed");
-};
-
-exports["test emit to nsIObserverService observers"] = function(assert) {
-  let ios = Cc['@mozilla.org/network/io-service;1']
-            .getService(Ci.nsIIOService);
-
-  let uri = ios.newURI("http://www.foo.com");
-  let timesCalled = 0;
-  let lastSubject = null;
-  let lastData = null;
-  let lastTopic = null;
-
-  var topic = Date.now().toString(32)
-  let nsIObserver = {
-    QueryInterface: function() {
-      return nsIObserver;
-    },
-    observe: function(subject, topic, data) {
-      // Ignores internal console events
-      if (isConsoleEvent(topic))
-        return;
-      timesCalled = timesCalled + 1;
-      lastSubject = subject;
-      lastData = data;
-      lastTopic = topic;
-    }
-  };
-
-  nsIObserverService.addObserver(nsIObserver, topic);
-
-  events.emit(topic, { subject: uri, data: "some data" });
-
-  assert.equal(timesCalled, 1, "emit notifies observers");
-  assert.equal(lastTopic, topic, "event type is notification topic");
-  assert.equal(lastSubject.wrappedJSObject.object, uri,
-               "event.subject is notification subject");
-  assert.equal(lastData, "some data", "event.data is notification data");
-  function customSubject() {}
-  function customData() {}
-  events.emit(topic, { subject: customSubject, data: customData });
-
-  assert.equal(timesCalled, 2, "emit notifies observers");
-  assert.equal(lastTopic, topic, "event.type is notification");
-  assert.equal(lastSubject.wrappedJSObject.object, customSubject,
-               "event.subject is notification subject");
-  assert.equal(lastData, customData, "event.data is notification data");
-
-  nsIObserverService.removeObserver(nsIObserver, topic);
-
-  events.emit(topic, { data: "more data" });
-
-  assert.equal(timesCalled, 2, "removed observers no longer invoked");
-
-  nsIObserverService.addObserver(nsIObserver, "*");
-
-  events.emit(topic, { data: "data again" });
-
-  assert.equal(timesCalled, 3, "emit notifies * observers");
-
-  assert.equal(lastTopic, topic, "event.type is notification");
-  assert.equal(lastSubject, null,
-               "event.subject is notification subject");
-  assert.equal(lastData, "data again", "event.data is notification data");
-
-  nsIObserverService.removeObserver(nsIObserver, "*");
-
-  events.emit(topic, { data: "last data" });
-  assert.equal(timesCalled, 3, "removed observers no longer invoked");
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-system-input-output.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";
-
-
-const { id: addonID, name: addonName } = require("sdk/self");
-const { Cc, Ci, Cu } = require("chrome");
-const { Loader, LoaderWithHookedConsole2 } = require("sdk/test/loader");
-const { InputPort } = require("sdk/input/system");
-const { OutputPort } = require("sdk/output/system");
-
-const { removeObserver, addObserver,
-        notifyObservers } = Cc["@mozilla.org/observer-service;1"].
-                              getService(Ci.nsIObserverService);
-
-const { lift, start, stop, send } = require("sdk/event/utils");
-
-const isConsoleEvent = topic =>
-  ["console-api-log-event",
-   "console-storage-cache-event"].indexOf(topic) >= 0;
-
-const message = x => ({wrappedJSObject: {data: x}});
-
-exports["test start / stop ports"] = assert => {
-  const input = new InputPort({ id: Date.now().toString(32), initial: {data:0} });
-  const topic = input.topic;
-
-  assert.ok(topic.includes(addonID), "topics are namespaced to add-on");
-
-  const xs = lift(({data}) => "x:" + data, input);
-  const ys = lift(({data}) => "y:" + data, input);
-
-  assert.deepEqual(input.value, {data:0}, "initila value is set");
-  assert.deepEqual(xs.value, "x:0", "initial value is mapped");
-  assert.deepEqual(ys.value, "y:0", "initial value is mapped");
-
-  notifyObservers(message(1), topic, null);
-
-  assert.deepEqual(input.value, {data:0}, "no message received on input port");
-  assert.deepEqual(xs.value, "x:0", "no message received on xs");
-  assert.deepEqual(ys.value, "y:0", "no message received on ys");
-
-  start(xs);
-
-
-  notifyObservers(message(2), topic, null);
-
-  assert.deepEqual(input.value, {data:2}, "message received on input port");
-  assert.deepEqual(xs.value, "x:2", "message received on xs");
-  assert.deepEqual(ys.value, "y:2", "no message received on (not started) ys");
-
-
-  notifyObservers(message(3), topic, null);
-
-
-  assert.deepEqual(input.value, {data:3}, "message received on input port");
-  assert.deepEqual(xs.value, "x:3", "message received on xs");
-  assert.deepEqual(ys.value, "y:3", "message received on ys");
-
-
-  notifyObservers(message(4), topic, null);
-
-  assert.deepEqual(input.value, {data:4}, "message received on input port");
-  assert.deepEqual(xs.value, "x:4", "message not received on (stopped) xs");
-  assert.deepEqual(ys.value, "y:4", "message received on ys");
-
-
-  stop(input);
-
-  notifyObservers(message(5), topic, null);
-
-  assert.deepEqual(input.value, {data:4}, "message note received on input port");
-  assert.deepEqual(xs.value, "x:4", "message not received on (stopped) xs");
-  assert.deepEqual(ys.value, "y:4", "message not received on (stopped) ys");
-};
-
-exports["test send messages to nsIObserverService"] = assert => {
-  let messages = [];
-
-  const { newURI } = Cc['@mozilla.org/network/io-service;1'].
-                       getService(Ci.nsIIOService);
-
-  const output = new OutputPort({ id: Date.now().toString(32), sync: true });
-  const topic = output.topic;
-
-  const observer = {
-    QueryInterface: function() {
-      return this;
-    },
-    observe: (subject, topic, data) => {
-      // Ignores internal console events
-      if (!isConsoleEvent(topic)) {
-        messages.push({
-          topic: topic,
-          subject: subject
-        });
-      }
-    }
-  };
-
-  addObserver(observer, topic, false);
-
-  send(output, null);
-  assert.deepEqual(messages.shift(), { topic: topic, subject: null },
-                   "null message received");
-
-
-  const uri = newURI("http://www.foo.com");
-  send(output, uri);
-
-  assert.deepEqual(messages.shift(), { topic: topic, subject: uri },
-                   "message received");
-
-
-  function customSubject() {}
-  send(output, customSubject);
-
-  let message = messages.shift();
-  assert.equal(message.topic, topic, "topic was received");
-  assert.equal(message.subject.wrappedJSObject, customSubject,
-               "custom subject is received");
-
-  removeObserver(observer, topic);
-
-  send(output, { data: "more data" });
-
-  assert.deepEqual(messages, [],
-                   "no more data received");
-
-  addObserver(observer, "*", false);
-
-  send(output, { data: "data again" });
-
-  message = messages.shift();
-  assert.equal(message.topic, topic, "topic was received");
-  assert.deepEqual(message.subject.wrappedJSObject,
-                   { data: "data again" },
-                   "wrapped message received");
-
-  removeObserver(observer, "*");
-
-  send(output, { data: "last data" });
-  assert.deepEqual(messages, [],
-                   "no more data received");
-
-  assert.throws(() => send(output, "hi"),
-                /Unsupproted message type: `string`/,
-                "strings can't be send");
-
-  assert.throws(() => send(output, 4),
-                /Unsupproted message type: `number`/,
-                "numbers can't be send");
-
-  assert.throws(() => send(output, void(0)),
-                /Unsupproted message type: `undefined`/,
-                "undefineds can't be send");
-
-  assert.throws(() => send(output, true),
-                /Unsupproted message type: `boolean`/,
-                "booleans can't be send");
-};
-
-exports["test async OutputPort"] = (assert, done) => {
-  let async = false;
-  const output = new OutputPort({ id: Date.now().toString(32) });
-  const observer = {
-    observe: (subject, topic, data) => {
-      removeObserver(observer, topic);
-      assert.equal(topic, output.topic, "correct topic");
-      assert.deepEqual(subject.wrappedJSObject, {foo: "bar"}, "message received");
-      assert.ok(async, "message received async");
-      done();
-    }
-  };
-  addObserver(observer, output.topic, false);
-  send(output, {foo: "bar"});
-
-  assert.throws(() => send(output, "boom"), "can only send object");
-  async = true;
-};
-
-exports["test explicit output topic"] = (assert, done) => {
-  const topic = Date.now().toString(32);
-  const output = new OutputPort({ topic: topic });
-  const observer = {
-    observe: (subject, topic, data) => {
-      removeObserver(observer, topic);
-      assert.deepEqual(subject.wrappedJSObject, {foo: "bar"}, "message received");
-      done();
-    }
-  };
-
-  assert.equal(output.topic, topic, "given topic is used");
-
-  addObserver(observer, topic, false);
-  send(output, {foo: "bar"});
-};
-
-exports["test explicit input topic"] = (assert) => {
-  const topic = Date.now().toString(32);
-  const input = new InputPort({ topic: topic });
-
-  start(input);
-  assert.equal(input.topic, topic, "given topic is used");
-
-
-  notifyObservers({wrappedJSObject: {foo: "bar"}}, topic, null);
-
-  assert.deepEqual(input.value, {foo: "bar"}, "message received");
-};
-
-
-exports["test receive what was send"] = assert => {
-  const id = Date.now().toString(32);
-  const input = new InputPort({ id: id, initial: 0});
-  const output = new OutputPort({ id: id, sync: true });
-
-  assert.ok(input.topic.includes(addonID),
-            "input topic is namespaced to addon");
-  assert.equal(input.topic, output.topic,
-              "input & output get same topics from id.");
-
-  start(input);
-
-  assert.equal(input.value, 0, "initial value is set");
-
-  send(output, { data: 1 });
-  assert.deepEqual(input.value, {data: 1}, "message unwrapped");
-
-  send(output, []);
-  assert.deepEqual(input.value, [], "array message unwrapped");
-
-  send(output, null);
-  assert.deepEqual(input.value, null, "null message received");
-
-  send(output, new String("message"));
-  assert.deepEqual(input.value, new String("message"),
-                   "string instance received");
-
-  send(output, /pattern/);
-  assert.deepEqual(input.value, /pattern/, "regexp received");
-
-  assert.throws(() => send(output, "hi"),
-                /Unsupproted message type: `string`/,
-                "strings can't be send");
-
-  assert.throws(() => send(output, 4),
-                /Unsupproted message type: `number`/,
-                "numbers can't be send");
-
-  assert.throws(() => send(output, void(0)),
-                /Unsupproted message type: `undefined`/,
-                "undefineds can't be send");
-
-  assert.throws(() => send(output, true),
-                /Unsupproted message type: `boolean`/,
-                "booleans can't be send");
-
-  stop(input);
-};
-
-
-exports["-test error reporting"] = function(assert) {
-  let { loader, messages } = LoaderWithHookedConsole2(module);
-  const { start, stop, lift } = loader.require("sdk/event/utils");
-  const { InputPort } = loader.require("sdk/input/system");
-  const { OutputPort } = loader.require("sdk/output/system");
-  const id = "error:" + Date.now().toString(32);
-
-  const raise = x => { if (x) throw new Error("foo"); };
-
-  const input = new InputPort({ id: id });
-  const output = new OutputPort({ id: id, sync: true });
-  const xs = lift(raise, input);
-
-  assert.equal(input.value, null, "initial inherited");
-
-  send(output, { data: "yo yo" });
-
-  assert.deepEqual(messages, [], "nothing happend yet");
-
-  start(xs);
-
-  send(output, { data: "first" });
-
-  assert.equal(messages.length, 4, "Got an exception");
-
-
-  assert.equal(messages[0], "console.error: " + addonName + ": \n",
-               "error is logged");
-
-  assert.ok(/Unhandled error/.test(messages[1]),
-            "expected error message");
-
-  loader.unload();
-};
-
-exports["test unload ends input port"] = assert => {
-  const loader = Loader(module);
-  const { start, stop, lift } = loader.require("sdk/event/utils");
-  const { InputPort } = loader.require("sdk/input/system");
-
-  const id = "unload!" + Date.now().toString(32);
-  const input = new InputPort({ id: id });
-
-  start(input);
-  notifyObservers(message(1), input.topic, null);
-  assert.deepEqual(input.value, {data: 1}, "message received");
-
-  notifyObservers(message(2), input.topic, null);
-  assert.deepEqual(input.value, {data: 2}, "message received");
-
-  loader.unload();
-  notifyObservers(message(3), input.topic, null);
-  assert.deepEqual(input.value, {data: 2}, "message wasn't received");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-system-runtime.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const runtime = require("sdk/system/runtime");
-
-exports["test system runtime"] = function(assert) {
-  assert.equal(typeof(runtime.inSafeMode), "boolean",
-               "inSafeMode is boolean");
-  assert.equal(typeof(runtime.OS), "string",
-               "runtime.OS is string");
-  assert.equal(typeof(runtime.processType), "number",
-               "runtime.processType is a number");
-  assert.equal(typeof(runtime.processID), "number",
-               "runtime.processID is a number");
-  assert.equal(typeof(runtime.widgetToolkit), "string",
-               "runtime.widgetToolkit is string");
-  const XPCOMABI = runtime.XPCOMABI;
-  assert.ok(XPCOMABI === null || typeof(XPCOMABI) === "string",
-            "runtime.XPCOMABI is string or null if not supported by platform");
-};
-
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-system-startup.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require("chrome");
-const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
-
-exports["test startup initialized"] = function(assert) {
-  assert.ok(Startup.initialized, "Startup.initialized is true");
-}
-
-exports["test startup onceInitialized"] = function*(assert) {
-  yield Startup.onceInitialized.then(() => {
-    assert.pass("onceInitialized promise was resolved");
-  }).catch(assert.fail);
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-system.js
+++ /dev/null
@@ -1,37 +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 runtime = require("sdk/system/runtime");
-const system = require("sdk/system");
-
-exports["test system architecture and compiler"] = function(assert) {
-
-  if (system.architecture !== null) {
-    assert.equal(
-      runtime.XPCOMABI.indexOf(system.architecture), 0,
-      "system.architecture is starting substring of runtime.XPCOMABI"
-    );
-  }
-
-  if (system.compiler !== null) {
-    assert.equal(
-      runtime.XPCOMABI.indexOf(system.compiler),
-      runtime.XPCOMABI.length - system.compiler.length,
-      "system.compiler is trailing substring of runtime.XPCOMABI"
-    );
-  }
-
-  assert.ok(
-    system.architecture === null || typeof(system.architecture) === "string",
-    "system.architecture is string or null if not supported by platform"
-  );
-
-  assert.ok(
-    system.compiler === null || typeof(system.compiler) === "string",
-    "system.compiler is string or null if not supported by platform"
-  );
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tab-events.js
+++ /dev/null
@@ -1,238 +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 { Loader } = require("sdk/test/loader");
-const utils = require("sdk/tabs/utils");
-const { open, close } = require("sdk/window/helpers");
-const { getMostRecentBrowserWindow } = require("sdk/window/utils");
-const { events } = require("sdk/tab/events");
-const { on, off } = require("sdk/event/core");
-const { resolve, defer } = require("sdk/core/promise");
-
-var isFennec = require("sdk/system/xul-app").is("Fennec");
-
-function test(options) {
-  return function(assert, done) {
-    let tabEvents = [];
-    let tabs = [];
-    let { promise, resolve: resolveP } = defer();
-    let win = isFennec ? resolve(getMostRecentBrowserWindow()) :
-      open(null, {
-        features: { private: true, toolbar:true, chrome: true }
-      });
-    let window = null;
-
-    // Firefox events are fired sync; Fennec events async
-    // this normalizes the tests
-    function handler (event) {
-      tabEvents.push(event);
-      runIfReady();
-    }
-
-    function runIfReady () {
-      let releventEvents = getRelatedEvents(tabEvents, tabs);
-      if (options.readyWhen(releventEvents))
-        options.end({
-          tabs: tabs,
-          events: releventEvents,
-          assert: assert,
-          done: resolveP
-        });
-    }
-
-    win.then(function(w) {
-      window = w;
-      on(events, "data", handler);
-      options.start({ tabs: tabs, window: window });
-
-      // Execute here for synchronous FF events, as the handlers
-      // were called before tabs were pushed to `tabs`
-      runIfReady(); 
-      return promise;
-    }).then(function() {
-      off(events, "data", handler);
-      return isFennec ? null : close(window);
-    }).then(done, assert.fail);
-  };
-}
-
-// Just making sure that tab events work for already opened tabs not only
-// for new windows.
-exports["test current window"] = test({
-  readyWhen: events => events.length === 3,
-  start: ({ tabs, window }) => {
-    let tab = utils.openTab(window, 'data:text/plain,open');
-    tabs.push(tab);
-    utils.closeTab(tab);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, close] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    assert.equal(close.type, "TabClose");
-    assert.equal(close.target, tab);
-    done();
-  }
-});
-
-exports["test open"] = test({
-  readyWhen: events => events.length === 2,
-  start: ({ tabs, window }) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,open'));
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-    done();
-  }
-});
-
-exports["test open -> close"] = test({
-  readyWhen: events => events.length === 3,
-  start: ({ tabs, window }) => {
-    // First tab is useless we just open it so that closing second tab won't
-    // close window on some platforms.
-    utils.openTab(window, 'data:text/plain,ignore');
-    let tab = utils.openTab(window, 'data:text/plain,open-close');
-    tabs.push(tab);
-    utils.closeTab(tab);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, close] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    assert.equal(close.type, "TabClose");
-    assert.equal(close.target, tab);
-    done();
-  }
-});
-
-exports["test open -> open -> select"] = test({
-  readyWhen: events => events.length === 5,
-  start: ({tabs, window}) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-1'));
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-2'));
-    utils.activateTab(tabs[0], window);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [ tab1, tab2 ] = tabs;
-    let tab1Events = 0;
-    getRelatedEvents(events, tab1).map(event => {
-      tab1Events++;
-      if (tab1Events === 1)
-        assert.equal(event.type, "TabOpen", "first tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "first tab selected");
-      assert.equal(event.target, tab1);
-    });
-    assert.equal(tab1Events, 3, "first tab has 3 events");
-
-    let tab2Opened;
-    getRelatedEvents(events, tab2).map(event => {
-      if (!tab2Opened)
-        assert.equal(event.type, "TabOpen", "second tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "second tab selected");
-      tab2Opened = true;
-      assert.equal(event.target, tab2);
-    });
-    done();
-  }
-});
-
-exports["test open -> pin -> unpin"] = test({
-  readyWhen: events => events.length === (isFennec ? 2 : 5),
-  start: ({ tabs, window }) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,pin-unpin'));
-    utils.pin(tabs[0]);
-    utils.unpin(tabs[0]);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [open, select, move, pin, unpin] = events;
-    let tab = tabs[0];
-
-    assert.equal(open.type, "TabOpen");
-    assert.equal(open.target, tab);
-
-    assert.equal(select.type, "TabSelect");
-    assert.equal(select.target, tab);
-
-    if (isFennec) {
-      assert.pass("Tab pin / unpin is not supported by Fennec");
-    }
-    else {
-      assert.equal(move.type, "TabMove");
-      assert.equal(move.target, tab);
-
-      assert.equal(pin.type, "TabPinned");
-      assert.equal(pin.target, tab);
-
-      assert.equal(unpin.type, "TabUnpinned");
-      assert.equal(unpin.target, tab);
-    }
-    done();
-  }
-});
-
-exports["test open -> open -> move "] = test({
-  readyWhen: events => events.length === (isFennec ? 4 : 5),
-  start: ({tabs, window}) => {
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-1'));
-    tabs.push(utils.openTab(window, 'data:text/plain,Tab-2'));
-    utils.move(tabs[0], 2);
-  },
-  end: ({ tabs, events, assert, done }) => {
-    let [ tab1, tab2 ] = tabs;
-    let tab1Events = 0;
-    getRelatedEvents(events, tab1).map(event => {
-      tab1Events++;
-      if (tab1Events === 1)
-        assert.equal(event.type, "TabOpen", "first tab opened");
-      else if (tab1Events === 2)
-        assert.equal(event.type, "TabSelect", "first tab selected");
-      else if (tab1Events === 3 && isFennec)
-        assert.equal(event.type, "TabMove", "first tab moved");
-      assert.equal(event.target, tab1);
-    });
-    assert.equal(tab1Events, isFennec ? 2 : 3,
-      "correct number of events for first tab");
-
-    let tab2Events = 0;
-    getRelatedEvents(events, tab2).map(event => {
-      tab2Events++;
-      if (tab2Events === 1)
-        assert.equal(event.type, "TabOpen", "second tab opened");
-      else
-        assert.equal(event.type, "TabSelect", "second tab selected");
-      assert.equal(event.target, tab2);
-    });
-    done();
-  }
-});
-
-function getRelatedEvents (events, tabs) {
-  return events.filter(({target}) => ~([].concat(tabs)).indexOf(target));
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tab-observer.js
+++ /dev/null
@@ -1,45 +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";
-
-// TODO Fennec support in Bug #894525
-module.metadata = {
-  "engines": {
-    "Firefox": "*"
-  }
-}
-
-const { openTab, closeTab } = require("sdk/tabs/utils");
-const { Loader } = require("sdk/test/loader");
-const { setTimeout } = require("sdk/timers");
-
-exports["test unload tab observer"] = function(assert, done) {
-  let loader = Loader(module);
-
-  let window = loader.require("sdk/deprecated/window-utils").activeBrowserWindow;
-  let observer = loader.require("sdk/tabs/observer").observer;
-  let opened = 0;
-  let closed = 0;
-
-  observer.on("open", function onOpen(window) { opened++; });
-  observer.on("close", function onClose(window) { closed++; });
-
-  // Open and close tab to trigger observers.
-  closeTab(openTab(window, "data:text/html;charset=utf-8,tab-1"));
-
-  // Unload the module so that all listeners set by observer are removed.
-  loader.unload();
-
-  // Open and close tab once again.
-  closeTab(openTab(window, "data:text/html;charset=utf-8,tab-2"));
-
-  // Enqueuing asserts to make sure that assertion is not performed early.
-  setTimeout(function () {
-    assert.equal(1, opened, "observer open was called before unload only");
-    assert.equal(1, closed, "observer close was called before unload only");
-    done();
-  }, 0);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tab-utils.js
+++ /dev/null
@@ -1,69 +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 { getTabs } = require('sdk/tabs/utils');
-const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
-const { browserWindows } = require('sdk/windows');
-const tabs = require('sdk/tabs');
-const { isPrivate } = require('sdk/private-browsing');
-const { openTab, closeTab, getTabContentWindow, getOwnerWindow } = require('sdk/tabs/utils');
-const { open, close } = require('sdk/window/helpers');
-const { windows } = require('sdk/window/utils');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { fromIterator } = require('sdk/util/array');
-
-if (isWindowPBSupported) {
-  exports.testGetTabs = function(assert, done) {
-    let tabCount = getTabs().length;
-    let windowCount = browserWindows.length;
-
-    open(null, {
-        features: {
-        private: true,
-        toolbar: true,
-        chrome: true
-      }
-    }).then(function(window) {
-      assert.ok(isPrivate(window), 'new tab is private');
-
-      assert.equal(getTabs().length, tabCount, 'there are no new tabs found');
-      getTabs().forEach(function(tab) {
-        assert.equal(isPrivate(tab), false, 'all found tabs are not private');
-        assert.equal(isPrivate(getOwnerWindow(tab)), false, 'all found tabs are not private');
-        assert.equal(isPrivate(getTabContentWindow(tab)), false, 'all found tabs are not private');
-      });
-
-      assert.equal(browserWindows.length, windowCount, 'there are no new windows found');
-      fromIterator(browserWindows).forEach(function(window) {
-        assert.equal(isPrivate(window), false, 'all found windows are not private');
-      });
-
-      assert.equal(windows(null, {includePrivate: true}).length, 2, 'there are really two windows');
-
-      close(window).then(done);
-    });
-  };
-}
-else if (isTabPBSupported) {
-  exports.testGetTabs = function(assert, done) {
-    let startTabCount = getTabs().length;
-    let tab = openTab(getMostRecentBrowserWindow(), 'about:blank', {
-      isPrivate: true
-    });
-
-    assert.ok(isPrivate(getTabContentWindow(tab)), 'new tab is private');
-    let utils_tabs = getTabs();
-    assert.equal(utils_tabs.length, startTabCount + 1,
-                 'there are two tabs found');
-    assert.equal(utils_tabs[utils_tabs.length-1], tab,
-                 'the last tab is the opened tab');
-    assert.equal(browserWindows.length, 1, 'there is only one window');
-    closeTab(tab);
-
-    done();
-  };
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tab.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";
-
-const tabs = require("sdk/tabs");
-const windowUtils = require("sdk/deprecated/window-utils");
-const windows = require("sdk/windows").browserWindows;
-const app = require("sdk/system/xul-app");
-const { viewFor } = require("sdk/view/core");
-const { modelFor } = require("sdk/model/core");
-const { getBrowserForTab, getTabId, isTab } = require("sdk/tabs/utils");
-const { defer } = require("sdk/lang/functional");
-
-function tabExistenceInTabs(assert, found, tab, tabs) {
-  let tabFound = false;
-
-  for (let t of tabs) {
-    assert.notEqual(t.title, undefined, 'tab title is not undefined');
-    assert.notEqual(t.url, undefined, 'tab url is not undefined');
-    assert.notEqual(t.index, undefined, 'tab index is not undefined');
-
-    if (t === tab) {
-      tabFound = true;
-      break;
-    }
-  }
-
-  // check for the tab's existence
-  if (found)
-    assert.ok(tabFound, 'the tab was found as expected');
-  else
-    assert.ok(!tabFound, 'the tab was not found as expected');
-}
-
-exports.testBehaviorOnCloseAfterReady = function(assert, done) {
-  tabs.open({
-    url: "about:mozilla",
-    onReady: function(tab) {
-      assert.equal(tab.url, "about:mozilla", "Tab has the expected url");
-      // if another test ends before closing a tab then index != 1 here
-      assert.ok(tab.index >= 1, "Tab has the expected index, a value greater than 0");
-
-      let testTabFound = tabExistenceInTabs.bind(null, assert, true, tab);
-      let testTabNotFound = tabExistenceInTabs.bind(null, assert, false, tab);
-
-      // tab in require("sdk/tabs") ?
-      testTabFound(tabs);
-      // tab was found in require("sdk/windows").windows.activeWindow.tabs ?
-      let activeWindowTabs = windows.activeWindow.tabs;
-      testTabFound(activeWindowTabs);
-
-      tab.close(function () {
-        assert.equal(tab.url, undefined,
-                     "After being closed, tab attributes are undefined (url)");
-        assert.equal(tab.index, undefined,
-                     "After being closed, tab attributes are undefined (index)");
-
-        tab.destroy();
-
-        testTabNotFound(tabs);
-        testTabNotFound(windows.activeWindow.tabs);
-        testTabNotFound(activeWindowTabs);
-
-        // Ensure that we can call destroy multiple times without throwing
-        tab.destroy();
-
-        testTabNotFound(tabs);
-        testTabNotFound(windows.activeWindow.tabs);
-        testTabNotFound(activeWindowTabs);
-
-        done();
-      });
-    }
-  });
-};
-
-exports.testBug844492 = function(assert, done) {
-  const activeWindowTabs = windows.activeWindow.tabs;
-  let openedTabs = 0;
-
-  tabs.on('open', function onOpenTab(tab) {
-    openedTabs++;
-
-    let testTabFound = tabExistenceInTabs.bind(null, assert, true, tab);
-    let testTabNotFound = tabExistenceInTabs.bind(null, assert, false, tab);
-
-    testTabFound(tabs);
-    testTabFound(windows.activeWindow.tabs);
-    testTabFound(activeWindowTabs);
-
-    tab.close();
-
-    testTabNotFound(tabs);
-    testTabNotFound(windows.activeWindow.tabs);
-    testTabNotFound(activeWindowTabs);
-
-    if (openedTabs >= 2) {
-      tabs.removeListener('open', onOpenTab);
-      done();
-    }
-  });
-
-  tabs.open({ url: 'about:mozilla' });
-  tabs.open({ url: 'about:mozilla' });
-};
-
-exports.testBehaviorOnCloseAfterOpen = function(assert, done) {
-  tabs.open({
-    url: "about:mozilla",
-    onOpen: function(tab) {
-      assert.notEqual(tab.url, undefined, "Tab has a url");
-      assert.ok(tab.index >= 1, "Tab has the expected index");
-
-      let testTabFound = tabExistenceInTabs.bind(null, assert, true, tab);
-      let testTabNotFound = tabExistenceInTabs.bind(null, assert, false, tab);
-
-      // tab in require("sdk/tabs") ?
-      testTabFound(tabs);
-      // tab was found in require("sdk/windows").windows.activeWindow.tabs ?
-      let activeWindowTabs = windows.activeWindow.tabs;
-      testTabFound(activeWindowTabs);
-
-      tab.close(function () {
-        assert.equal(tab.url, undefined,
-                     "After being closed, tab attributes are undefined (url)");
-        assert.equal(tab.index, undefined,
-                     "After being closed, tab attributes are undefined (index)");
-
-        tab.destroy();
-
-        if (app.is("Firefox")) {
-          // Ensure that we can call destroy multiple times without throwing;
-          // Fennec doesn't use this internal utility
-          tab.destroy();
-          tab.destroy();
-        }
-
-        testTabNotFound(tabs);
-        testTabNotFound(windows.activeWindow.tabs);
-        testTabNotFound(activeWindowTabs);
-
-        // Ensure that we can call destroy multiple times without throwing
-        tab.destroy();
-
-        testTabNotFound(tabs);
-        testTabNotFound(windows.activeWindow.tabs);
-        testTabNotFound(activeWindowTabs);
-
-        done();
-      });
-    }
-  });
-};
-
-exports["test viewFor(tab)"] = (assert, done) => {
-  // Note we defer handlers as length collection is updated after
-  // handler is invoked, so if test is finished before counnts are
-  // updated wrong length will show up in followup tests.
-  tabs.once("open", defer(tab => {
-    const view = viewFor(tab);
-    assert.ok(view, "view is returned");
-    assert.equal(getTabId(view), tab.id, "tab has a same id");
-
-    tab.close(defer(done));
-  }));
-
-  tabs.open({ url: "about:mozilla" });
-};
-
-
-exports["test modelFor(xulTab)"] = (assert, done) => {
-  tabs.open({
-    url: "about:mozilla",
-    onReady: tab => {
-      const view = viewFor(tab);
-      assert.ok(view, "view is returned");
-      assert.ok(isTab(view), "view is underlaying tab");
-      assert.equal(getTabId(view), tab.id, "tab has a same id");
-      assert.equal(modelFor(view), tab, "modelFor(view) is SDK tab");
-
-      tab.close(defer(done));
-    }
-  });
-};
-
-exports["test tab.readyState"] = (assert, done) => {
-  tabs.open({
-    url: "data:text/html;charset=utf-8,test_readyState",
-    onOpen: (tab) => {
-      assert.notEqual(["uninitialized", "loading"].indexOf(tab.readyState), -1,
-        "tab is either uninitialized or loading when onOpen");
-    },
-    onReady: (tab) => {
-      assert.notEqual(["interactive", "complete"].indexOf(tab.readyState), -1,
-        "tab is either interactive or complete when onReady");
-    },
-    onLoad: (tab) => {
-      assert.equal(tab.readyState, "complete", "tab is complete onLoad");
-      tab.close(defer(done));
-    }
-  });
-}
-
-exports["test tab.readyState for existent tabs"] = function* (assert) {
-  assert.equal(tabs.length, 1, "tabs contains an existent tab");
-
-  function frameScript() {
-    sendAsyncMessage("test:contentDocument.readyState", content.document.readyState);
-  }
-
-  for (let tab of tabs) {
-    let browserForTab = getBrowserForTab(viewFor(tab));
-    let mm = browserForTab.messageManager;
-
-    yield new Promise((resolve) => {
-      mm.addMessageListener("test:contentDocument.readyState", function listener(evt) {
-        mm.removeMessageListener("test:contentDocument.readyState", listener);
-        assert.equal(evt.data, tab.readyState,
-                     "tab.readyState has the same value of the associated contentDocument.readyState CPOW");
-        resolve();
-      });
-      mm.loadFrameScript(`data:,new ${frameScript};`, false);
-    });
-  }
-}
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tabs-common.js
+++ /dev/null
@@ -1,654 +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 { Loader, LoaderWithHookedConsole } = require("sdk/test/loader");
-const { browserWindows } = require('sdk/windows');
-const tabs = require('sdk/tabs');
-const { isPrivate } = require('sdk/private-browsing');
-const { openDialog } = require('sdk/window/utils');
-const { isWindowPrivate } = require('sdk/window/utils');
-const { setTimeout } = require('sdk/timers');
-const { openWebpage } = require('./private-browsing/helper');
-const { isTabPBSupported, isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { getTabContentWindow } = require('sdk/tabs/utils');
-const { attach, detach } = require('sdk/content/mod');
-const { Style } = require('sdk/stylesheet/style');
-const fixtures = require('./fixtures');
-const { viewFor } = require('sdk/view/core');
-const app = require("sdk/system/xul-app");
-const { cleanUI } = require('sdk/test/utils');
-
-const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
-
-// TEST: tab count
-exports.testTabCounts = function(assert, done) {
-  tabs.open({
-    url: 'about:blank',
-    onReady: function(tab) {
-      let count1 = 0,
-          count2 = 0;
-      for (let window of browserWindows) {
-        count1 += window.tabs.length;
-        for (let tab of window.tabs) {
-          count2 += 1;
-        }
-      }
-
-      assert.ok(tabs.length > 1, 'tab count is > 1');
-      assert.equal(count1, tabs.length, 'tab count by length is correct');
-      assert.equal(count2, tabs.length, 'tab count by iteration is correct');
-
-      // end test
-      tab.close(done);
-    }
-  });
-};
-
-exports.testTabRelativePath = function(assert, done) {
-  const { merge } = require("sdk/util/object");
-  const self = require("sdk/self");
-
-  const options = merge({}, require('@loader/options'),
-                        { prefixURI: require('./fixtures').url() });
-
-  let loader = Loader(module, null, options);
-
-  let tabs = loader.require("sdk/tabs");
-
-  tabs.open({
-    url: "./test.html",
-    onReady: (tab) => {
-      assert.equal(tab.title, "foo",
-        "tab opened a document with relative path");
-
-      tab.attach({
-        contentScriptFile: "./test-contentScriptFile.js",
-        onMessage: (message) => {
-          assert.equal(message, "msg from contentScriptFile",
-            "Tab attach a contentScriptFile with relative path worked");
-
-          tab.close(done);
-          loader.unload();
-        }
-      });
-    }
-  });
-};
-
-// TEST: tabs.activeTab getter
-exports.testActiveTab_getter = function(assert, done) {
-  let evtCount = 0;
-  let activeTab = null;
-
-  function endTest(type, tab) {
-    if (type == 'activate') {
-      assert.strictEqual(tabs.activeTab, tab, 'the active tab is the opened tab');
-      activeTab = tabs.activeTab;
-    }
-    else {
-      assert.equal(tab.url, url, 'the opened tab has the correct url');
-    }
-
-    if (++evtCount != 2)
-      return;
-
-    assert.strictEqual(activeTab, tab, 'the active tab is the ready tab');
-    assert.strictEqual(tabs.activeTab, tab, 'the active tab is the ready tab');
-
-    tab.close(done);
-  }
-
-  let url = URL.replace("#title#", "testActiveTab_getter");
-  tabs.open({
-    url: url,
-    onReady: endTest.bind(null, 'ready'),
-    onActivate: endTest.bind(null, 'activate')
-  });
-};
-
-// TEST: tab.activate()
-exports.testActiveTab_setter = function(assert, done) {
-  let url = URL.replace("#title#", "testActiveTab_setter");
-  let tab1URL = URL.replace("#title#", "tab1");
-
-  tabs.open({
-    url: tab1URL,
-    onReady: function(activeTab) {
-      let activeTabURL = tabs.activeTab.url;
-
-      tabs.open({
-        url: url,
-        inBackground: true,
-        onReady: function onReady(tab) {
-          assert.equal(tabs.activeTab.url, activeTabURL, "activeTab url has not changed");
-          assert.equal(tab.url, url, "url of new background tab matches");
-
-          tab.once('activate', function onActivate(eventTab) {
-            assert.equal(tabs.activeTab.url, url, "url after activeTab setter matches");
-            assert.equal(eventTab, tab, "event argument is the activated tab");
-            assert.equal(eventTab, tabs.activeTab, "the tab is the active one");
-
-            activeTab.close(function() {
-              tab.close(done);
-            });
-          });
-
-          tab.activate();
-        }
-      });
-    }
-  });
-};
-
-// TEST: tab.close()
-exports.testTabClose_alt = function(assert, done) {
-  let url = URL.replace('#title#', 'TabClose_alt');
-  let tab1URL = URL.replace('#title#', 'tab1');
-
-  tabs.open({
-    url: tab1URL,
-    onReady: function(tab1) {
-      // make sure that our tab is not active first
-      assert.notEqual(tabs.activeTab.url, url, "tab is not the active tab");
-
-      tabs.open({
-        url: url,
-        onReady: function(tab) {
-          assert.equal(tab.url, url, "tab is now the active tab");
-          assert.equal(tabs.activeTab.url, url, "tab is now the active tab");
-
-          // another tab should be activated on close
-          tabs.once('activate', function() {
-            assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
-
-            // end test
-            tab1.close(done);
-          });
-
-          tab.close();
-        }
-      });
-    }
-  });
-};
-
-exports.testAttachOnMultipleDocuments_alt = function (assert, done) {
-  // Example of attach that process multiple tab documents
-  let firstLocation = "data:text/html;charset=utf-8,foobar";
-  let secondLocation = "data:text/html;charset=utf-8,bar";
-  let thirdLocation = "data:text/html;charset=utf-8,fox";
-  let onReadyCount = 0;
-  let worker1 = null;
-  let worker2 = null;
-  let detachEventCount = 0;
-
-  tabs.open({
-    url: firstLocation,
-    onReady: function (tab) {
-      onReadyCount++;
-      if (onReadyCount == 1) {
-        worker1 = tab.attach({
-          contentScript: 'self.on("message", ' +
-                         '  () => self.postMessage(document.location.href)' +
-                         ');',
-          onMessage: function (msg) {
-            assert.equal(msg, firstLocation,
-                             "Worker url is equal to the 1st document");
-            tab.url = secondLocation;
-          },
-          onDetach: function () {
-            detachEventCount++;
-            assert.pass("Got worker1 detach event");
-            assert.throws(function () {
-                worker1.postMessage("ex-1");
-              },
-              /Couldn't find the worker/,
-              "postMessage throw because worker1 is destroyed");
-            checkEnd();
-          }
-        });
-        worker1.postMessage("new-doc-1");
-      }
-      else if (onReadyCount == 2) {
-        worker2 = tab.attach({
-          contentScript: 'self.on("message", ' +
-                         '  () => self.postMessage(document.location.href)' +
-                         ');',
-          onMessage: function (msg) {
-            assert.equal(msg, secondLocation,
-                             "Worker url is equal to the 2nd document");
-            tab.url = thirdLocation;
-          },
-          onDetach: function () {
-            detachEventCount++;
-            assert.pass("Got worker2 detach event");
-            assert.throws(function () {
-                worker2.postMessage("ex-2");
-              },
-              /Couldn't find the worker/,
-              "postMessage throw because worker2 is destroyed");
-            checkEnd(tab);
-          }
-        });
-        worker2.postMessage("new-doc-2");
-      }
-      else if (onReadyCount == 3) {
-        tab.close();
-      }
-    }
-  });
-
-  function checkEnd(tab) {
-    if (detachEventCount != 2)
-      return;
-
-    assert.pass("Got all detach events");
-
-    done();
-  }
-};
-
-exports.testAttachWrappers_alt = function (assert, done) {
-  // Check that content script has access to wrapped values by default
-
-  let document = "data:text/html;charset=utf-8,<script>var globalJSVar = true; " +
-                 "                       document.getElementById = 3;</script>";
-  let count = 0;
-
-  tabs.open({
-    url: document,
-    onReady: function (tab) {
-      let worker = tab.attach({
-        contentScript: 'try {' +
-                       '  self.postMessage(!("globalJSVar" in window));' +
-                       '  self.postMessage(typeof window.globalJSVar == "undefined");' +
-                       '} catch(e) {' +
-                       '  self.postMessage(e.message);' +
-                       '}',
-        onMessage: function (msg) {
-          assert.equal(msg, true, "Worker has wrapped objects ("+count+")");
-          if (count++ == 1)
-            tab.close(() => done());
-        }
-      });
-    }
-  });
-};
-
-// TEST: activeWindow getter and activeTab getter on tab 'activate' event
-exports.testActiveWindowActiveTabOnActivate_alt = function(assert, done) {
-
-  let activateCount = 0;
-  let newTabs = [];
-  let tabs = browserWindows.activeWindow.tabs;
-
-  tabs.on('activate', function onActivate(tab) {
-    assert.equal(tabs.activeTab, tab,
-                    "the active window's active tab is the tab provided");
-
-    if (++activateCount == 2) {
-      assert.equal(newTabs.length, activateCount, "Should have seen the right number of tabs open");
-      tabs.removeListener('activate', onActivate);
-
-      newTabs.forEach(function(tab) {
-        tab.close(function() {
-          if (--activateCount == 0) {
-            done();
-          }
-        });
-      });
-    }
-    else if (activateCount > 2) {
-      assert.fail("activateCount is greater than 2 for some reason..");
-    }
-  });
-
-  tabs.open({
-    url: URL.replace("#title#", "tabs.open1"),
-    onOpen: tab => newTabs.push(tab)
-  });
-  tabs.open({
-    url: URL.replace("#title#", "tabs.open2"),
-    onOpen: tab => newTabs.push(tab)
-  });
-};
-
-// TEST: tab properties
-exports.testTabContentTypeAndReload = function(assert, done) {
-
-  let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
-  let urlXML = "data:text/xml;charset=utf-8,<foo>bar</foo>";
-  tabs.open({
-    url: url,
-    onReady: function(tab) {
-      if (tab.url === url) {
-        assert.equal(tab.contentType, "text/html");
-        tab.url = urlXML;
-      }
-      else {
-        assert.equal(tab.contentType, "text/xml");
-        tab.close(done);
-      }
-    }
-  });
-};
-
-// test that it isn't possible to open a private tab without the private permission
-exports.testTabOpenPrivate = function(assert, done) {
-
-  let url = 'about:blank';
-  tabs.open({
-    url: url,
-    isPrivate: true,
-    onReady: function(tab) {
-      assert.equal(tab.url, url, 'opened correct tab');
-      assert.equal(isPrivate(tab), false, 'private tabs are not supported by default');
-
-      tab.close(done);
-    }
-  });
-}
-
-// We need permission flag in order to see private window's tabs
-exports.testPrivateAreNotListed = function (assert, done) {
-  let originalTabCount = tabs.length;
-
-  let page = openWebpage("about:blank", true);
-  if (!page) {
-    assert.pass("Private browsing isn't supported in this release");
-    return;
-  }
-
-  page.ready.then(function (win) {
-    if (isTabPBSupported || isWindowPBSupported) {
-      assert.ok(isWindowPrivate(win), "the window is private");
-      assert.equal(tabs.length, originalTabCount,
-                       'but the tab is *not* visible in tabs list');
-    }
-    else {
-      assert.ok(!isWindowPrivate(win), "the window isn't private");
-      assert.equal(tabs.length, originalTabCount + 1,
-                       'so that the tab is visible is tabs list');
-    }
-    page.close().then(done);
-  });
-}
-
-// If we close the tab while being in `onOpen` listener,
-// we end up synchronously consuming TabOpen, closing the tab and still
-// synchronously consuming the related TabClose event before the second
-// loader have a change to process the first TabOpen event!
-exports.testImmediateClosing = function (assert, done) {
-  let tabURL = 'data:text/html,foo';
-
-  let { loader, messages } = LoaderWithHookedConsole(module, onMessage);
-  let concurrentTabs = loader.require("sdk/tabs");
-  concurrentTabs.on("open", function (tab) {
-    // On Firefox, It shouldn't receive such event as the other loader will just
-    // open and destroy the tab without giving a chance to other loader to even
-    // know about the existance of this tab.
-    if (app.is("Firefox")) {
-      assert.fail("Concurrent loader received a tabs `open` event");
-    }
-    else {
-      // On mobile, we can still receive an open event,
-      // but not the related ready event
-      tab.on("ready", function () {
-        assert.fail("Concurrent loader received a tabs `ready` event");
-      });
-    }
-  });
-  function onMessage(type, msg) {
-    assert.fail("Unexpected mesage on concurrent loader: " + msg);
-  }
-
-  tabs.open({
-    url: tabURL,
-    onOpen: function(tab) {
-      tab.close(function () {
-        assert.pass("Tab succesfully removed");
-        // Let a chance to the concurrent loader to receive a TabOpen event
-        // on the next event loop turn
-        setTimeout(function () {
-          loader.unload();
-          done();
-        }, 0);
-      });
-    }
-  });
-}
-
-// TEST: tab.reload()
-exports.testTabReload = function(assert, done) {
-
-  let url = "data:text/html;charset=utf-8,<!doctype%20html><title></title>";
-
-  tabs.open({
-    url: url,
-    onReady: function onReady(tab) {
-      tab.removeListener('ready', onReady);
-
-      tab.once(
-        'ready',
-        function onReload() {
-          assert.pass("the tab was loaded again");
-          assert.equal(tab.url, url, "the tab has the same URL");
-
-          tab.close(() => done());
-        }
-      );
-
-      tab.reload();
-    }
-  });
-};
-
-exports.testOnPageShowEvent = function (assert, done) {
-  let events = [];
-  let firstUrl = 'data:text/html;charset=utf-8,First';
-  let secondUrl = 'data:text/html;charset=utf-8,Second';
-
-  let counter = 0;
-  function onPageShow (tab, persisted) {
-    events.push('pageshow');
-    counter++;
-    if (counter === 1) {
-      assert.equal(persisted, false, 'page should not be cached on initial load');
-      tab.url = secondUrl;
-    }
-    else if (counter === 2) {
-      assert.equal(persisted, false, 'second test page should not be cached either');
-      tab.attach({
-        contentScript: 'setTimeout(function () { window.history.back(); }, 0)'
-      });
-    }
-    else {
-      assert.equal(persisted, true, 'when we get back to the fist page, it has to' +
-                             'come from cache');
-      tabs.removeListener('pageshow', onPageShow);
-      tabs.removeListener('open', onOpen);
-      tabs.removeListener('ready', onReady);
-      tab.close(() => {
-        ['open', 'ready', 'pageshow', 'ready',
-            'pageshow', 'pageshow'].map((type, i) => {
-          assert.equal(type, events[i], 'correct ordering of events');
-        });
-        done()
-      });
-    }
-  }
-
-  function onOpen () {
-    return events.push('open');
-  }
-  function onReady () {
-    return events.push('ready');
-  }
-
-  tabs.on('pageshow', onPageShow);
-  tabs.on('open', onOpen);
-  tabs.on('ready', onReady);
-  tabs.open({
-    url: firstUrl
-  });
-};
-
-exports.testOnPageShowEventDeclarative = function (assert, done) {
-  let events = [];
-  let firstUrl = 'data:text/html;charset=utf-8,First';
-  let secondUrl = 'data:text/html;charset=utf-8,Second';
-
-  let counter = 0;
-  function onPageShow (tab, persisted) {
-    events.push('pageshow');
-    counter++;
-    if (counter === 1) {
-      assert.equal(persisted, false, 'page should not be cached on initial load');
-      tab.url = secondUrl;
-    }
-    else if (counter === 2) {
-      assert.equal(persisted, false, 'second test page should not be cached either');
-      tab.attach({
-        contentScript: 'setTimeout(function () { window.history.back(); }, 0)'
-      });
-    }
-    else {
-      assert.equal(persisted, true, 'when we get back to the fist page, it has to' +
-                             'come from cache');
-      tabs.removeListener('pageshow', onPageShow);
-      tabs.removeListener('open', onOpen);
-      tabs.removeListener('ready', onReady);
-      tab.close(() => {
-        ['open', 'ready', 'pageshow', 'ready',
-            'pageshow', 'pageshow'].map((type, i) => {
-          assert.equal(type, events[i], 'correct ordering of events');
-        });
-        done()
-      });
-    }
-  }
-
-  function onOpen () {
-    return events.push('open');
-  }
-  function onReady () {
-    return events.push('ready');
-  }
-
-  tabs.open({
-    url: firstUrl,
-    onPageShow: onPageShow,
-    onOpen: onOpen,
-    onReady: onReady
-  });
-};
-
-exports.testAttachStyleToTab = function(assert, done) {
-   let style = Style({
-    source: "div { height: 100px; }",
-    uri: fixtures.url("include-file.css")
-  });
-
-  tabs.open({
-    url: "data:text/html;charset=utf-8,<div style='background: silver'>css test</div>",
-    onReady: (tab) => {
-      let xulTab = viewFor(tab);
-
-      attach(style, tab)
-
-      let { document } = getTabContentWindow(xulTab);
-      let div = document.querySelector("div");
-
-      assert.equal(div.clientHeight, 100,
-        "Style.source properly attached to tab");
-
-      assert.equal(div.offsetHeight, 120,
-        "Style.uri properly attached to tab");
-
-      detach(style, tab);
-
-      assert.notEqual(div.clientHeight, 100,
-        "Style.source properly detached from tab");
-
-      assert.notEqual(div.offsetHeight, 120,
-        "Style.uri properly detached from tab");
-
-      attach(style, xulTab);
-
-      assert.equal(div.clientHeight, 100,
-        "Style.source properly attached to xul tab");
-
-      assert.equal(div.offsetHeight, 120,
-        "Style.uri properly attached to xul tab");
-
-      detach(style, tab);
-
-      assert.notEqual(div.clientHeight, 100,
-        "Style.source properly detached from xul tab");
-
-      assert.notEqual(div.offsetHeight, 120,
-        "Style.uri properly detached from xul tab");
-
-      tab.close(done);
-    }
-  });
-};
-
-// Tests that the this property is correct in event listeners called from
-// the tabs API.
-exports.testTabEventBindings = function(assert, done) {
-  let loader = Loader(module);
-  let tabs = loader.require("sdk/tabs");
-  let firstTab = tabs.activeTab;
-
-  let EVENTS = ["open", "close", "activate", "deactivate",
-                "load", "ready", "pageshow"];
-
-  let tabBoundEventHandler = (event) => function(tab) {
-    assert.equal(this, tab, "tab listener for " + event + " event should be bound to the tab object.");
-  };
-
-  let tabsBoundEventHandler = (event) => function(tab) {
-    assert.equal(this, tabs, "tabs listener for " + event + " event should be bound to the tabs object.");
-  }
-  for (let event of EVENTS)
-    tabs.on(event, tabsBoundEventHandler(event));
-
-  let tabsOpenEventHandler = (event) => function(tab) {
-    assert.equal(this, tab, "tabs open listener for " + event + " event should be bound to the tab object.");
-  }
-
-  let openArgs = {
-    url: "data:text/html;charset=utf-8,binding-test",
-    onOpen: function(tab) {
-      tabsOpenEventHandler("open").call(this, tab);
-
-      for (let event of EVENTS)
-        tab.on(event, tabBoundEventHandler(event));
-
-      tab.once("pageshow", () => {
-        tab.once("deactivate", () => {
-          tab.once("close", () => {
-            loader.unload();
-            done();
-          });
-
-          tab.close();
-        });
-
-        firstTab.activate();
-      });
-    }
-  };
-  // Listen to everything except onOpen
-  for (let event of EVENTS.slice(1)) {
-    let eventProperty = "on" + event.slice(0, 1).toUpperCase() + event.slice(1);
-    openArgs[eventProperty] = tabsOpenEventHandler(event);
-  }
-
-  tabs.open(openArgs);
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-tabs.js
+++ /dev/null
@@ -1,20 +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 = {
-  'engines': {
-    'Firefox': '*',
-    'Fennec': '*'
-  }
-};
-
-const app = require('sdk/system/xul-app');
-
-if (app.is('Fennec')) {
-  module.exports = require('./tabs/test-fennec-tabs');
-}
-else {
-  module.exports = require('./tabs/test-firefox-tabs');
-}
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-addon-file.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-// demonstrates that requiring a test file from a test addon works
-
-exports["test part 1"] = function(assert) {
-  let test = require("./addons/addon-manager/lib/test-main.js");
-  assert.equal(Object.keys(test).length, 1, "there is only one test");
-  assert.ok("test getAddonByID" in test, "the test is corret");
-};
-
-exports["test getAddonByID"] = require("./addons/addon-manager/lib/test-main.js")["test getAddonByID"];
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-assert.js
+++ /dev/null
@@ -1,218 +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 { Assert } = require("sdk/test/assert");
-
-function createAssertTest() {
-  let failures = [], successes = [], exceptions = [];
-  return {
-    test: new Assert({
-      fail: (m) => failures.push(m),
-      pass: (m) => successes.push(m),
-      exception: (e) => exceptions.push(e)
-    }),
-    failures: failures,
-    successes: successes,
-    exceptions: exceptions
-  };
-}
-
-exports["test createAssertTest initial state"] = function(assert) {
-  let { failures, successes, exceptions } = createAssertTest();
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.ok(true)"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.strictEqual(test.ok(true), true, "assert ok(true) strictEquals true");
-  assert.equal(successes.length, 1, "1 success log");
-
-  assert.equal(test.ok(true), true, "assert ok(true) equals true");
-  assert.equal(successes.length, 2, "2 success logs");
-
-  assert.ok(test.ok(true), "assert ok(true) is ok");
-  assert.equal(successes.length, 3, "3 success logs");
-
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.ok(false)"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.strictEqual(test.ok(false), false, "assert ok(false) strictEquals false");
-  assert.equal(failures.length, 1, "1 failure log");
-
-  assert.equal(test.ok(false), false, "assert ok(false) equals false");
-  assert.equal(failures.length, 2, "2 failure logs");
-
-  assert.ok(!test.ok(false), "assert ok(false) is not ok");
-  assert.equal(failures.length, 3, "3 failure logs");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.ok(false) failure message"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  test.ok(false, "XYZ");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 1, "1 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-
-  assert.equal(failures[0], "XYZ - false == true");
-}
-
-exports["test assert.equal"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.strictEqual(test.equal(true, true), true, "assert equal(true, true) strictEquals true");
-  assert.equal(test.equal(true, true), true, "assert equal(true, true) equals true");
-  assert.ok(test.equal(true, true), "assert equal(true, true) is ok");
-
-  assert.equal(successes.length, 3, "3 success log");
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.equal failure message"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  test.equal("foo", "bar", "XYZ");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 1, "1 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-
-  assert.equal(failures[0], "XYZ - \"foo\" == \"bar\"");
-}
-
-exports["test assert.strictEqual"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.strictEqual(test.strictEqual(true, true), true, "assert strictEqual(true, true) strictEquals true");
-  assert.equal(successes.length, 1, "1 success logs");
-
-  assert.equal(test.strictEqual(true, true), true, "assert strictEqual(true, true) equals true");
-  assert.equal(successes.length, 2, "2 success logs");
-
-  assert.ok(test.strictEqual(true, true), "assert strictEqual(true, true) is ok");
-  assert.equal(successes.length, 3, "3 success logs");
-
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.strictEqual failure message"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  test.strictEqual("foo", "bar", "XYZ");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 1, "1 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-
-  assert.equal(failures[0], "XYZ - \"foo\" === \"bar\"");
-}
-
-exports["test assert.throws(func, string, string) matches"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.ok(
-    test.throws(
-      () => { throw new Error("this is a thrown error") },
-      "this is a thrown error"
-    ),
-    "throwing an new Error works");
-  assert.equal(successes.length, 1, "1 success log");
-
-  assert.ok(
-    test.throws(
-      () => { throw Error("this is a thrown error") },
-      "this is a thrown error"
-    ),
-    "throwing an Error works");
-  assert.equal(successes.length, 2, "2 success log");
-
-  assert.ok(
-    test.throws(
-      () => { throw "this is a thrown string" },
-      "this is a thrown string"
-    ),
-    "throwing a String works");
-  assert.equal(successes.length, 3, "3 success logs");
-
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.throws(func, string, string) failure message"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  test.throws(
-    () => { throw new Error("foo") },
-    "bar",
-    "XYZ");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 1, "1 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-
-  assert.equal(failures[0], "XYZ - \"foo\" matches \"bar\"");
-}
-
-exports["test assert.throws(func, regex, string) matches"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  assert.ok(
-    test.throws(
-      () => { throw new Error("this is a thrown error") },
-      /this is a thrown error/
-    ),
-    "throwing an new Error works");
-  assert.equal(successes.length, 1, "1 success log");
-
-  assert.ok(
-    test.throws(
-      () => { throw Error("this is a thrown error") },
-      /this is a thrown error/
-    ),
-    "throwing an Error works");
-  assert.equal(successes.length, 2, "2 success log");
-
-  assert.ok(
-    test.throws(
-      () => { throw "this is a thrown string" },
-      /this is a thrown string/
-    ),
-    "throwing a String works");
-  assert.equal(successes.length, 3, "3 success logs");
-
-  assert.equal(failures.length, 0, "0 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-}
-
-exports["test assert.throws(func, regex, string) failure message"] = (assert) => {
-  let { test, failures, successes, exceptions } = createAssertTest();
-
-  test.throws(
-    () => { throw new Error("foo") },
-    /bar/i,
-    "XYZ");
-
-  assert.equal(successes.length, 0, "0 success log");
-  assert.equal(failures.length, 1, "1 failure logs");
-  assert.equal(exceptions.length, 0, "0 exception logs");
-
-  assert.equal(failures[0], "XYZ - \"foo\" matches \"/bar/i\"");
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-loader.js
+++ /dev/null
@@ -1,59 +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 { LoaderWithHookedConsole } = require("sdk/test/loader");
-
-exports["test LoaderWithHookedConsole"] = function (assert) {
-  let count = 0;
-  function onMessage(type, message) {
-    switch (count++) {
-      case 0:
-        assert.equal(type, "log", "got log type");
-        assert.equal(message, "1st", "got log msg");
-        break;
-      case 1:
-        assert.equal(type, "error", "got error type");
-        assert.equal(message, "2nd", "got error msg");
-        break;
-      case 2:
-        assert.equal(type, "warn", "got warn type");
-        assert.equal(message, "3rd", "got warn msg");
-        break;
-      case 3:
-        assert.equal(type, "info", "got info type");
-        assert.equal(message, "4th", "got info msg");
-        break;
-      case 4:
-        assert.equal(type, "debug", "got debug type");
-        assert.equal(message, "5th", "got debug msg");
-        break;
-      case 5:
-        assert.equal(type, "exception", "got exception type");
-        assert.equal(message, "6th", "got exception msg");
-        break;
-      default:
-        assert.fail("Got unexception message: " + i);
-    }
-  }
-
-  let { loader, messages } = LoaderWithHookedConsole(module, onMessage);
-  let console = loader.globals.console;
-  console.log("1st");
-  console.error("2nd");
-  console.warn("3rd");
-  console.info("4th");
-  console.debug("5th");
-  console.exception("6th");
-  assert.equal(messages.length, 6, "Got all console messages");
-  assert.deepEqual(messages[0], {type: "log", msg: "1st", innerID: null}, "Got log");
-  assert.deepEqual(messages[1], {type: "error", msg: "2nd", innerID: null}, "Got error");
-  assert.deepEqual(messages[2], {type: "warn", msg: "3rd", innerID: null}, "Got warn");
-  assert.deepEqual(messages[3], {type: "info", msg: "4th", innerID: null}, "Got info");
-  assert.deepEqual(messages[4], {type: "debug", msg: "5th", innerID: null}, "Got debug");
-  assert.deepEqual(messages[5], {type: "exception", msg: "6th", innerID: null}, "Got exception");
-  assert.equal(count, 6, "Called for all messages");
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-memory.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci, Cu, components } = require('chrome');
-const { gc } = require('sdk/test/memory');
-
-exports.testGC = function*(assert) {
-  let weakref;
-
-  if (true) {
-    let tempObj = {};
-    weakref = Cu.getWeakReference(tempObj);
-    assert.equal(weakref.get(), tempObj, 'the weakref returned the tempObj');
-  }
-
-  let arg = yield gc();
-
-  assert.equal(arg, undefined, 'there is no argument');
-  assert.pass('gc() returns a promise which eventually resolves');
-  assert.equal(weakref.get(), undefined, 'the weakref returned undefined');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-utils-async.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { defer: async } = require('sdk/lang/functional');
-const { before, after } = require('sdk/test/utils');
-const { resolve } = require('sdk/core/promise');
-
-var AFTER_RUN = 0;
-var BEFORE_RUN = 0;
-
-/*
- * Tests are dependent on ordering, as the before and after functions
- * are called outside of each test, and sometimes checked in the next test
- * (like in the `after` tests)
- */
-exports.testABeforeAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testABeforeNameAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 2, 'before function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 1, 'after function was called previously');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterNameAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 2, 'after function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testSyncABefore = function (assert) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-exports.testSyncAfter = function (assert) {
-  assert.equal(AFTER_RUN, 1, 'after function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-exports.testGeneratorBefore = function*(assert) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called for generator test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  yield resolve();
-}
-
-exports.testGeneratorAfter = function*(assert) {
-  assert.equal(AFTER_RUN, 1, 'after function was called for generator test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  yield resolve();
-};
-
-before(exports, (name, assert, done) => {
-  BEFORE_RUN = (name === 'testABeforeNameAsync') ? 2 : 1;
-  assert.pass('assert passed into before function');
-  async(done)();
-});
-
-after(exports, (name, assert, done) => {
-  // testAfterName runs after testAfter, which is where this
-  // check occurs in the assertation
-  AFTER_RUN = (name === 'testAfterAsync') ? 2 : 1;
-  assert.pass('assert passed into after function');
-  async(done)();
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-utils-generator.js
+++ /dev/null
@@ -1,76 +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";
-
-// NOTE: this test is explictly testing non-normal,
-//       generator functions.
-
-
-const { defer: async } = require('sdk/lang/functional');
-const { before, after } = require('sdk/test/utils');
-const { resolve } = require("sdk/core/promise");
-
-var AFTER_RUN = 0;
-var BEFORE_RUN = 0;
-
-/*
- * Tests are dependent on ordering, as the before and after functions
- * are called outside of each test, and sometimes checked in the next test
- * (like in the `after` tests)
- */
-exports.testABeforeAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testABeforeNameAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 2, 'before function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 1, 'after function was called previously');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterNameAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 2, 'after function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testSyncABefore = function (assert) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-exports.testSyncAfter = function (assert) {
-  assert.equal(AFTER_RUN, 1, 'after function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-before(exports, function*(name, assert) {
-  yield resolve();
-  BEFORE_RUN = (name === 'testABeforeNameAsync') ? 2 : 1;
-  assert.pass('assert passed into before function');
-});
-
-after(exports, function*(name, assert) {
-  yield resolve();
-  // testAfterName runs after testAfter, which is where this
-  // check occurs in the assertation
-  AFTER_RUN = (name === 'testAfterAsync') ? 2 : 1;
-  assert.pass('assert passed into after function');
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-utils-sync.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { defer: async } = require('sdk/lang/functional');
-const { before, after } = require('sdk/test/utils');
-const { resolve } = require('sdk/core/promise');
-
-var AFTER_RUN = 0;
-var BEFORE_RUN = 0;
-
-/*
- * Tests are dependent on ordering, as the before and after functions
- * are called outside of each test, and sometimes checked in the next test
- * (like in the `after` tests)
- */
-exports.testABeforeAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testABeforeNameAsync = function (assert, done) {
-  assert.equal(BEFORE_RUN, 2, 'before function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 1, 'after function was called previously');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testAfterNameAsync = function (assert, done) {
-  assert.equal(AFTER_RUN, 2, 'after function was called with name');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  async(done)();
-};
-
-exports.testSyncABefore = function (assert) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-exports.testSyncAfter = function (assert) {
-  assert.equal(AFTER_RUN, 1, 'after function was called for sync test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-};
-
-exports.testGeneratorBefore = function*(assert) {
-  assert.equal(BEFORE_RUN, 1, 'before function was called for generator test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  yield resolve();
-}
-
-exports.testGeneratorAfter = function*(assert) {
-  assert.equal(AFTER_RUN, 1, 'after function was called for generator test');
-  BEFORE_RUN = 0;
-  AFTER_RUN = 0;
-  yield resolve();
-};
-
-before(exports, (name, assert) => {
-  BEFORE_RUN = (name === 'testABeforeNameAsync') ? 2 : 1;
-  assert.pass('assert passed into before function');
-});
-
-after(exports, (name, assert) => {
-  // testAfterName runs after testAfter, which is where this
-  // check occurs in the assertation
-  AFTER_RUN = (name === 'testAfterAsync') ? 2 : 1;
-  assert.pass('assert passed into after function');
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-test-utils.js
+++ /dev/null
@@ -1,81 +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 { setTimeout } = require('sdk/timers');
-const { waitUntil, cleanUI } = require('sdk/test/utils');
-const tabs = require('sdk/tabs');
-const fixtures = require("./fixtures");
-const testURI = fixtures.url("test.html");
-
-exports.testWaitUntil = function (assert, done) {
-  let bool = false;
-  let finished = false;
-  waitUntil(() => {
-    if (finished)
-      assert.fail('interval should be cleared after predicate is truthy');
-    return bool;
-  }).then(function () {
-    assert.ok(bool,
-      'waitUntil shouldn\'t call until predicate is truthy');
-    finished = true;
-    done();
-  });
-  setTimeout(() => { bool = true; }, 20);
-};
-
-exports.testWaitUntilInterval = function (assert, done) {
-  let bool = false;
-  let finished = false;
-  let counter = 0;
-  waitUntil(() => {
-    if (finished)
-      assert.fail('interval should be cleared after predicate is truthy');
-    counter++;
-    return bool;
-  }, 50).then(function () {
-    assert.ok(bool,
-      'waitUntil shouldn\'t call until predicate is truthy');
-    assert.equal(counter, 1,
-      'predicate should only be called once with a higher interval');
-    finished = true;
-    done();
-  });
-  setTimeout(() => { bool = true; }, 10);
-};
-
-exports.testCleanUIWithExtraTabAndWindow = function*(assert) {
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: testURI,
-      inNewWindow: true,
-      onReady: resolve
-    });
-  });
-
-  assert.equal(tabs.length, 2, 'there are two tabs open');
-
-  yield cleanUI()
-  assert.pass("the ui was cleaned");
-  assert.equal(tabs.length, 1, 'there is only one tab open');
-}
-
-exports.testCleanUIWithOnlyExtraTab = function*(assert) {
-  let tab = yield new Promise(resolve => {
-    tabs.open({
-      url: testURI,
-      inBackground: true,
-      onReady: resolve
-    });
-  });
-
-  assert.equal(tabs.length, 2, 'there are two tabs open');
-
-  yield cleanUI();
-  assert.pass("the ui was cleaned.");
-  assert.equal(tabs.length, 1, 'there is only one tab open');
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-text-streams.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const file = require("sdk/io/file");
-const { pathFor } = require("sdk/system");
-const { Loader } = require("sdk/test/loader");
-
-const STREAM_CLOSED_ERROR = new RegExp("The stream is closed and cannot be used.");
-
-// This should match the constant of the same name in text-streams.js.
-const BUFFER_BYTE_LEN = 0x8000;
-
-exports.testWriteRead = function (assert) {
-  let fname = dataFileFilename();
-
-  // Write a small string less than the stream's buffer size...
-  let str = "exports.testWriteRead data!";
-  let stream = file.open(fname, "w");
-  assert.ok(!stream.closed, "stream.closed after open should be false");
-  stream.write(str);
-  stream.close();
-  assert.ok(stream.closed, "stream.closed after close should be true");
-  assert.throws(() => stream.close(),
-                    STREAM_CLOSED_ERROR,
-                    "stream.close after already closed should raise error");
-  assert.throws(() => stream.write("This shouldn't be written!"),
-                    STREAM_CLOSED_ERROR,
-                    "stream.write after close should raise error");
-
-  // ... and read it.
-  stream = file.open(fname);
-  assert.ok(!stream.closed, "stream.closed after open should be false");
-  assert.equal(stream.read(), str,
-                   "stream.read should return string written");
-  assert.equal(stream.read(), "",
-                   "stream.read at EOS should return empty string");
-  stream.close();
-  assert.ok(stream.closed, "stream.closed after close should be true");
-  assert.throws(() => stream.close(),
-                    STREAM_CLOSED_ERROR,
-                    "stream.close after already closed should raise error");
-  assert.throws(() => stream.read(),
-                    STREAM_CLOSED_ERROR,
-                    "stream.read after close should raise error");
-
-  // Write a big string many times the size of the stream's buffer and read it.
-  // Since it comes after the previous test, this also ensures that the file is
-  // truncated when it's opened for writing.
-  str = "";
-  let bufLen = BUFFER_BYTE_LEN;
-  let fileSize = bufLen * 10;
-  for (let i = 0; i < fileSize; i++)
-    str += i % 10;
-  stream = file.open(fname, "w");
-  stream.write(str);
-  stream.close();
-  stream = file.open(fname);
-  assert.equal(stream.read(), str,
-                   "stream.read should return string written");
-  stream.close();
-
-  // The same, but write and read in chunks.
-  stream = file.open(fname, "w");
-  let i = 0;
-  while (i < str.length) {
-    // Use a chunk length that spans buffers.
-    let chunk = str.substr(i, bufLen + 1);
-    stream.write(chunk);
-    i += bufLen + 1;
-  }
-  stream.close();
-  stream = file.open(fname);
-  let readStr = "";
-  bufLen = BUFFER_BYTE_LEN;
-  let readLen = bufLen + 1;
-  do {
-    var frag = stream.read(readLen);
-    readStr += frag;
-  } while (frag);
-  stream.close();
-  assert.equal(readStr, str,
-                   "stream.write and read in chunks should work as expected");
-
-  // Read the same file, passing in strange numbers of bytes to read.
-  stream = file.open(fname);
-  assert.equal(stream.read(fileSize * 100), str,
-                   "stream.read with big byte length should return string " +
-                   "written");
-  stream.close();
-
-  stream = file.open(fname);
-  assert.equal(stream.read(0), "",
-                   "string.read with zero byte length should return empty " +
-                   "string");
-  stream.close();
-
-  stream = file.open(fname);
-  assert.equal(stream.read(-1), "",
-                   "string.read with negative byte length should return " +
-                   "empty string");
-  stream.close();
-
-  file.remove(fname);
-};
-
-exports.testWriteAsync = function (assert, done) {
-  let fname = dataFileFilename();
-  let str = "exports.testWriteAsync data!";
-  let stream = file.open(fname, "w");
-  assert.ok(!stream.closed, "stream.closed after open should be false");
-
-  // Write.
-  stream.writeAsync(str, function (err) {
-    assert.equal(this, stream, "|this| should be the stream object");
-    assert.equal(err, undefined,
-                     "stream.writeAsync should not cause error");
-    assert.ok(stream.closed, "stream.closed after write should be true");
-    assert.throws(() => stream.close(),
-                      STREAM_CLOSED_ERROR,
-                      "stream.close after already closed should raise error");
-    assert.throws(() => stream.writeAsync("This shouldn't work!"),
-                      STREAM_CLOSED_ERROR,
-                      "stream.writeAsync after close should raise error");
-
-    // Read.
-    stream = file.open(fname, "r");
-    assert.ok(!stream.closed, "stream.closed after open should be false");
-    let readStr = stream.read();
-    assert.equal(readStr, str,
-                     "string.read should yield string written");
-    stream.close();
-    file.remove(fname);
-    done();
-  });
-};
-
-exports.testUnload = function (assert) {
-  let loader = Loader(module);
-  let file = loader.require("sdk/io/file");
-
-  let filename = dataFileFilename("temp");
-  let stream = file.open(filename, "w");
-
-  loader.unload();
-  assert.ok(stream.closed, "stream should be closed after module unload");
-};
-
-// Returns the name of a file that should be used to test writing and reading.
-function dataFileFilename() {
-  return file.join(pathFor("ProfD"), "test-text-streams-data");
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-timer.js
+++ /dev/null
@@ -1,229 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var timer = require("sdk/timers");
-const { Loader } = require("sdk/test/loader");
-const { gc } = require("sdk/test/memory");
-const { all, defer } = require("sdk/core/promise");
-
-exports.testSetTimeout = function(assert, end) {
-  timer.setTimeout(function() {
-    assert.pass("testSetTimeout passed");
-    end();
-  }, 1);
-};
-
-exports.testSetTimeoutGC = function*(assert) {
-  let called = defer();
-  let gcDone = defer();
-
-  timer.setTimeout(called.resolve, 300);
-  gc().then(gcDone.resolve);
-
-  yield called.promise;
-  yield gcDone.promise;
-
-  assert.pass("setTimeout passed!");
-};
-
-exports.testParamedSetTimeout = function(assert, end) {
-  let params = [1, 'foo', { bar: 'test' }, null, undefined];
-  timer.setTimeout.apply(null, [function() {
-    assert.equal(arguments.length, params.length);
-    for (let i = 0, ii = params.length; i < ii; i++)
-      assert.equal(params[i], arguments[i]);
-    end();
-  }, 1].concat(params));
-};
-
-exports.testClearTimeout = function(assert, end) {
-  var myFunc = function myFunc() {
-    assert.fail("myFunc() should not be called in testClearTimeout");
-  };
-  var id = timer.setTimeout(myFunc, 1);
-  timer.setTimeout(function() {
-    assert.pass("testClearTimeout passed");
-    end();
-  }, 2);
-  timer.clearTimeout(id);
-};
-
-exports.testParamedClearTimeout = function(assert, end) {
-  let params = [1, 'foo', { bar: 'test' }, null, undefined];
-  var myFunc = function myFunc() {
-    assert.fail("myFunc() should not be called in testClearTimeout");
-  };
-  var id = timer.setTimeout(myFunc, 1);
-  timer.setTimeout.apply(null, [function() {
-    assert.equal(arguments.length, params.length);
-    for (let i = 0, ii = params.length; i < ii; i++)
-      assert.equal(params[i], arguments[i]);
-    end();
-  }, 1].concat(params));
-  timer.clearTimeout(id);
-};
-
-exports.testSetInterval = function (assert, end) {
-  var count = 0;
-  var id = timer.setInterval(function () {
-    count++;
-    if (count >= 5) {
-      timer.clearInterval(id);
-      assert.pass("testSetInterval passed");
-      end();
-    }
-  }, 1);
-};
-
-exports.testSetIntervalGC = function*(assert) {
-  let called = defer();
-  let gcDone = defer();
-  let done = false;
-  let count = 0;
-
-  let id = timer.setInterval(() => {
-    assert.pass("call count is " + count);
-
-    if (done) {
-      timer.clearInterval(id);
-      called.resolve();
-      return null;
-    }
-
-    if (count++ == 0) {
-      assert.pass("first call to setInterval worked!");
-
-      gc().then(() => {
-        assert.pass("gc is complete!");
-        done = true;
-        gcDone.resolve();
-      });
-
-      assert.pass("called gc()!");
-    }
-
-    return null;
-  }, 1);
-
-  yield gcDone.promise;
-  yield called.promise;
-
-  assert.pass("setInterval was called after the gc!");
-};
-
-exports.testParamedSetInerval = function(assert, end) {
-  let params = [1, 'foo', { bar: 'test' }, null, undefined];
-  let count = 0;
-  let id = timer.setInterval.apply(null, [function() {
-    count ++;
-    if (count < 5) {
-      assert.equal(arguments.length, params.length);
-      for (let i = 0, ii = params.length; i < ii; i++)
-        assert.equal(params[i], arguments[i]);
-    } else {
-      timer.clearInterval(id);
-      end();
-    }
-  }, 1].concat(params));
-};
-
-exports.testClearInterval = function (assert, end) {
-  timer.clearInterval(timer.setInterval(function () {
-    assert.fail("setInterval callback should not be called");
-  }, 1));
-  var id = timer.setInterval(function () {
-    timer.clearInterval(id);
-    assert.pass("testClearInterval passed");
-    end();
-  }, 2);
-};
-
-exports.testParamedClearInterval = function(assert, end) {
-  timer.clearInterval(timer.setInterval(function () {
-    assert.fail("setInterval callback should not be called");
-  }, 1, timer, {}, null));
-
-  let id = timer.setInterval(function() {
-    timer.clearInterval(id);
-    assert.equal(3, arguments.length);
-    end();
-  }, 2, undefined, 'test', {});
-};
-
-
-exports.testImmediate = function(assert, end) {
-  let actual = [];
-  let ticks = 0;
-  timer.setImmediate(function(...params) {
-    actual.push(params);
-    assert.equal(ticks, 1, "is a next tick");
-    assert.deepEqual(actual, [["start", "immediates"]]);
-  }, "start", "immediates");
-
-  timer.setImmediate(function(...params) {
-    actual.push(params);
-    assert.deepEqual(actual, [["start", "immediates"],
-                                  ["added"]]);
-    assert.equal(ticks, 1, "is a next tick");
-    timer.setImmediate(function(...params) {
-      actual.push(params);
-      assert.equal(ticks, 2, "is second tick");
-      assert.deepEqual(actual, [["start", "immediates"],
-                                    ["added"],
-                                    [],
-                                    ["last", "immediate", "handler"],
-                                    ["side-effect"]]);
-      end();
-    }, "side-effect");
-  }, "added");
-
-  timer.setImmediate(function(...params) {
-    actual.push(params);
-    assert.equal(ticks, 1, "is a next tick");
-    assert.deepEqual(actual, [["start", "immediates"],
-                              ["added"],
-                              []]);
-    timer.clearImmediate(removeID);
-  });
-
-  function removed() {
-    assert.fail("should be removed");
-  }
-  let removeID = timer.setImmediate(removed);
-
-  timer.setImmediate(function(...params) {
-    actual.push(params);
-    assert.equal(ticks, 1, "is a next tick");
-    assert.deepEqual(actual, [["start", "immediates"],
-                              ["added"],
-                              [],
-                              ["last", "immediate", "handler"]]);
-    ticks = ticks + 1;
-  }, "last", "immediate", "handler");
-
-
-  ticks = ticks + 1;
-};
-
-exports.testUnload = function(assert, end) {
-  var loader = Loader(module);
-  var sbtimer = loader.require("sdk/timers");
-
-  var myFunc = function myFunc() {
-    assert.fail("myFunc() should not be called in testUnload");
-  };
-
-  sbtimer.setTimeout(myFunc, 1);
-  sbtimer.setTimeout(myFunc, 1, 'foo', 4, {}, undefined);
-  sbtimer.setInterval(myFunc, 1);
-  sbtimer.setInterval(myFunc, 1, {}, null, 'bar', undefined, 87);
-  loader.unload();
-  timer.setTimeout(function() {
-    assert.pass("timer testUnload passed");
-    end();
-  }, 2);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-traceback.js
+++ /dev/null
@@ -1,139 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-var traceback = require("sdk/console/traceback");
-var {Cc,Ci,Cr,Cu} = require("chrome");
-const { on, off } = require("sdk/system/events");
-
-function throwNsIException() {
-  var ios = Cc['@mozilla.org/network/io-service;1']
-            .getService(Ci.nsIIOService);
-  ios.newURI("i'm a malformed URI");
-}
-
-function throwError() {
-  throw new Error("foob");
-}
-
-exports.testFormatDoesNotFetchRemoteFiles = function(assert) {
-  ["http", "https"].forEach(
-    function(scheme) {
-      var httpRequests = 0;
-      function onHttp() {
-        httpRequests++;
-      }
-
-      on("http-on-modify-request", onHttp);
-
-      try {
-        var tb = [{filename: scheme + "://www.mozilla.org/",
-                   lineNumber: 1,
-                   name: "blah"}];
-        traceback.format(tb);
-      } catch (e) {
-        assert.fail(e);
-      }
-
-      off("http-on-modify-request", onHttp);
-
-      assert.equal(httpRequests, 0,
-                       "traceback.format() does not make " +
-                       scheme + " request");
-    });
-};
-
-exports.testFromExceptionWithString = function(assert) {
-  try {
-    throw "foob";
-    assert.fail("an exception should've been thrown");
-  } catch (e) {
-    if (e == "foob") {
-      var tb = traceback.fromException(e);
-      assert.equal(tb.length, 0);
-    }
-    else {
-      throw e;
-    }
-  }
-};
-
-exports.testFormatWithString = function(assert) {
-  // This can happen if e.g. a thrown exception was
-  // a string instead of an Error instance.
-  assert.equal(traceback.format("blah"),
-		   "Traceback (most recent call last):");
-};
-
-exports.testFromExceptionWithError = function(assert) {
-  try {
-    throwError();
-    assert.fail("an exception should've been thrown");
-  } catch (e) {
-    if (e instanceof Error) {
-      var tb = traceback.fromException(e);
-
-      var xulApp = require("sdk/system/xul-app");
-      assert.equal(tb.slice(-1)[0].name, "throwError");
-    }
-    else {
-      throw e;
-    }
-  }
-};
-
-exports.testFromExceptionWithNsIException = function(assert) {
-  try {
-    throwNsIException();
-    assert.fail("an exception should've been thrown");
-  } catch (e) {
-    if (e.result == Cr.NS_ERROR_MALFORMED_URI) {
-      var tb = traceback.fromException(e);
-      assert.equal(tb[tb.length - 1].name, "throwNsIException");
-    }
-    else {
-      throw e;
-    }
-  }
-};
-
-exports.testFormat = function(assert) {
-  function getTraceback() {
-    return traceback.format();
-  }
-
-  var formatted = getTraceback();
-  assert.equal(typeof(formatted), "string");
-  var lines = formatted.split("\n");
-
-  assert.equal(lines[lines.length - 2].indexOf("getTraceback") > 0,
-                   true,
-                   "formatted traceback should include function name");
-
-  assert.equal(lines[lines.length - 1].trim(),
-                   "return traceback.format();",
-                   "formatted traceback should include source code");
-};
-
-exports.testExceptionsWithEmptyStacksAreLogged = function(assert) {
-  // Ensures that our fix to bug 550368 works.
-  var sandbox = Cu.Sandbox("http://www.foo.com");
-  var excRaised = false;
-  try {
-    Cu.evalInSandbox("returns 1 + 2;", sandbox, "1.8",
-                     "blah.js", 25);
-  } catch (e) {
-    excRaised = true;
-    var stack = traceback.fromException(e);
-    assert.equal(stack.length, 1, "stack should have one frame");
-
-    assert.ok(stack[0].fileName, "blah.js", "frame should have filename");
-    assert.ok(stack[0].lineNumber, 25, "frame should have line no");
-    assert.equal(stack[0].name, null, "frame should have null function name");
-  }
-  if (!excRaised)
-    assert.fail("Exception should have been raised.");
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-action-button.js
+++ /dev/null
@@ -1,1188 +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 = {
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-const { Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const { data } = require('sdk/self');
-const { open, focus, close } = require('sdk/window/helpers');
-const { setTimeout } = require('sdk/timers');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { partial } = require('sdk/lang/functional');
-const { wait } = require('./event/helpers');
-const { gc } = require('sdk/test/memory');
-const { emit, once } = require("sdk/event/core");
-
-const openBrowserWindow = partial(open, null, {features: {toolbar: true}});
-const openPrivateBrowserWindow = partial(open, null,
-  {features: {toolbar: true, private: true}});
-
-const badgeNodeFor = (node) =>
-  node.ownerDocument.getAnonymousElementByAttribute(node,
-                                      'class', 'toolbarbutton-badge');
-
-function getWidget(buttonId, window = getMostRecentBrowserWindow()) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  const { AREA_NAVBAR } = CustomizableUI;
-
-  let widgets = CustomizableUI.getWidgetIdsInArea(AREA_NAVBAR).
-    filter((id) => id.startsWith('action-button--') && id.endsWith(buttonId));
-
-  if (widgets.length === 0)
-    throw new Error('Widget with id `' + id +'` not found.');
-
-  if (widgets.length > 1)
-    throw new Error('Unexpected number of widgets: ' + widgets.length)
-
-  return CustomizableUI.getWidget(widgets[0]).forWindow(window);
-};
-
-exports['test basic constructor validation'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  assert.throws(
-    () => ActionButton({}),
-    /^The option/,
-    'throws on no option given');
-
-  // Test no label
-  assert.throws(
-    () => ActionButton({ id: 'my-button', icon: './icon.png'}),
-    /^The option "label"/,
-    'throws on no label given');
-
-  // Test no id
-  assert.throws(
-    () => ActionButton({ label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no id given');
-
-  // Test no icon
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'my button' }),
-    /^The option "icon"/,
-    'throws on no icon given');
-
-
-  // Test empty label
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: '', icon: './icon.png' }),
-    /^The option "label"/,
-    'throws on no valid label given');
-
-  // Test invalid id
-  assert.throws(
-    () => ActionButton({ id: 'my button', label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no valid id given');
-
-  // Test empty id
-  assert.throws(
-    () => ActionButton({ id: '', label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no valid id given');
-
-  // Test remote icon
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'my button', icon: 'http://www.mozilla.org/favicon.ico'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: no absolute URI to local resource, neither relative './'
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'my button', icon: 'icon.png'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: no absolute URI to local resource, neither relative './'
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'my button', icon: 'foo and bar'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: '../' is not allowed
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'my button', icon: '../icon.png'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'button', icon: './i.png', badge: true}),
-    /^The option "badge"/,
-    'throws on no valid badge given');
-
-  assert.throws(
-    () => ActionButton({ id: 'my-button', label: 'button', icon: './i.png', badgeColor: true}),
-    /^The option "badgeColor"/,
-    'throws on no valid badge given');
-
-  loader.unload();
-};
-
-exports['test button added'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  let button = ActionButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // check defaults
-  assert.equal(button.disabled, false,
-    'disabled is set to default `false` value');
-
-  let { node } = getWidget(button.id);
-
-  assert.ok(!!node, 'The button is in the navbar');
-
-  assert.equal(button.label, node.getAttribute('label'),
-    'label is set');
-
-  assert.equal(button.label, node.getAttribute('tooltiptext'),
-    'tooltip is set');
-
-  assert.equal(data.url(button.icon.substr(2)), node.getAttribute('image'),
-    'icon is set');
-
-  assert.equal("", node.getAttribute('badge'),
-    'badge attribute is empty');
-
-  loader.unload();
-}
-
-exports['test button is not garbaged'] = function (assert, done) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  ActionButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: () => {
-      loader.unload();
-      done();
-    }
-  });
-
-  gc().then(() => {
-    let { node } = getWidget('my-button-1');
-
-    assert.ok(!!node, 'The button is in the navbar');
-
-    assert.equal('my button', node.getAttribute('label'),
-      'label is set');
-
-    assert.equal(data.url('icon.png'), node.getAttribute('image'),
-      'icon is set');
-
-    // ensure the listener is not gc'ed too
-    node.click();
-  }).catch(assert.fail);
-}
-
-exports['test button added with resource URI'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  let button = ActionButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: data.url('icon.png')
-  });
-
-  assert.equal(button.icon, data.url('icon.png'),
-    'icon is set');
-
-  let { node } = getWidget(button.id);
-
-  assert.equal(button.icon, node.getAttribute('image'),
-    'icon on node is set');
-
-  loader.unload();
-}
-
-exports['test button duplicate id'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let button = ActionButton({
-    id: 'my-button-2',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  assert.throws(() => {
-    let doppelganger = ActionButton({
-      id: 'my-button-2',
-      label: 'my button',
-      icon: './icon.png'
-    });
-  },
-  /^The ID/,
-  'No duplicates allowed');
-
-  loader.unload();
-}
-
-exports['test button multiple destroy'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let button = ActionButton({
-    id: 'my-button-2',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  button.destroy();
-  button.destroy();
-  button.destroy();
-
-  assert.pass('multiple destroy doesn\'t matter');
-
-  loader.unload();
-}
-
-exports['test button removed on dispose'] = function(assert, done) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let widgetId;
-
-  CustomizableUI.addListener({
-    onWidgetDestroyed: function(id) {
-      if (id === widgetId) {
-        CustomizableUI.removeListener(this);
-
-        assert.pass('button properly removed');
-        loader.unload();
-        done();
-      }
-    }
-  });
-
-  let button = ActionButton({
-    id: 'my-button-3',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
-  // was removed or it's not in the UX build yet
-  widgetId = getWidget(button.id).id;
-
-  button.destroy();
-};
-
-exports['test button global state updated'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require("sdk/self");
-
-  let button = ActionButton({
-    id: 'my-button-4',
-    label: 'my button',
-    icon: './icon.png',
-  });
-  assert.pass('the button was created.');
-
-  // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
-  // was removed or it's not in the UX build yet
-
-  let { node, id: widgetId } = getWidget(button.id);
-
-  // check read-only properties
-
-  assert.throws(() => button.id = 'another-id',
-    /^setting getter-only property/,
-    'id cannot be set at runtime');
-
-  assert.equal(button.id, 'my-button-4',
-    'id is unchanged');
-  assert.equal(node.id, widgetId,
-    'node id is unchanged');
-
-  // check writable properties
-
-  button.label = 'New label';
-  assert.equal(button.label, 'New label',
-    'label is updated');
-  assert.equal(node.getAttribute('label'), 'New label',
-    'node label is updated');
-  assert.equal(node.getAttribute('tooltiptext'), 'New label',
-    'node tooltip is updated');
-
-  button.icon = './new-icon.png';
-  assert.equal(button.icon, './new-icon.png',
-    'icon is updated');
-  assert.equal(node.getAttribute('image'), data.url('new-icon.png'),
-    'node image is updated');
-
-  button.disabled = true;
-  assert.equal(button.disabled, true,
-    'disabled is updated');
-  assert.equal(node.getAttribute('disabled'), 'true',
-    'node disabled is updated');
-
-  button.badge = '+2';
-  button.badgeColor = 'blue';
-
-  assert.equal(button.badge, '+2',
-    'badge is updated');
-  assert.equal(node.getAttribute('bagde'), '',
-    'node badge is updated');
-
-  assert.equal(button.badgeColor, 'blue',
-    'badgeColor is updated');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, 'blue',
-    'badge color is updated');
-
-  // TODO: test validation on update
-
-  loader.unload();
-}
-
-exports['test button global state set and get with state method'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let button = ActionButton({
-    id: 'my-button-16',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // read the button's state
-  let state = button.state(button);
-
-  assert.equal(state.label, 'my button',
-    'label is correct');
-  assert.equal(state.icon, './icon.png',
-    'icon is correct');
-  assert.equal(state.disabled, false,
-    'disabled is correct');
-
-  // set the new button's state
-  button.state(button, {
-    label: 'New label',
-    icon: './new-icon.png',
-    disabled: true,
-    badge: '+2',
-    badgeColor: 'blue'
-  });
-
-  assert.equal(button.label, 'New label',
-    'label is updated');
-  assert.equal(button.icon, './new-icon.png',
-    'icon is updated');
-  assert.equal(button.disabled, true,
-    'disabled is updated');
-  assert.equal(button.badge, '+2',
-    'badge is updated');
-  assert.equal(button.badgeColor, 'blue',
-    'badgeColor is updated');
-
-  loader.unload();
-}
-
-exports['test button global state updated on multiple windows'] = function*(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  let button = ActionButton({
-    id: 'my-button-5',
-    label: 'my button',
-    icon: './icon.png'
-  });
-  assert.pass('the button was created');
-
-  let nodes = [ getWidget(button.id).node ];
-
-  let window = yield openBrowserWindow();
-  assert.pass('the window was created');
-
-  nodes.push(getWidget(button.id, window).node);
-
-  button.label = 'New label';
-  button.icon = './new-icon.png';
-  button.disabled = true;
-  button.badge = '+10';
-  button.badgeColor = 'green';
-
-  for (let node of nodes) {
-    assert.equal(node.getAttribute('label'), 'New label',
-      'node label is updated');
-    assert.equal(node.getAttribute('tooltiptext'), 'New label',
-      'node tooltip is updated');
-
-    assert.equal(button.icon, './new-icon.png',
-      'icon is updated');
-    assert.equal(node.getAttribute('image'), data.url('new-icon.png'),
-      'node image is updated');
-
-    assert.equal(button.disabled, true,
-      'disabled is updated');
-    assert.equal(node.getAttribute('disabled'), 'true',
-      'node disabled is updated');
-
-    assert.equal(button.badge, '+10',
-      'badge is updated')
-    assert.equal(button.badgeColor, 'green',
-      'badgeColor is updated')
-    assert.equal(node.getAttribute('badge'), '+10',
-      'node badge is updated')
-    assert.equal(badgeNodeFor(node).style.backgroundColor, 'green',
-      'node badge color is updated')
-  };
-
-  yield close(window);
-
-  loader.unload();
-};
-
-exports['test button window state'] = function*(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let { data } = loader.require('sdk/self');
-
-  let button = ActionButton({
-    id: 'my-button-6',
-    label: 'my button',
-    icon: './icon.png',
-    badge: '+1',
-    badgeColor: 'red'
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let nodes = [getWidget(button.id).node];
-
-  let window = yield openBrowserWindow().then(focus);
-
-  nodes.push(getWidget(button.id, window).node);
-
-  let { activeWindow } = browserWindows;
-
-  button.state(activeWindow, {
-    label: 'New label',
-    icon: './new-icon.png',
-    disabled: true,
-    badge: '+2',
-    badgeColor : 'green'
-  });
-
-  // check the states
-
-  assert.equal(button.label, 'my button',
-    'global label unchanged');
-  assert.equal(button.icon, './icon.png',
-    'global icon unchanged');
-  assert.equal(button.disabled, false,
-    'global disabled unchanged');
-  assert.equal(button.badge, '+1',
-    'global badge unchanged');
-  assert.equal(button.badgeColor, 'red',
-    'global badgeColor unchanged');
-
-  let state = button.state(mainWindow);
-
-  assert.equal(state.label, 'my button',
-    'previous window label unchanged');
-  assert.equal(state.icon, './icon.png',
-    'previous window icon unchanged');
-  assert.equal(state.disabled, false,
-    'previous window disabled unchanged');
-  assert.deepEqual(button.badge, '+1',
-    'previouswindow badge unchanged');
-  assert.deepEqual(button.badgeColor, 'red',
-    'previous window badgeColor unchanged');
-
-  state = button.state(activeWindow);
-
-  assert.equal(state.label, 'New label',
-    'active window label updated');
-  assert.equal(state.icon, './new-icon.png',
-    'active window icon updated');
-  assert.equal(state.disabled, true,
-    'active disabled updated');
-  assert.equal(state.badge, '+2',
-    'active badge updated');
-  assert.equal(state.badgeColor, 'green',
-    'active badgeColor updated');
-
-  // change the global state, only the windows without a state are affected
-
-  button.label = 'A good label';
-  button.badge = '+3';
-
-  assert.equal(button.label, 'A good label',
-    'global label updated');
-  assert.equal(button.state(mainWindow).label, 'A good label',
-    'previous window label updated');
-  assert.equal(button.state(activeWindow).label, 'New label',
-    'active window label unchanged');
-  assert.equal(button.state(activeWindow).badge, '+2',
-    'active badge unchanged');
-  assert.equal(button.state(activeWindow).badgeColor, 'green',
-    'active badgeColor unchanged');
-  assert.equal(button.state(mainWindow).badge, '+3',
-    'previous window badge updated');
-  assert.equal(button.state(mainWindow).badgeColor, 'red',
-    'previous window badgeColor unchanged');
-
-  // delete the window state will inherits the global state again
-
-  button.state(activeWindow, null);
-
-  state = button.state(activeWindow);
-
-  assert.equal(state.label, 'A good label',
-    'active window label inherited');
-  assert.equal(state.badge, '+3',
-    'previous window badge inherited');
-  assert.equal(button.badgeColor, 'red',
-    'previous window badgeColor inherited');
-
-  // check the nodes properties
-  let node = nodes[0];
-
-  state = button.state(mainWindow);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute("badge"), state.badge,
-    'badge is correct');
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  node = nodes[1];
-  state = button.state(activeWindow);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute('badge'), state.badge,
-    'badge is correct');
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  yield close(window);
-
-  loader.unload();
-};
-
-
-exports['test button tab state'] = function*(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let { data } = loader.require('sdk/self');
-  let tabs = loader.require('sdk/tabs');
-
-  let button = ActionButton({
-    id: 'my-button-7',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let mainTab = tabs.activeTab;
-  let node = getWidget(button.id).node;
-
-  tabs.open('about:blank');
-
-  yield wait(tabs, 'ready');
-
-  let tab = tabs.activeTab;
-  let { activeWindow } = browserWindows;
-
-  // set window state
-  button.state(activeWindow, {
-    label: 'Window label',
-    icon: './window-icon.png',
-    badge: 'win',
-    badgeColor: 'blue'
-  });
-
-  // set previous active tab state
-  button.state(mainTab, {
-    label: 'Tab label',
-    icon: './tab-icon.png',
-    badge: 'tab',
-    badgeColor: 'red'
-  });
-
-  // set current active tab state
-  button.state(tab, {
-    icon: './another-tab-icon.png',
-    disabled: true,
-    badge: 't1',
-    badgeColor: 'green'
-  });
-
-  // check the states, be sure they won't be gc'ed
-  yield gc();
-
-  assert.equal(button.label, 'my button',
-    'global label unchanged');
-  assert.equal(button.icon, './icon.png',
-    'global icon unchanged');
-  assert.equal(button.disabled, false,
-    'global disabled unchanged');
-  assert.equal(button.badge, undefined,
-    'global badge unchanged')
-
-  let state = button.state(mainTab);
-
-  assert.equal(state.label, 'Tab label',
-    'previous tab label updated');
-  assert.equal(state.icon, './tab-icon.png',
-    'previous tab icon updated');
-  assert.equal(state.disabled, false,
-    'previous tab disabled unchanged');
-  assert.equal(state.badge, 'tab',
-    'previous tab badge unchanged')
-  assert.equal(state.badgeColor, 'red',
-    'previous tab badgeColor unchanged')
-
-  state = button.state(tab);
-
-  assert.equal(state.label, 'Window label',
-    'active tab inherited from window state');
-  assert.equal(state.icon, './another-tab-icon.png',
-    'active tab icon updated');
-  assert.equal(state.disabled, true,
-    'active disabled updated');
-  assert.equal(state.badge, 't1',
-    'active badge updated');
-  assert.equal(state.badgeColor, 'green',
-    'active badgeColor updated');
-
-  // change the global state
-  button.icon = './good-icon.png';
-
-  // delete the tab state
-  button.state(tab, null);
-
-  assert.equal(button.icon, './good-icon.png',
-    'global icon updated');
-  assert.equal(button.state(mainTab).icon, './tab-icon.png',
-    'previous tab icon unchanged');
-  assert.equal(button.state(tab).icon, './window-icon.png',
-    'tab icon inherited from window');
-  assert.equal(button.state(mainTab).badge, 'tab',
-    'previous tab badge is unchaged');
-  assert.equal(button.state(tab).badge, 'win',
-    'tab badge is inherited from window');
-
-  // delete the window state
-  button.state(activeWindow, null);
-
-  state = button.state(tab);
-
-  assert.equal(state.icon, './good-icon.png',
-    'tab icon inherited from global');
-  assert.equal(state.badge, undefined,
-    'tab badge inherited from global');
-  assert.equal(state.badgeColor, undefined,
-    'tab badgeColor inherited from global');
-
-  // check the node properties
-  yield new Promise(resolve => {
-    let target = {};
-    once(target, "ready", resolve);
-    emit(target, "ready");
-  });
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'node disabled is correct');
-  assert.equal(node.getAttribute('badge'), '',
-    'badge text is correct');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, '',
-    'badge color is correct');
-
-  mainTab.activate();
-
-  yield wait(tabs, 'activate');
-
-  // This is made in order to avoid to check the node before it
-  // is updated, need a better check
-  yield new Promise(resolve => {
-    let target = {};
-    once(target, "ready", resolve);
-    emit(target, "ready");
-  });
-
-  state = button.state(mainTab);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute('badge'), state.badge,
-    'badge text is correct');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  tab.close(loader.unload);
-
-  loader.unload();
-};
-
-exports['test button click'] = function*(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let labels = [];
-
-  let button = ActionButton({
-    id: 'my-button-8',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: ({label}) => labels.push(label)
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let chromeWindow = getMostRecentBrowserWindow();
-
-  let window = yield openBrowserWindow().then(focus);
-
-  button.state(mainWindow, { label: 'nothing' });
-  button.state(mainWindow.tabs.activeTab, { label: 'foo'})
-  button.state(browserWindows.activeWindow, { label: 'bar' });
-
-  button.click();
-
-  yield focus(chromeWindow);
-
-  button.click();
-
-  assert.deepEqual(labels, ['bar', 'foo'],
-    'button click works');
-
-  yield close(window);
-
-  loader.unload();
-}
-
-exports['test button icon set'] = function(assert) {
-  Cu.import("resource://gre/modules/Services.jsm");
-
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  // Test remote icon set
-  assert.throws(
-    () => ActionButton({
-      id: 'my-button-10',
-      label: 'my button',
-      icon: {
-        '16': 'http://www.mozilla.org/favicon.ico'
-      }
-    }),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  let button = ActionButton({
-    id: 'my-button-11',
-    label: 'my button',
-    icon: {
-      '5': './icon5.png',
-      '16': './icon16.png',
-      '32': './icon32.png',
-      '64': './icon64.png'
-    }
-  });
-
-  let { node, id: widgetId } = getWidget(button.id);
-  let { devicePixelRatio } = node.ownerGlobal;
-
-  let size = [5, 16, 32, 64].find(x => (16 * devicePixelRatio) <= x);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon[size].substr(2)),
-    'the icon is set properly in navbar');
-
-  size = [5, 16, 32, 64].find(x => (32 * devicePixelRatio) <= x);
-
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_PANEL);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon[size].substr(2)),
-    'the icon is set properly in panel');
-
-  // Using `loader.unload` without move back the button to the original area
-  // raises an error in the CustomizableUI. This is doesn't happen if the
-  // button is moved manually from navbar to panel. I believe it has to do
-  // with `addWidgetToArea` method, because even with a `timeout` the issue
-  // persist.
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
-
-  Cu.import("resource://gre/modules/Services.jsm");
-  loader.unload();
-}
-
-exports['test button icon set with only one option'] = function(assert) {
-  Cu.import("resource://gre/modules/Services.jsm");
-
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { data } = loader.require('sdk/self');
-
-  // Test remote icon set
-  assert.throws(
-    () => ActionButton({
-      id: 'my-button-10',
-      label: 'my button',
-      icon: {
-        '16': 'http://www.mozilla.org/favicon.ico'
-      }
-    }),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  let button = ActionButton({
-    id: 'my-button-11',
-    label: 'my button',
-    icon: {
-      '5': './icon5.png'
-    }
-  });
-
-  let { node, id: widgetId } = getWidget(button.id);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon['5'].substr(2)),
-    'the icon is set properly in navbar');
-
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_PANEL);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon['5'].substr(2)),
-    'the icon is set properly in panel');
-
-  // Using `loader.unload` without move back the button to the original area
-  // raises an error in the CustomizableUI. This is doesn't happen if the
-  // button is moved manually from navbar to panel. I believe it has to do
-  // with `addWidgetToArea` method, because even with a `timeout` the issue
-  // persist.
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
-
-  Cu.import("resource://gre/modules/Services.jsm");
-  loader.unload();
-}
-
-exports['test button state validation'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ActionButton({
-    id: 'my-button-12',
-    label: 'my button',
-    icon: './icon.png'
-  })
-
-  let state = button.state(button);
-
-  assert.throws(
-    () => button.state(button, { icon: 'http://www.mozilla.org/favicon.ico' }),
-    /^The option "icon"/,
-    'throws on remote icon given');
-
-  assert.throws(
-    () => button.state(button, { badge: true } ),
-    /^The option "badge"/,
-    'throws on wrong badge value given');
-
-  loader.unload();
-};
-
-exports['test button are not in private windows'] = function(assert, done) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let{ isPrivate } = loader.require('sdk/private-browsing');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ActionButton({
-    id: 'my-button-13',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  openPrivateBrowserWindow().then(window => {
-    assert.ok(isPrivate(window),
-      'the new window is private');
-
-    let { node } = getWidget(button.id, window);
-
-    assert.ok(!node || node.style.display === 'none',
-      'the button is not added / is not visible on private window');
-
-    return window;
-  }).
-  then(close).
-  then(loader.unload).
-  then(done, assert.fail)
-}
-
-exports['test button state are snapshot'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let tabs = loader.require('sdk/tabs');
-
-  let button = ActionButton({
-    id: 'my-button-14',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let state = button.state(button);
-  let windowState = button.state(browserWindows.activeWindow);
-  let tabState = button.state(tabs.activeTab);
-
-  assert.deepEqual(windowState, state,
-    'window state has the same properties of button state');
-
-  assert.deepEqual(tabState, state,
-    'tab state has the same properties of button state');
-
-  assert.notEqual(windowState, state,
-    'window state is not the same object of button state');
-
-  assert.notEqual(tabState, state,
-    'tab state is not the same object of button state');
-
-  assert.deepEqual(button.state(button), state,
-    'button state has the same content of previous button state');
-
-  assert.deepEqual(button.state(browserWindows.activeWindow), windowState,
-    'window state has the same content of previous window state');
-
-  assert.deepEqual(button.state(tabs.activeTab), tabState,
-    'tab state has the same content of previous tab state');
-
-  assert.notEqual(button.state(button), state,
-    'button state is not the same object of previous button state');
-
-  assert.notEqual(button.state(browserWindows.activeWindow), windowState,
-    'window state is not the same object of previous window state');
-
-  assert.notEqual(button.state(tabs.activeTab), tabState,
-    'tab state is not the same object of previous tab state');
-
-  loader.unload();
-}
-
-exports['test button icon object is a snapshot'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let icon = {
-    '16': './foo.png'
-  };
-
-  let button = ActionButton({
-    id: 'my-button-17',
-    label: 'my button',
-    icon: icon
-  });
-
-  assert.deepEqual(button.icon, icon,
-    'button.icon has the same properties of the object set in the constructor');
-
-  assert.notEqual(button.icon, icon,
-    'button.icon is not the same object of the object set in the constructor');
-
-  assert.throws(
-    () => button.icon[16] = './bar.png',
-    /16 is read-only/,
-    'properties of button.icon are ready-only'
-  );
-
-  let newIcon = {'16': './bar.png'};
-  button.icon = newIcon;
-
-  assert.deepEqual(button.icon, newIcon,
-    'button.icon has the same properties of the object set');
-
-  assert.notEqual(button.icon, newIcon,
-    'button.icon is not the same object of the object set');
-
-  loader.unload();
-}
-
-exports['test button after destroy'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let { activeTab } = loader.require('sdk/tabs');
-
-  let button = ActionButton({
-    id: 'my-button-15',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: () => assert.fail('onClick should not be called')
-  });
-
-  button.destroy();
-
-  assert.throws(
-    () => button.click(),
-    /^The state cannot be set or get/,
-    'button.click() not executed');
-
-  assert.throws(
-    () => button.label,
-    /^The state cannot be set or get/,
-    'button.label cannot be get after destroy');
-
-  assert.throws(
-    () => button.label = 'my label',
-    /^The state cannot be set or get/,
-    'button.label cannot be set after destroy');
-
-  assert.throws(
-    () => {
-      button.state(browserWindows.activeWindow, {
-        label: 'window label'
-      });
-    },
-    /^The state cannot be set or get/,
-    'window state label cannot be set after destroy');
-
-  assert.throws(
-    () => button.state(browserWindows.activeWindow).label,
-    /^The state cannot be set or get/,
-    'window state label cannot be get after destroy');
-
-  assert.throws(
-    () => {
-      button.state(activeTab, {
-        label: 'tab label'
-      });
-    },
-    /^The state cannot be set or get/,
-    'tab state label cannot be set after destroy');
-
-  assert.throws(
-    () => button.state(activeTab).label,
-    /^The state cannot be set or get/,
-    'window state label cannot se get after destroy');
-
-  loader.unload();
-};
-
-exports['test button badge property'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let button = ActionButton({
-    id: 'my-button-18',
-    label: 'my button',
-    icon: './icon.png',
-    badge: 123456
-  });
-
-  assert.equal(button.badge, 123456,
-    'badge is set');
-
-  assert.equal(button.badgeColor, undefined,
-    'badge color is not set');
-
-  let { node } = getWidget(button.id);
-  let { getComputedStyle } = node.ownerGlobal;
-  let badgeNode = badgeNodeFor(node);
-
-  assert.equal('1234', node.getAttribute('badge'),
-    'badge text is displayed up to four characters');
-
-  assert.equal(getComputedStyle(badgeNode).backgroundColor, 'rgb(217, 0, 0)',
-    'badge color is the default one');
-
-  button.badge = '危機';
-
-  assert.equal(button.badge, '危機',
-    'badge is properly set');
-
-  assert.equal('危機', node.getAttribute('badge'),
-    'badge text is displayed');
-
-  button.badge = '🐶🐰🐹';
-
-  assert.equal(button.badge, '🐶🐰🐹',
-    'badge is properly set');
-
-  assert.equal('🐶🐰🐹', node.getAttribute('badge'),
-    'badge text is displayed');
-
-  loader.unload();
-}
-exports['test button badge color'] = function(assert) {
-  let loader = Loader(module);
-  let { ActionButton } = loader.require('sdk/ui');
-
-  let button = ActionButton({
-    id: 'my-button-19',
-    label: 'my button',
-    icon: './icon.png',
-    badge: '+1',
-    badgeColor: 'blue'
-  });
-
-  assert.equal(button.badgeColor, 'blue',
-    'badge color is set');
-
-  let { node } = getWidget(button.id);
-  let { getComputedStyle } = node.ownerGlobal;
-  let badgeNode = badgeNodeFor(node);
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, 'blue',
-    'badge color is displayed properly');
-  assert.equal(getComputedStyle(badgeNode).backgroundColor, 'rgb(0, 0, 255)',
-    'badge color overrides the default one');
-
-  loader.unload();
-}
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-frame.js
+++ /dev/null
@@ -1,252 +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 = {
-  "engines": {
-    "Firefox": "*"
-  }
-};
-
-const { Cu } = require("chrome");
-const { Frame } = require("sdk/ui/frame");
-const { Toolbar } = require("sdk/ui/toolbar");
-const { Loader } = require("sdk/test/loader");
-const { identify } = require("sdk/ui/id");
-const { setTimeout } = require("sdk/timers");
-const { getMostRecentBrowserWindow, open } = require("sdk/window/utils");
-const { ready, loaded, close } = require("sdk/window/helpers");
-const { defer, all } = require("sdk/core/promise");
-const { send } = require("sdk/event/utils");
-const { object } = require("sdk/util/sequence");
-const { OutputPort } = require("sdk/output/system");
-const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
-const output = new OutputPort({ id: "toolbar-change" });
-
-const wait = (toolbar, event, times) => {
-  let { promise, resolve } = defer();
-  if (times) {
-    let resolveArray = [];
-    let counter = 0;
-    toolbar.on(event, function onEvent (e) {
-      resolveArray.push(e);
-      if (++counter === times) {
-        toolbar.off(event, onEvent);
-        resolve(resolveArray);
-      }
-    });
-  }
-  else {
-    toolbar.once(event, resolve);
-  }
-  return promise;
-};
-
-const stateEventsFor = frame =>
-  [wait(frame, "attach"), wait(frame, "ready"),
-   wait(frame, "load"), wait(frame, "detach")];
-
-
-const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
-  !!window.document.getElementById(id);
-
-// Use `Task.spawn` instead of `Task.async` because the returned function does not contain
-// a length for the test harness to determine whether the test should be executed
-exports["test frame API"] = function* (assert) {
-  const url = "data:text/html,frame-api";
-  assert.throws(() => new Frame(),
-                /The `options.url`/,
-                "must provide url");
-
-  assert.throws(() => new Frame({ url: "http://mozilla.org/" }),
-                /The `options.url`/,
-                "options.url must be local url");
-
-  assert.throws(() => new Frame({url: url, name: "4you" }),
-                /The `option.name` must be a valid/,
-                "can only take valid names");
-
-  const f1 = new Frame({ url: url });
-
-  assert.ok(f1.id, "frame has an id");
-  assert.equal(f1.url, void(0), "frame has no url until it's loaded");
-  assert.equal(typeof(f1.postMessage), "function",
-               "frames can postMessages");
-
-  const p1 = wait(f1, "register");
-
-  assert.throws(() => new Frame({ url: url }),
-                /Frame with this id already exists/,
-                "can't have two identical frames");
-
-
-  const f2 = new Frame({ name: "frame-2", url: url });
-  assert.pass("can create frame with same url but diff name");
-  const p2 = wait(f2, "register");
-
-  yield p1;
-  assert.pass("frame#1 was registered");
-  assert.equal(f1.url, url, "once registered it get's url");
-
-  yield p2;
-  assert.pass("frame#2 was registered");
-  assert.equal(f2.url, url, "once registered it get's url");
-
-  f1.destroy();
-  const f3 = new Frame({ url: url });
-  assert.pass("frame identical to destroyed one can be created");
-
-  yield wait(f3, "register");
-  assert.equal(f3.url, url, "url is set");
-  f2.destroy();
-  f3.destroy();
-};
-
-exports["test frame in toolbar"] = function* (assert) {
-  const assertEvent = (event, type) => {
-    assert.ok(event, "`" + type + "` event was dispatched");
-    assert.equal(event.type, type, "event.type is: " + type);
-    assert.equal(typeof(event.source), "object",
-                 "event.source is an object");
-    assert.equal(typeof(event.source.postMessage), "function",
-                 "messages can be posted to event.source");
-  };
-
-
-  const url = "data:text/html,toolbar-frame";
-  const f1 = new Frame({ url: url });
-  const t1 = new Toolbar({
-    title: "frame toolbar",
-    items: [f1]
-  });
-
-  const w1 = getMostRecentBrowserWindow();
-  const [a1, r1, l1] = stateEventsFor(f1);
-
-  assertEvent((yield a1), "attach");
-  assert.ok(isAttached(f1, w1), "frame is in the window#1");
-  assertEvent((yield r1), "ready");
-  assertEvent((yield l1), "load");
-
-  const [a2, r2, l2] = stateEventsFor(f1);
-  const w2 = open();
-
-  assertEvent((yield a2), "attach");
-  assert.ok(isAttached(f1, w2), "frame is in the window#2");
-  assertEvent((yield r2), "ready");
-  assertEvent((yield l2), "load");
-  assert.pass("frame attached to window#2");
-
-
-  const d1 = wait(f1, "detach");
-  yield close(w2);
-  assertEvent((yield d1), "detach");
-  assert.pass("frame detached when window is closed");
-
-  t1.destroy();
-
-  assertEvent((yield wait(f1, "detach")), "detach");
-  assert.ok(!isAttached(f1, w1), "frame was removed from window#1");
-  assert.pass("toolbar destroy detaches frame");
-};
-
-
-exports["test host to content messaging"] = function* (assert) {
-  const url = "data:text/html,<script>new " + function() {
-    window.addEventListener("message", (event) => {
-      if (event.data === "ping!")
-        event.source.postMessage("pong!", event.origin);
-    });
-  } + "</script>";
-  const f1 = new Frame({ name: "mailbox", url: url });
-  const t1 = new Toolbar({ title: "mailbox", items: [f1] });
-
-  const e1 = yield wait(f1, "ready");
-  e1.source.postMessage("ping!", e1.origin);
-
-  const pong = yield wait(f1, "message");
-  assert.equal(pong.data, "pong!", "received ping back");
-  t1.destroy();
-
-  yield wait(t1, "detach");
-};
-
-
-exports["test content to host messaging"] = function* (assert) {
-  const url = "data:text/html,<script>new " + function() {
-    window.addEventListener("message", (event) => {
-      if (event.data === "pong!")
-        event.source.postMessage("end", event.origin);
-    });
-
-    window.parent.postMessage("ping!", "*");
-  } + "</script>";
-
-  const f1 = new Frame({ name: "inbox", url: url });
-  const t1 = new Toolbar({ title: "inbox", items: [f1] });
-
-  const e1 = yield wait(f1, "message");
-  assert.equal(e1.data, "ping!", "received ping from content");
-
-  e1.source.postMessage("pong!", e1.origin);
-
-  const e2 = yield wait(f1, "message");
-  assert.equal(e2.data, "end", "received end message");
-
-  t1.destroy();
-  yield wait(t1, "detach");
-
-};
-
-
-exports["test direct messaging"] = function* (assert) {
-  let message;
-  const url = "data:text/html,<script>new " + function() {
-    var n = 0;
-    window.addEventListener("message", (event) => {
-      if (event.data === "inc")
-        n = n + 1;
-      if (event.data === "print")
-        event.source.postMessage({ n: n }, event.origin);
-    });
-  } + "</script>";
-
-  const w1 = getMostRecentBrowserWindow();
-  const f1 = new Frame({ url: url, name: "mail-cluster" });
-  const t1 = new Toolbar({ title: "claster", items: [f1] });
-
-  yield wait(f1, "ready");
-  assert.pass("document loaded in window#1");
-
-  const w2 = open();
-
-  yield wait(f1, "ready");
-  assert.pass("document loaded in window#2");
-
-  let messages = wait(f1, "message", 2);
-  f1.postMessage("inc", f1.origin);
-  f1.postMessage("print", f1.origin);
-
-  const [e1, e2] = yield messages;
-  assert.deepEqual(e1.data, {n: 1}, "received message from window#1");
-  assert.deepEqual(e2.data, {n: 1}, "received message from window#2");
-
-  message = wait(f1, "message");
-  e1.source.postMessage("inc", e1.origin);
-  e1.source.postMessage("print", e1.origin);
-  const e3 = yield message;
-  assert.deepEqual(e3.data, {n: 2}, "state changed in window#1");
-
-  message = wait(f1, "message");
-  e2.source.postMessage("print", e2.origin);
-  yield message;
-  assert.deepEqual(e2.data, {n:1}, "window#2 didn't received inc message");
-
-  yield close(w2);
-  t1.destroy();
-
-  yield wait(t1, "detach");
-};
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-id.js
+++ /dev/null
@@ -1,43 +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 { identify } = require('sdk/ui/id');
-const { Class } = require('sdk/core/heritage');
-
-const signature = /{[0-9a-f\-]+}/;
-
-exports['test generate id'] = function(assert) {
-  let first = identify({});
-  let second = identify({});
-
-  assert.ok(signature.test(first), 'first id has a correct signature');
-  assert.ok(signature.test(second), 'second id has a correct signature');
-
-  assert.notEqual(first, identify({}), 'identify generated new uuid [1]');
-  assert.notEqual(first, second, 'identify generated new uuid [2]');
-};
-
-exports['test get id'] = function(assert) {
-  let thing = {};
-  let thingID = identify(thing);
-
-  assert.equal(thingID, identify(thing), 'ids for things are cached by default');
-  assert.notEqual(identify(thing), identify({}), 'new ids for new things');
-};
-
-exports['test custom id definition for classes'] = function(assert) {
-  let Thing = Class({});
-  let thing = Thing();
-  let counter = 0;
-
-  identify.define(Thing, function(thing) {
-    return ++counter;
-  });
-
-  assert.equal(identify(thing), counter, 'it is possible to define custom identifications');
-  assert.ok(signature.test(identify({})), 'defining a custom identification does not affect the default behavior');
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-sidebar-private-browsing.js
+++ /dev/null
@@ -1,203 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Loader } = require('sdk/test/loader');
-const { show, hide } = require('sdk/ui/sidebar/actions');
-const { isShowing } = require('sdk/ui/sidebar/utils');
-const { getMostRecentBrowserWindow, isWindowPrivate } = require('sdk/window/utils');
-const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
-const { setTimeout } = require('sdk/timers');
-const { isPrivate } = require('sdk/private-browsing');
-const { data } = require('sdk/self');
-const { URL } = require('sdk/url');
-
-const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing,
-        getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand,
-        simulateClick, isChecked } = require('./sidebar/utils');
-
-exports.testSideBarIsNotInNewPrivateWindows = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSideBarIsNotInNewPrivateWindows';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  let startWindow = getMostRecentBrowserWindow();
-  let ele = startWindow.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added');
-
-  open(null, { features: { private: true } }).then(function(window) {
-      let ele = window.document.getElementById(makeID(testName));
-      assert.ok(isPrivate(window), 'the new window is private');
-      assert.equal(ele, null, 'sidebar element was not added');
-
-      sidebar.destroy();
-      assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-      assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
-
-      close(window).then(done, assert.fail);
-  })
-}
-
-exports.testSidebarIsNotOpenInNewPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarIsNotOpenInNewPrivateWindow';
-  let window = getMostRecentBrowserWindow();
-
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName,
-      url: 'data:text/html;charset=utf-8,'+testName
-    });
-
-    sidebar.on('show', function() {
-      assert.equal(isPrivate(window), false, 'the new window is not private');
-      assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-      assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-      let window2 = window.OpenBrowserWindow({ private: true });
-      windowPromise(window2, 'load').then(focus).then(function() {
-        // TODO: find better alt to setTimeout...
-        setTimeout(function() {
-          assert.equal(isPrivate(window2), true, 'the new window is private');
-          assert.equal(isSidebarShowing(window), true, 'the sidebar is showing in old window still');
-          assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing in the new private window');
-          assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-
-          sidebar.destroy();
-          close(window2).then(done);
-        }, 500);
-      })
-    });
-
-    sidebar.show();
-}
-
-// TEST: edge case where web panel is destroyed while loading
-exports.testDestroyEdgeCaseBugWithPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testDestroyEdgeCaseBug';
-  let window = getMostRecentBrowserWindow();
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  // NOTE: purposely not listening to show event b/c the event happens
-  //       between now and then.
-  sidebar.show();
-
-  assert.equal(isPrivate(window), false, 'the new window is not private');
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-
-  //assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-  open(null, { features: { private: true } }).then(focus).then(function(window2) {
-    assert.equal(isPrivate(window2), true, 'the new window is private');
-    assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing');
-    assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-
-    sidebar.destroy();
-    assert.pass('destroying the sidebar');
-
-    close(window2).then(function() {
-      let loader = Loader(module);
-
-      assert.equal(isPrivate(window), false, 'the current window is not private');
-
-      let sidebar = loader.require('sdk/ui/sidebar').Sidebar({
-        id: testName,
-        title: testName,
-        url:  'data:text/html;charset=utf-8,'+ testName,
-        onShow: function() {
-          assert.pass('onShow works for Sidebar');
-          loader.unload();
-
-          let sidebarMI = getSidebarMenuitems();
-          for (let mi of sidebarMI) {
-            assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar')
-            assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
-          }
-          assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-          assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-
-          done();
-        }
-      })
-
-      sidebar.show();
-      assert.pass('showing the sidebar');
-
-    });
-  });
-}
-
-exports.testShowInPrivateWindow = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowInPrivateWindow';
-  let window = getMostRecentBrowserWindow();
-  let { document } = window;
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  assert.ok(!isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is not checked');
-  assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
-
-  windowPromise(window.OpenBrowserWindow({ private: true }), 'load').then(function(window) {
-    let { document } = window;
-    assert.equal(isWindowPrivate(window), true, 'new window is private');
-    assert.equal(isPrivate(window), true, 'new window is private');
-
-    sidebar1.show().then(
-      function bad() {
-        assert.fail('a successful show should not happen here..');
-      },
-      function good() {
-        assert.equal(isShowing(sidebar1), false, 'the sidebar is still not showing');
-        assert.equal(document.getElementById(makeID(sidebar1.id)),
-                     null,
-                     'the menuitem dne on the private window');
-        assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
-
-        sidebar1.destroy();
-        close(window).then(done);
-      });
-  }, assert.fail);
-}
-
-// If the module doesn't support the app we're being run in, require() will
-// throw.  In that case, remove all tests above from exports, and add one dummy
-// test that passes.
-try {
-  require('sdk/ui/sidebar');
-}
-catch (err) {
-  if (!/^Unsupported Application/.test(err.message))
-    throw err;
-
-  module.exports = {
-    'test Unsupported Application': assert => assert.pass(err.message)
-  }
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-sidebar.js
+++ /dev/null
@@ -1,1577 +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 = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const { show, hide } = require('sdk/ui/sidebar/actions');
-const { isShowing } = require('sdk/ui/sidebar/utils');
-const { getMostRecentBrowserWindow, isFocused } = require('sdk/window/utils');
-const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
-const { setTimeout, setImmediate } = require('sdk/timers');
-const { isPrivate } = require('sdk/private-browsing');
-const data = require('./fixtures');
-const { URL } = require('sdk/url');
-const { once, off, emit } = require('sdk/event/core');
-const { defer, all } = require('sdk/core/promise');
-const { modelFor } = require('sdk/model/core');
-const { cleanUI } = require("sdk/test/utils");
-const { before, after } = require('sdk/test/utils');
-
-require('sdk/windows');
-
-const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing,
-        getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand,
-        simulateClick, isChecked } = require('./sidebar/utils');
-
-exports.testSidebarBasicLifeCycle = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarBasicLifeCycle';
-  let window = getMostRecentBrowserWindow();
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  let sidebarXUL = window.document.getElementById('sidebar');
-  assert.ok(sidebarXUL, 'sidebar xul element does exist');
-  assert.ok(!getExtraSidebarMenuitems().length, 'there are no extra sidebar menuitems');
-
-  assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 1');
-  let sidebarDetails = {
-    id: testName,
-    title: 'test',
-    url: 'data:text/html;charset=utf-8,'+testName
-  };
-  let sidebar = Sidebar(sidebarDetails);
-
-  // test the sidebar attributes
-  for (let key of Object.keys(sidebarDetails)) {
-    assert.equal(sidebarDetails[key], sidebar[key], 'the attributes match the input');
-  }
-
-  assert.pass('The Sidebar constructor worked');
-
-  let extraMenuitems = getExtraSidebarMenuitems();
-  assert.equal(extraMenuitems.length, 1, 'there is one extra sidebar menuitems');
-
-  let ele = window.document.getElementById(makeID(testName));
-  assert.equal(ele, extraMenuitems[0], 'the only extra menuitem is the one for our sidebar.')
-  assert.ok(ele, 'sidebar element was added');
-  assert.ok(!isChecked(ele), 'the sidebar is not displayed');
-  assert.equal(ele.getAttribute('label'), sidebar.title, 'the sidebar title is the menuitem label')
-
-  assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 2');
-
-  // explicit test of the on hide event
-  yield new Promise(resolve => {
-    sidebar.on('show', resolve);
-    sidebar.show();
-    assert.pass('showing sidebar..');
-  });
-
-  assert.pass('the show event was fired');
-  assert.equal(isSidebarShowing(window), true, 'sidebar is not showing 3');
-  assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-  assert.ok(isChecked(ele), 'the sidebar is displayed');
-
-  // explicit test of the on show event
-  yield new Promise(resolve => {
-    sidebar.on('hide', () => {
-      sidebar.once('detach', resolve);
-
-      assert.pass('the hide event was fired');
-      assert.ok(!isChecked(ele), 'the sidebar menuitem is not checked');
-      assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-      assert.equal(isSidebarShowing(window), false, 'the sidebar elemnt is hidden');
-    });
-    sidebar.hide();
-    assert.pass('hiding sidebar..');
-  });
-
-  // calling destroy twice should not matter
-  sidebar.destroy();
-  sidebar.destroy();
-
-  for (let mi of getSidebarMenuitems()) {
-    let id = mi.getAttribute('id');
-
-    if (BUILTIN_SIDEBAR_MENUITEMS.indexOf(id) < 0) {
-      assert.fail('the menuitem "' + id + '" is not a built-in sidebar');
-    }
-    assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
-  }
-
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  assert.pass('calling destroy worked without error');
-}
-
-exports.testSideBarIsInNewWindows = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSideBarIsInNewWindows';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  let startWindow = getMostRecentBrowserWindow();
-  let ele = startWindow.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added');
-
-  let window = yield open();
-
-  ele = window.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added');
-
-  // calling destroy twice should not matter
-  sidebar.destroy();
-  sidebar.destroy();
-
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
-}
-
-exports.testSideBarIsShowingInNewWindows = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSideBarIsShowingInNewWindows';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: URL('data:text/html;charset=utf-8,'+testName)
-  });
-
-  let startWindow = getMostRecentBrowserWindow();
-  let ele = startWindow.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added');
-
-  let oldEle = ele;
-
-  yield new Promise(resolve => {
-    sidebar.once('attach', function() {
-      assert.pass('attach event fired');
-
-      sidebar.once('show', function() {
-        assert.pass('show event fired');
-        resolve();
-      })
-    });
-    sidebar.show();
-  });
-
-  yield new Promise(resolve => {
-    sidebar.once('show', resolve);
-    startWindow.OpenBrowserWindow();
-  });
-
-  let window = getMostRecentBrowserWindow();
-  assert.notEqual(startWindow, window, 'window is new');
-
-  let sb = window.document.getElementById('sidebar');
-  yield new Promise(resolve => {
-    if (sb && sb.docShell && sb.contentDocument && sb.contentDocument.getElementById('web-panels-browser')) {
-      end();
-    }
-    else {
-      sb.addEventListener('DOMWindowCreated', end);
-    }
-    function end () {
-      sb.removeEventListener('DOMWindowCreated', end);
-      resolve();
-    }
-  })
-
-  ele = window.document.getElementById(makeID(testName));
-  assert.ok(ele, 'sidebar element was added 2');
-  assert.ok(isChecked(ele), 'the sidebar is checked');
-  assert.notEqual(ele, oldEle, 'there are two different sidebars');
-
-  assert.equal(isShowing(sidebar), true, 'the sidebar is showing in new window');
-
-  sidebar.destroy();
-
-  assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-  assert.ok(!isSidebarShowing(window), 'sidebar in most recent window is not showing');
-  assert.ok(!isSidebarShowing(startWindow), 'sidebar in most start window is not showing');
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
-}
-
-// TODO: determine if this is acceptable..
-/*
-exports.testAddonGlobalSimple = function(assert, done) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testAddonGlobalSimple';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: data.url('test-sidebar-addon-global.html')
-  });
-
-  sidebar.on('show', function({worker}) {
-    assert.pass('sidebar was attached');
-    assert.ok(!!worker, 'attach event has worker');
-
-    worker.port.on('X', function(msg) {
-      assert.equal(msg, '23', 'the final message is correct');
-
-      sidebar.destroy();
-
-      done();
-    });
-    worker.port.emit('X', '2');
-  });
-  show(sidebar);
-}
-*/
-
-exports.testAddonGlobalComplex = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testAddonGlobalComplex';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: data.url('test-sidebar-addon-global.html')
-  });
-
-  let worker = yield new Promise(resolve => {
-    sidebar.on('attach', resolve);
-    show(sidebar);
-  });
-
-  assert.pass('sidebar was attached');
-  assert.ok(!!worker, 'attach event has worker');
-
-
-  let msg = yield new Promise(resolve => {
-    worker.port.once('Y', resolve);
-  });
-
-  assert.equal(msg, '1', 'got event from worker');
-
-  msg = yield new Promise(resolve => {
-    worker.port.on('X', resolve);
-    worker.port.emit('X', msg + '2');
-  });
-
-  assert.equal(msg, '123', 'the final message is correct');
-
-  sidebar.destroy();
-}
-
-exports.testAddonReady = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testAddonReady';
-  let ready = defer();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: data.url('test-sidebar-addon-global.html'),
-    onReady: ready.resolve
-  });
-  show(sidebar);
-
-  let worker = yield ready.promise;
-  assert.pass('sidebar was attached');
-  assert.ok(!!worker, 'attach event has worker');
-
-  let msg = yield new Promise(resolve => {
-    worker.port.on('X', resolve);
-    worker.port.emit('X', '12');
-  });
-  assert.equal(msg, '123', 'the final message is correct');
-
-  sidebar.destroy();
-}
-
-exports.testShowingOneSidebarAfterAnother = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowingOneSidebarAfterAnother';
-
-  let sidebar1 = Sidebar({
-    id: testName + '1',
-    title: testName + '1',
-    url:  'data:text/html;charset=utf-8,'+ testName + 1
-  });
-  let sidebar2 = Sidebar({
-    id: testName + '2',
-    title: testName + '2',
-    url:  'data:text/html;charset=utf-8,'+ testName + 2
-  });
-
-  let window = getMostRecentBrowserWindow();
-  let IDs = [ sidebar1.id, sidebar2.id ];
-
-  let extraMenuitems = getExtraSidebarMenuitems(window);
-  assert.equal(extraMenuitems.length, 2, 'there are two extra sidebar menuitems');
-
-  function testShowing(sb1, sb2, sbEle) {
-    assert.equal(isShowing(sidebar1), sb1);
-    assert.equal(isShowing(sidebar2), sb2);
-    assert.equal(isSidebarShowing(window), sbEle);
-  }
-  testShowing(false, false, false);
-
-  yield show(sidebar1);
-  assert.pass('showed sidebar1');
-
-  testShowing(true, false, true);
-
-  for (let mi of getExtraSidebarMenuitems(window)) {
-    let menuitemID = mi.getAttribute('id').replace(/^jetpack-sidebar-/, '');
-    assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars');
-    assert.equal(isChecked(mi), menuitemID == sidebar1.id, 'the test sidebar menuitem has the correct checked value');
-  }
-
-  yield show(sidebar2);
-  assert.pass('showed sidebar2');
-
-  testShowing(false, true, true);
-
-  for (let mi of getExtraSidebarMenuitems(window)) {
-    let menuitemID = mi.getAttribute('id').replace(/^jetpack-sidebar-/, '');
-    assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars');
-    assert.equal(isChecked(mi), menuitemID == sidebar2.id, 'the test sidebar menuitem has the correct checked value');
-  }
-
-  sidebar1.destroy();
-  sidebar2.destroy();
-
-  testShowing(false, false, false);
-}
-
-exports.testSidebarUnload = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarUnload';
-  let loader = Loader(module);
-
-  let window = getMostRecentBrowserWindow();
-
-  assert.equal(isPrivate(window), false, 'the current window is not private');
-
-  let sidebar = loader.require('sdk/ui/sidebar').Sidebar({
-    id: testName,
-    title: testName,
-    url:  'data:text/html;charset=utf-8,'+ testName
-  });
-
-  yield sidebar.show();
-  assert.pass('showing the sidebar');
-
-  loader.unload();
-
-  for (let mi of getSidebarMenuitems()) {
-    assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar')
-    assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
-  }
-
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-}
-
-exports.testRelativeURL = function*(assert) {
-  const { merge } = require('sdk/util/object');
-  const self = require('sdk/self');
-
-  let loader = Loader(module, null, null, {
-    modules: {
-      'sdk/self': merge({}, self, {
-        data: merge({}, self.data, require('./fixtures'))
-      })
-    }
-  });
-
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-
-  let testName = 'testRelativeURL';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: './test-sidebar-addon-global.html'
-  });
-
-  yield new Promise(resolve => {
-    sidebar.on('attach', function(worker) {
-      assert.pass('sidebar was attached');
-      assert.ok(!!worker, 'attach event has worker');
-
-      worker.port.once('Y', function(msg) {
-        assert.equal(msg, '1', 'got event from worker');
-
-        worker.port.on('X', function(msg) {
-          assert.equal(msg, '123', 'the final message is correct');
-          resolve();
-        });
-        worker.port.emit('X', msg + '2');
-      })
-    });
-    sidebar.show();
-  });
-
-  sidebar.destroy();
-}
-
-exports.testRemoteContent = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testRemoteContent';
-  try {
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName,
-      url: 'http://dne.xyz.mozilla.org'
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "url" must be a valid local URI\./.test(e), 'remote content is not acceptable');
-  }
-}
-
-exports.testInvalidURL = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidURL';
-  try {
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName,
-      url: 'http:mozilla.org'
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
-  }
-}
-
-exports.testInvalidURLType = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidURLType';
-  try {
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
-  }
-}
-
-exports.testInvalidTitle = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidTitle';
-  try {
-    let sidebar = Sidebar({
-      id: testName,
-      title: '',
-      url: 'data:text/html;charset=utf-8,'+testName
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.equal('The option "title" must be one of the following types: string', e.message, 'invalid titles are not acceptable');
-  }
-}
-
-exports.testInvalidID = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidID';
-  try {
-    let sidebar = Sidebar({
-      id: '!',
-      title: testName,
-      url: 'data:text/html;charset=utf-8,'+testName
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
-  }
-}
-
-exports.testInvalidBlankID = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidBlankID';
-  try {
-    let sidebar = Sidebar({
-      id: '',
-      title: testName,
-      url: 'data:text/html;charset=utf-8,'+testName
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
-  }
-}
-
-exports.testInvalidNullID = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidNullID';
-  try {
-    let sidebar = Sidebar({
-      id: null,
-      title: testName,
-      url: 'data:text/html;charset=utf-8,'+testName
-    });
-    assert.fail('a bad sidebar was created..');
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
-  }
-}
-
-exports.testUndefinedID = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testInvalidUndefinedID';
-
-  try {
-    let sidebar = Sidebar({
-      title: testName,
-      url: 'data:text/html;charset=utf-8,' + testName
-    });
-
-    assert.ok(sidebar.id, 'an undefined id was accepted, id was creawted: ' + sidebar.id);
-    assert.ok(getMostRecentBrowserWindow().document.getElementById(makeID(sidebar.id)), 'the sidebar element was found');
-
-    sidebar.destroy();
-  }
-  catch(e) {
-    assert.fail('undefined ids are acceptable');
-    assert.fail(e.message);
-  }
-}
-
-// TEST: edge case where web panel is destroyed while loading
-exports.testDestroyEdgeCaseBug = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testDestroyEdgeCaseBug';
-  let window = getMostRecentBrowserWindow();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  // NOTE: purposely not listening to show event b/c the event happens
-  //       between now and then.
-  sidebar.show();
-
-  assert.equal(isPrivate(window), false, 'the new window is not private');
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-
-  //assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
-
-  let window2 = yield open().then(focus);
-
-  assert.equal(isPrivate(window2), false, 'the new window is not private');
-  assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing');
-  assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
-
-  sidebar.destroy();
-  assert.pass('destroying the sidebar');
-
-  yield close(window2);
-
-  let loader = Loader(module);
-
-  assert.equal(isPrivate(window), false, 'the current window is not private');
-
-  sidebar = loader.require('sdk/ui/sidebar').Sidebar({
-    id: testName,
-    title: testName,
-    url:  'data:text/html;charset=utf-8,'+ testName,
-    onShow: function() {
-    }
-  })
-
-  assert.pass('showing the sidebar');
-  yield sidebar.show();
-  loader.unload();
-
-  for (let mi of getSidebarMenuitems()) {
-    let id = mi.getAttribute('id');
-
-    if (BUILTIN_SIDEBAR_MENUITEMS.indexOf(id) < 0) {
-      assert.fail('the menuitem "' + id + '" is not a built-in sidebar');
-    }
-    assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
-  }
-  assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-}
-
-exports.testClickingACheckedMenuitem = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  const testName = 'testClickingACheckedMenuitem';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName,
-  });
-  assert.pass('sidebar was created');
-
-  let window = yield open().then(focus);
-  yield sidebar.show();
-  assert.pass('the show callback works');
-
-  let waitForHide = defer();
-  sidebar.once('hide', waitForHide.resolve);
-  let menuitem = window.document.getElementById(makeID(sidebar.id));
-  simulateCommand(menuitem);
-
-  yield waitForHide.promise;
-
-  assert.pass('clicking the menuitem after the sidebar has shown hides it.');
-  sidebar.destroy();
-};
-
-exports.testTitleSetter = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testTitleSetter';
-  let { document } = getMostRecentBrowserWindow();
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName,
-  });
-
-  assert.equal(sidebar1.title, testName, 'title getter works');
-
-  yield sidebar1.show();
-  assert.equal(document.getElementById(makeID(sidebar1.id)).getAttribute('label'),
-               testName,
-               'the menuitem label is correct');
-
-  assert.equal(document.getElementById('sidebar-title').value, testName, 'the menuitem label is correct');
-
-  sidebar1.title = 'foo';
-
-  assert.equal(sidebar1.title, 'foo', 'title getter works');
-
-  assert.equal(document.getElementById(makeID(sidebar1.id)).getAttribute('label'),
-               'foo',
-               'the menuitem label was updated');
-
-  assert.equal(document.getElementById('sidebar-title').value, 'foo', 'the sidebar title was updated');
-
-  sidebar1.destroy();
-}
-
-exports.testURLSetter = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testURLSetter';
-  let window = getMostRecentBrowserWindow();
-  let { document } = window;
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  assert.ok(!isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is not checked');
-  assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
-
-  window = yield windowPromise(window.OpenBrowserWindow(), 'load');
-  document = window.document;
-  assert.pass('new window was opened');
-
-  yield sidebar1.show();
-
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is checked');
-  assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
-
-  yield new Promise(resolve => {
-    sidebar1.once('show', resolve);
-    sidebar1.url = (url + '1');
-    assert.equal(sidebar1.url, (url + '1'), 'url getter works');
-    assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-    assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
-  });
-
-  assert.pass('setting the sidebar.url causes a show event');
-
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  assert.equal(isSidebarShowing(window), true, 'the new window sidebar is still showing');
-
-  assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is still checked');
-
-  sidebar1.destroy();
-  assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
-}
-
-exports.testDuplicateID = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testDuplicateID';
-  let window = getMostRecentBrowserWindow();
-  let { document } = window;
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  assert.throws(function() {
-    Sidebar({
-      id: testName,
-      title: testName + 1,
-      url: url + 2
-    }).destroy();
-  }, /The ID .+ seems already used\./i, 'duplicate IDs will throw errors');
-
-  sidebar1.destroy();
-}
-
-exports.testURLSetterToSameValueReloadsSidebar = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testURLSetterToSameValueReloadsSidebar';
-  let window = getMostRecentBrowserWindow();
-  let { document } = window;
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  assert.ok(!isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is not checked');
-  assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
-
-  window = yield windowPromise(window.OpenBrowserWindow(), 'load');
-  document = window.document;
-  assert.pass('new window was opened');
-
-  yield focus(window);
-  assert.pass('new window was focused');
-
-  yield sidebar1.show();
-
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is checked');
-  assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
-
-  let shown = defer();
-  sidebar1.once('show', shown.resolve);
-  sidebar1.url = url;
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
-
-  yield shown.promise;
-
-  assert.pass('setting the sidebar.url causes a show event');
-
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  assert.ok(isSidebarShowing(window), 'the new window sidebar is still showing');
-
-  assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
-               'the menuitem is still checked');
-
-  sidebar1.destroy();
-}
-
-exports.testShowingInOneWindowDoesNotAffectOtherWindows = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowingInOneWindowDoesNotAffectOtherWindows';
-  let window1 = getMostRecentBrowserWindow();
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar1 = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  assert.equal(sidebar1.url, url, 'url getter works');
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  let checkCount = 1;
-  function checkSidebarShowing(window, expected) {
-    assert.pass('check count ' + checkCount++);
-
-    let mi = window.document.getElementById(makeID(sidebar1.id));
-    if (mi) {
-      assert.equal(isChecked(mi), expected,
-                   'the menuitem is not checked');
-    }
-    assert.equal(isSidebarShowing(window), expected || false, 'the new window sidebar is not showing');
-  }
-  checkSidebarShowing(window1, false);
-
-  let window = yield windowPromise(window1.OpenBrowserWindow(), 'load');
-  let { document } = window;
-  assert.pass('new window was opened!');
-
-  // waiting for show
-  yield sidebar1.show();
-
-  // check state of the new window
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  checkSidebarShowing(window, true);
-
-  // check state of old window
-  checkSidebarShowing(window1, false);
-
-  yield sidebar1.show();
-
-  // check state of the new window
-  assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
-  checkSidebarShowing(window, true);
-
-  // check state of old window
-  checkSidebarShowing(window1, false);
-
-  // calling destroy() twice should not matter
-  sidebar1.destroy();
-  sidebar1.destroy();
-
-  // check state of the new window
-  assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
-  checkSidebarShowing(window, undefined);
-
-  // check state of old window
-  checkSidebarShowing(window1, undefined);
-}
-
-exports.testHidingAHiddenSidebarRejects = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testHidingAHiddenSidebarRejects';
-  let url = 'data:text/html;charset=utf-8,'+testName;
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  yield sidebar.hide().then(assert.fail, assert.pass);
-
-  sidebar.destroy();
-}
-
-exports.testGCdSidebarsOnUnload = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  const window = getMostRecentBrowserWindow();
-
-  let testName = 'testGCdSidebarsOnUnload';
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-
-  // IMPORTANT: make no reference to the sidebar instance, so it is GC'd
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  yield sidebar.show();
-  sidebar = null;
-
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-
-  let menuitemID = makeID(testName);
-
-  assert.ok(window.document.getElementById(menuitemID), 'the menuitem was found');
-
-  yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
-
-  loader.unload();
-
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing after unload');
-  assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
-}
-
-exports.testGCdShowingSidebarsOnUnload = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  const window = getMostRecentBrowserWindow();
-
-  let testName = 'testGCdShowingSidebarsOnUnload';
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  yield sidebar.show();
-
-  sidebar = null;
-
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
-
-  let menuitemID = makeID(testName);
-
-  assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found');
-
-  yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
-
-  assert.equal(isSidebarShowing(window), true, 'the sidebar is still showing after gc');
-  assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found after gc');
-
-  loader.unload();
-
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing after unload');
-  assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
-}
-
-exports.testDetachEventOnWindowClose = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  let window = getMostRecentBrowserWindow();
-
-  let testName = 'testDetachEventOnWindowClose';
-  let url = 'data:text/html;charset=utf-8,' + testName;
-
-  window = yield windowPromise(window.OpenBrowserWindow(), 'load').then(focus);
-
-  yield new Promise(resolve => {
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName,
-      url: url,
-      onAttach: function() {
-        assert.pass('the attach event is fired');
-        window.close();
-      },
-      onDetach: resolve
-    });
-
-    sidebar.show();
-  });
-
-  assert.pass('the detach event is fired when the window showing it closes');
-  loader.unload();
-}
-
-exports.testHideEventOnWindowClose = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  let window = getMostRecentBrowserWindow();
-
-  let testName = 'testDetachEventOnWindowClose';
-  let url = 'data:text/html;charset=utf-8,' + testName;
-
-
-  window = yield windowPromise(window.OpenBrowserWindow(), 'load').then(focus);
-  yield new Promise(resolve => {
-    let sidebar = Sidebar({
-      id: testName,
-      title: testName,
-      url: url,
-      onAttach: function() {
-        assert.pass('the attach event is fired');
-        window.close();
-      },
-      onHide: resolve
-    });
-
-    sidebar.show();
-  });
-
-  assert.pass('the hide event is fired when the window showing it closes');
-  loader.unload();
-}
-
-exports.testGCdHiddenSidebarsOnUnload = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  const window = getMostRecentBrowserWindow();
-
-  let testName = 'testGCdHiddenSidebarsOnUnload';
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
-
-  // IMPORTANT: make no reference to the sidebar instance, so it is GC'd
-  Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  let menuitemID = makeID(testName);
-
-  assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found');
-
-  yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
-
-  assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found after gc');
-
-  loader.unload();
-
-  assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
-}
-
-exports.testSidebarGettersAndSettersAfterDestroy = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarGettersAndSettersAfterDestroy';
-  let url = 'data:text/html;charset=utf-8,'+testName;
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  sidebar.destroy();
-
-  assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
-
-  assert.throws(() => sidebar.id = 'foo-tang',
-    /^setting getter-only property/,
-    'id cannot be set at runtime');
-
-  assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
-
-  assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
-  sidebar.title = 'boo-tang';
-  assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
-
-  assert.equal(sidebar.url, undefined, 'sidebar after destroy has no url');
-  sidebar.url = url + 'barz';
-  assert.equal(sidebar.url, undefined, 'sidebar after destroy has no url');
-}
-
-
-exports.testSidebarLeakCheckDestroyAfterAttach = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testSidebarLeakCheckDestroyAfterAttach';
-  let window = getMostRecentBrowserWindow();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  yield new Promise(resolve => {
-    sidebar.on('attach', resolve);
-    assert.pass('showing the sidebar');
-    sidebar.show();
-  })
-
-  assert.pass('the sidebar was shown');
-
-  sidebar.on('show', () => {
-    assert.fail('the sidebar show listener should have been removed');
-  });
-  assert.pass('added a sidebar show listener');
-
-  sidebar.on('hide', () => {
-    assert.fail('the sidebar hide listener should have been removed');
-  });
-  assert.pass('added a sidebar hide listener');
-
-  yield new Promise(resolve => {
-    let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
-    panelBrowser.contentWindow.addEventListener('unload', function() {
-      resolve();
-    }, {once: true});
-    sidebar.destroy();
-  });
-
-  assert.pass('the sidebar web panel was unloaded properly');
-}
-
-exports.testSidebarLeakCheckUnloadAfterAttach = function*(assert) {
-  const loader = Loader(module);
-  const { Sidebar } = loader.require('sdk/ui/sidebar');
-  let testName = 'testSidebarLeakCheckUnloadAfterAttach';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName
-  });
-
-  let window = yield open().then(focus);
-
-  yield new Promise(resolve => {
-    sidebar.on('attach', resolve);
-    assert.pass('showing the sidebar');
-    sidebar.show();
-  });
-
-  assert.pass('the sidebar was shown');
-
-  sidebar.on('show', function() {
-    assert.fail('the sidebar show listener should have been removed');
-  });
-  assert.pass('added a sidebar show listener');
-
-  sidebar.on('hide', function() {
-    assert.fail('the sidebar hide listener should have been removed');
-  });
-  assert.pass('added a sidebar hide listener');
-
-  let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
-  yield new Promise(resolve => {
-    panelBrowser.contentWindow.addEventListener('unload', function() {
-      resolve();
-    }, {once: true});
-    loader.unload();
-  });
-
-  assert.pass('the sidebar web panel was unloaded properly');
-}
-
-exports.testTwoSidebarsWithSameTitleAndURL = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testTwoSidebarsWithSameTitleAndURL';
-
-  let title = testName;
-  let url = 'data:text/html;charset=utf-8,' + testName;
-
-  let sidebar1 = Sidebar({
-    id: testName + 1,
-    title: title,
-    url: url
-  });
-
-  assert.throws(function() {
-    Sidebar({
-      id: testName + 2,
-      title: title,
-      url: url
-    }).destroy();
-  }, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
-
-  let sidebar2 = Sidebar({
-    id: testName + 2,
-    title: title,
-    url: 'data:text/html;charset=utf-8,X'
-  });
-
-  assert.throws(function() {
-    sidebar2.url = url;
-  }, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
-
-  sidebar2.title = 'foo';
-  sidebar2.url = url;
-
-  assert.throws(function() {
-    sidebar2.title = title;
-  }, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
-
-  sidebar1.destroy();
-  sidebar2.destroy();
-}
-
-exports.testChangingURLBackToOriginalValue = function(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testChangingURLBackToOriginalValue';
-
-  let title = testName;
-  let url = 'data:text/html;charset=utf-8,' + testName;
-  let count = 0;
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: title,
-    url: url
-  });
-
-  sidebar.url = url + 2;
-  assert.equal(sidebar.url, url + 2, 'the sidebar.url is correct');
-  sidebar.url = url;
-  assert.equal(sidebar.url, url, 'the sidebar.url is correct');
-
-  sidebar.title = 'foo';
-  assert.equal(sidebar.title, 'foo', 'the sidebar.title is correct');
-  sidebar.title = title;
-  assert.equal(sidebar.title, title, 'the sidebar.title is correct');
-
-  sidebar.destroy();
-
-  assert.pass('Changing values back to originals works');
-}
-
-exports.testShowToOpenXToClose = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowToOpenXToClose';
-
-  let title = testName;
-  let url = 'data:text/html;charset=utf-8,' + testName;
-  let window = getMostRecentBrowserWindow();
-  let shown = defer();
-  let hidden = defer();
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url,
-    onShow: shown.resolve,
-    onHide: hidden.resolve
-  });
-
-  let menuitem = window.document.getElementById(makeID(sidebar.id));
-
-  assert.ok(!isChecked(menuitem), 'menuitem is not checked');
-
-  sidebar.show();
-
-  yield shown.promise;
-
-  assert.ok(isChecked(menuitem), 'menuitem is checked');
-
-  let closeButton = window.document.querySelector('#sidebar-close');
-  simulateCommand(closeButton);
-
-  yield hidden.promise;
-
-  assert.ok(!isChecked(menuitem), 'menuitem is not checked');
-
-  sidebar.destroy();
-}
-
-exports.testShowToOpenMenuitemToClose = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testShowToOpenMenuitemToClose';
-
-  let title = testName;
-  let url = 'data:text/html;charset=utf-8,' + testName;
-  let window = getMostRecentBrowserWindow();
-
-  let hidden = defer();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url,
-    onHide: hidden.resolve
-  });
-
-  let menuitem = window.document.getElementById(makeID(sidebar.id));
-
-  assert.ok(!isChecked(menuitem), 'menuitem is not checked');
-
-  yield sidebar.show();
-
-  assert.ok(isChecked(menuitem), 'menuitem is checked');
-
-  simulateCommand(menuitem);
-
-  yield hidden.promise;
-
-  assert.ok(!isChecked(menuitem), 'menuitem is not checked');
-
-  sidebar.destroy();
-}
-
-exports.testDestroyWhileNonBrowserWindowIsOpen = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testDestroyWhileNonBrowserWindowIsOpen';
-  let url = 'data:text/html;charset=utf-8,' + testName;
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: url
-  });
-
-  let window = yield open('chrome://browser/content/aboutDialog.xul');
-
-  yield sidebar.show();
-  assert.equal(isSidebarShowing(getMostRecentBrowserWindow()), true, 'the sidebar is showing');
-
-  sidebar.destroy();
-  assert.pass('sidebar was destroyed while a non browser window was open');
-
-  yield cleanUI();
-  assert.equal(isSidebarShowing(getMostRecentBrowserWindow()), false, 'the sidebar is not showing');
-}
-
-exports.testEventListeners = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testWhatThisIsInSidebarEventListeners';
-  let eventListenerOrder = [];
-
-  let constructorOnShow = defer();
-  let constructorOnHide = defer();
-  let constructorOnAttach = defer();
-  let constructorOnReady = defer();
-
-  let onShow = defer();
-  let onHide = defer();
-  let onAttach = defer();
-  let onReady = defer();
-
-  let onceShow = defer();
-  let onceHide = defer();
-  let onceAttach = defer();
-  let onceReady = defer();
-
-  function testThis() {
-    assert(this, sidebar, '`this` is correct');
-  }
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,' + testName,
-    onShow: function() {
-      assert.equal(this, sidebar, '`this` is correct in onShow');
-      eventListenerOrder.push('onShow');
-      constructorOnShow.resolve();
-    },
-    onAttach: function() {
-      assert.equal(this, sidebar, '`this` is correct in onAttach');
-      eventListenerOrder.push('onAttach');
-      constructorOnAttach.resolve();
-    },
-    onReady: function() {
-      assert.equal(this, sidebar, '`this` is correct in onReady');
-      eventListenerOrder.push('onReady');
-      constructorOnReady.resolve();
-    },
-    onHide: function() {
-      assert.equal(this, sidebar, '`this` is correct in onHide');
-      eventListenerOrder.push('onHide');
-      constructorOnHide.resolve();
-    }
-  });
-
-  sidebar.once('show', function() {
-    assert.equal(this, sidebar, '`this` is correct in once show');
-    eventListenerOrder.push('once show');
-    onceShow.resolve();
-  });
-  sidebar.once('attach', function() {
-    assert.equal(this, sidebar, '`this` is correct in once attach');
-    eventListenerOrder.push('once attach');
-    onceAttach.resolve();
-  });
-  sidebar.once('ready', function() {
-    assert.equal(this, sidebar, '`this` is correct in once ready');
-    eventListenerOrder.push('once ready');
-    onceReady.resolve();
-  });
-  sidebar.once('hide', function() {
-    assert.equal(this, sidebar, '`this` is correct in once hide');
-    eventListenerOrder.push('once hide');
-    onceHide.resolve();
-  });
-
-  sidebar.on('show', function() {
-    assert.equal(this, sidebar, '`this` is correct in on show');
-    eventListenerOrder.push('on show');
-    onShow.resolve();
-
-    sidebar.hide();
-  });
-  sidebar.on('attach', function() {
-    assert.equal(this, sidebar, '`this` is correct in on attach');
-    eventListenerOrder.push('on attach');
-    onAttach.resolve();
-  });
-  sidebar.on('ready', function() {
-    assert.equal(this, sidebar, '`this` is correct in on ready');
-    eventListenerOrder.push('on ready');
-    onReady.resolve();
-  });
-  sidebar.on('hide', function() {
-    assert.equal(this, sidebar, '`this` is correct in on hide');
-    eventListenerOrder.push('on hide');
-    onHide.resolve();
-  });
-
-  sidebar.show();
-
-  yield all([constructorOnShow.promise,
-      constructorOnAttach.promise,
-      constructorOnReady.promise,
-      constructorOnHide.promise,
-      onceShow.promise,
-      onceAttach.promise,
-      onceReady.promise,
-      onceHide.promise,
-      onShow.promise,
-      onAttach.promise,
-      onReady.promise,
-      onHide.promise]);
-
-  assert.equal(eventListenerOrder.join(), [
-    'onAttach',
-    'once attach',
-    'on attach',
-    'onReady',
-    'once ready',
-    'on ready',
-    'onShow',
-    'once show',
-    'on show',
-    'onHide',
-    'once hide',
-    'on hide'
-  ].join(), 'the event order was correct');
-
-  sidebar.destroy();
-}
-
-// For more information see Bug 920780
-exports.testAttachDoesNotEmitWhenShown = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-  let testName = 'testAttachDoesNotEmitWhenShown';
-  let count = 0;
-
-  let attached = defer();
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,'+testName,
-    onAttach: function() {
-      if (count > 2) {
-        assert.fail('sidebar was attached again..');
-      }
-      else {
-        assert.pass('sidebar was attached ' + count + ' time(s)');
-      }
-
-      count++;
-      attached.resolve();
-    }
-  });
-
-  sidebar.show();
-
-  yield attached.promise;
-
-  let shownFired = 0;
-  let onShow = () => shownFired++;
-  sidebar.on('show', onShow);
-
-  yield sidebar.show();
-  assert.equal(shownFired, 0, 'shown should not be fired again when already showing from after attach');
-
-  yield sidebar.hide();
-  assert.pass("the sidebar was hidden");
-
-  yield sidebar.show();
-  assert.equal(shownFired, 1, 'shown was emitted when `show` called after being hidden');
-
-  yield sidebar.show();
-  assert.equal(shownFired, 1, 'shown was not emitted again if already being shown');
-
-  sidebar.off('show', onShow);
-  sidebar.destroy();
-}
-
-exports.testShowHideRawWindowArg = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-
-  let testName = 'testShowHideRawWindowArg';
-
-  assert.pass("Creating sidebar");
-
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,' + testName
-  });
-
-  assert.pass("Created sidebar");
-
-  let mainWindow = getMostRecentBrowserWindow();
-  let newWindow = yield windowPromise(mainWindow.OpenBrowserWindow(), 'load');
-  assert.pass("Created the new window");
-
-  yield focus(newWindow);
-  assert.pass("Focused the new window");
-
-  let newWindow2 = yield windowPromise(mainWindow.OpenBrowserWindow(), 'load');
-  assert.pass("Created the second new window");
-
-  yield focus(newWindow2);
-  assert.pass("Focused the second new window");
-
-  yield sidebar.show(newWindow);
-
-  assert.pass('the sidebar was shown');
-  assert.equal(isSidebarShowing(mainWindow), false, 'sidebar is not showing in main window');
-  assert.equal(isSidebarShowing(newWindow2), false, 'sidebar is not showing in second window');
-  assert.equal(isSidebarShowing(newWindow), true, 'sidebar is showing in new window');
-
-  assert.ok(isFocused(newWindow2), 'main window is still focused');
-
-  yield sidebar.hide(newWindow);
-
-  assert.equal(isFocused(newWindow2), true, 'second window is still focused');
-  assert.equal(isSidebarShowing(mainWindow), false, 'sidebar is not showing in main window');
-  assert.equal(isSidebarShowing(newWindow2), false, 'sidebar is not showing in second window');
-  assert.equal(isSidebarShowing(newWindow), false, 'sidebar is not showing in new window');
-
-  sidebar.destroy();
-}
-
-exports.testShowHideSDKWindowArg = function*(assert) {
-  const { Sidebar } = require('sdk/ui/sidebar');
-
-  let testName = 'testShowHideSDKWindowArg';
-  let sidebar = Sidebar({
-    id: testName,
-    title: testName,
-    url: 'data:text/html;charset=utf-8,' + testName
-  });
-
-  let mainWindow = getMostRecentBrowserWindow();
-  let newWindow = yield open().then(focus);
-  let newSDKWindow = modelFor(newWindow);
-
-  yield focus(mainWindow);
-
-  yield sidebar.show(newSDKWindow);
-
-  assert.pass('the sidebar was shown');
-  assert.ok(!isSidebarShowing(mainWindow), 'sidebar is not showing in main window');
-  assert.ok(isSidebarShowing(newWindow), 'sidebar is showing in new window');
-
-  assert.ok(isFocused(mainWindow), 'main window is still focused');
-
-  yield sidebar.hide(newSDKWindow);
-
-  assert.ok(isFocused(mainWindow), 'main window is still focused');
-  assert.ok(!isSidebarShowing(mainWindow), 'sidebar is not showing in main window');
-  assert.ok(!isSidebarShowing(newWindow), 'sidebar is not showing in new window');
-  sidebar.destroy();
-}
-
-before(exports, (name, assert) => {
-  assert.equal(isSidebarShowing(), false, 'no sidebar is showing');
-});
-
-after(exports, function*(name, assert) {
-  assert.pass("Cleaning new windows and tabs");
-  yield cleanUI();
-  assert.equal(isSidebarShowing(), false, 'no sidebar is showing');
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-toggle-button.js
+++ /dev/null
@@ -1,1386 +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 = {
-  'engines': {
-    'Firefox': '> 28'
-  }
-};
-
-const { Cu } = require('chrome');
-const { Loader } = require('sdk/test/loader');
-const { data } = require('sdk/self');
-const { open, focus, close } = require('sdk/window/helpers');
-const { setTimeout } = require('sdk/timers');
-const { getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { partial } = require('sdk/lang/functional');
-const { wait } = require('./event/helpers');
-const { gc } = require('sdk/test/memory');
-const packaging = require("@loader/options");
-
-const openBrowserWindow = partial(open, null, {features: {toolbar: true}});
-const openPrivateBrowserWindow = partial(open, null,
-  {features: {toolbar: true, private: true}});
-
-const badgeNodeFor = (node) =>
-  node.ownerDocument.getAnonymousElementByAttribute(node,
-                                      'class', 'toolbarbutton-badge');
-
-function getWidget(buttonId, window = getMostRecentBrowserWindow()) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  const { AREA_NAVBAR } = CustomizableUI;
-
-  let widgets = CustomizableUI.getWidgetIdsInArea(AREA_NAVBAR).
-    filter((id) => id.startsWith('toggle-button--') && id.endsWith(buttonId));
-
-  if (widgets.length === 0)
-    throw new Error('Widget with id `' + id +'` not found.');
-
-  if (widgets.length > 1)
-    throw new Error('Unexpected number of widgets: ' + widgets.length)
-
-  return CustomizableUI.getWidget(widgets[0]).forWindow(window);
-};
-
-exports['test basic constructor validation'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  assert.throws(
-    () => ToggleButton({}),
-    /^The option/,
-    'throws on no option given');
-
-  // Test no label
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', icon: './icon.png'}),
-    /^The option "label"/,
-    'throws on no label given');
-
-  // Test no id
-  assert.throws(
-    () => ToggleButton({ label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no id given');
-
-  // Test no icon
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'my button' }),
-    /^The option "icon"/,
-    'throws on no icon given');
-
-
-  // Test empty label
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: '', icon: './icon.png' }),
-    /^The option "label"/,
-    'throws on no valid label given');
-
-  // Test invalid id
-  assert.throws(
-    () => ToggleButton({ id: 'my button', label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no valid id given');
-
-  // Test empty id
-  assert.throws(
-    () => ToggleButton({ id: '', label: 'my button', icon: './icon.png' }),
-    /^The option "id"/,
-    'throws on no valid id given');
-
-  // Test remote icon
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'my button', icon: 'http://www.mozilla.org/favicon.ico'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: no absolute URI to local resource, neither relative './'
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'my button', icon: 'icon.png'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: no absolute URI to local resource, neither relative './'
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'my button', icon: 'foo and bar'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  // Test wrong icon: '../' is not allowed
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'my button', icon: '../icon.png'}),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'button', icon: './i.png', badge: true}),
-    /^The option "badge"/,
-    'throws on no valid badge given');
-
-  assert.throws(
-    () => ToggleButton({ id: 'my-button', label: 'button', icon: './i.png', badgeColor: true}),
-    /^The option "badgeColor"/,
-    'throws on no valid badge given');
-
-  loader.unload();
-};
-
-exports['test button added'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // check defaults
-  assert.equal(button.disabled, false,
-    'disabled is set to default `false` value');
-
-  let { node } = getWidget(button.id);
-
-  assert.ok(!!node, 'The button is in the navbar');
-
-  assert.equal(button.label, node.getAttribute('label'),
-    'label is set');
-
-  assert.equal(button.label, node.getAttribute('tooltiptext'),
-    'tooltip is set');
-
-  assert.equal(data.url(button.icon.substr(2)), node.getAttribute('image'),
-    'icon is set');
-
-  assert.equal("", node.getAttribute('badge'),
-    'badge attribute is empty');
-
-  loader.unload();
-}
-exports['test button is not garbaged'] = function (assert, done) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  ToggleButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: () => {
-      loader.unload();
-      done();
-    }
-  });
-
-  gc().then(() => {
-    let { node } = getWidget('my-button-1');
-
-    assert.ok(!!node, 'The button is in the navbar');
-
-    assert.equal('my button', node.getAttribute('label'),
-      'label is set');
-
-    assert.equal(data.url('icon.png'), node.getAttribute('image'),
-      'icon is set');
-
-    // ensure the listener is not gc'ed too
-    node.click();
-  }).catch(assert.fail);
-}
-
-exports['test button added with resource URI'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-1',
-    label: 'my button',
-    icon: data.url('icon.png')
-  });
-
-  assert.equal(button.icon, data.url('icon.png'),
-    'icon is set');
-
-  let { node } = getWidget(button.id);
-
-  assert.equal(button.icon, node.getAttribute('image'),
-    'icon on node is set');
-
-  loader.unload();
-}
-
-exports['test button duplicate id'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-2',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  assert.throws(() => {
-    let doppelganger = ToggleButton({
-      id: 'my-button-2',
-      label: 'my button',
-      icon: './icon.png'
-    });
-  },
-  /^The ID/,
-  'No duplicates allowed');
-
-  loader.unload();
-}
-
-exports['test button multiple destroy'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-2',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  button.destroy();
-  button.destroy();
-  button.destroy();
-
-  assert.pass('multiple destroy doesn\'t matter');
-
-  loader.unload();
-}
-
-exports['test button removed on dispose'] = function(assert, done) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let widgetId;
-
-  CustomizableUI.addListener({
-    onWidgetDestroyed: function(id) {
-      if (id === widgetId) {
-        CustomizableUI.removeListener(this);
-
-        assert.pass('button properly removed');
-        loader.unload();
-        done();
-      }
-    }
-  });
-
-  let button = ToggleButton({
-    id: 'my-button-3',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
-  // was removed or it's not in the UX build yet
-  widgetId = getWidget(button.id).id;
-
-  button.destroy();
-};
-
-exports['test button global state updated'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-4',
-    label: 'my button',
-    icon: './icon.png',
-  });
-
-  // Tried to use `getWidgetIdsInArea` but seems undefined, not sure if it
-  // was removed or it's not in the UX build yet
-
-  let { node, id: widgetId } = getWidget(button.id);
-
-  // check read-only properties
-
-  assert.throws(() => button.id = 'another-id',
-    /^setting getter-only property/,
-    'id cannot be set at runtime');
-
-  assert.equal(button.id, 'my-button-4',
-    'id is unchanged');
-  assert.equal(node.id, widgetId,
-    'node id is unchanged');
-
-  // check writable properties
-
-  button.label = 'New label';
-  assert.equal(button.label, 'New label',
-    'label is updated');
-  assert.equal(node.getAttribute('label'), 'New label',
-    'node label is updated');
-  assert.equal(node.getAttribute('tooltiptext'), 'New label',
-    'node tooltip is updated');
-
-  button.icon = './new-icon.png';
-  assert.equal(button.icon, './new-icon.png',
-    'icon is updated');
-  assert.equal(node.getAttribute('image'), data.url('new-icon.png'),
-    'node image is updated');
-
-  button.disabled = true;
-  assert.equal(button.disabled, true,
-    'disabled is updated');
-  assert.equal(node.getAttribute('disabled'), 'true',
-    'node disabled is updated');
-
-  button.badge = '+2';
-  button.badgeColor = 'blue';
-
-  assert.equal(button.badge, '+2',
-    'badge is updated');
-  assert.equal(node.getAttribute('bagde'), '',
-    'node badge is updated');
-
-  assert.equal(button.badgeColor, 'blue',
-    'badgeColor is updated');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, 'blue',
-    'badge color is updated');
-
-  // TODO: test validation on update
-
-  loader.unload();
-}
-
-exports['test button global state set and get with state method'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-16',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  // read the button's state
-  let state = button.state(button);
-
-  assert.equal(state.label, 'my button',
-    'label is correct');
-  assert.equal(state.icon, './icon.png',
-    'icon is correct');
-  assert.equal(state.disabled, false,
-    'disabled is correct');
-
-  // set the new button's state
-  button.state(button, {
-    label: 'New label',
-    icon: './new-icon.png',
-    disabled: true,
-    badge: '+2',
-    badgeColor: 'blue'
-  });
-
-  assert.equal(button.label, 'New label',
-    'label is updated');
-  assert.equal(button.icon, './new-icon.png',
-    'icon is updated');
-  assert.equal(button.disabled, true,
-    'disabled is updated');
-  assert.equal(button.badge, '+2',
-    'badge is updated');
-  assert.equal(button.badgeColor, 'blue',
-    'badgeColor is updated');
-
-  loader.unload();
-}
-
-exports['test button global state updated on multiple windows'] = function*(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-5',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let nodes = [getWidget(button.id).node];
-
-  let window = yield openBrowserWindow();
-
-  nodes.push(getWidget(button.id, window).node);
-
-  button.label = 'New label';
-  button.icon = './new-icon.png';
-  button.disabled = true;
-  button.badge = '+10';
-  button.badgeColor = 'green';
-
-  for (let node of nodes) {
-    assert.equal(node.getAttribute('label'), 'New label',
-      'node label is updated');
-    assert.equal(node.getAttribute('tooltiptext'), 'New label',
-      'node tooltip is updated');
-
-    assert.equal(button.icon, './new-icon.png',
-      'icon is updated');
-    assert.equal(node.getAttribute('image'), data.url('new-icon.png'),
-      'node image is updated');
-
-    assert.equal(button.disabled, true,
-      'disabled is updated');
-    assert.equal(node.getAttribute('disabled'), 'true',
-      'node disabled is updated');
-
-    assert.equal(button.badge, '+10',
-      'badge is updated')
-    assert.equal(button.badgeColor, 'green',
-      'badgeColor is updated')
-    assert.equal(node.getAttribute('badge'), '+10',
-      'node badge is updated')
-    assert.equal(badgeNodeFor(node).style.backgroundColor, 'green',
-      'node badge color is updated')
-  };
-
-  yield close(window);
-
-  loader.unload();
-};
-
-exports['test button window state'] = function*(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ToggleButton({
-    id: 'my-button-6',
-    label: 'my button',
-    icon: './icon.png',
-    badge: '+1',
-    badgeColor: 'red'
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let nodes = [getWidget(button.id).node];
-
-  let window = yield openBrowserWindow().then(focus);
-
-  nodes.push(getWidget(button.id, window).node);
-
-  let { activeWindow } = browserWindows;
-
-  button.state(activeWindow, {
-    label: 'New label',
-    icon: './new-icon.png',
-    disabled: true,
-    badge: '+2',
-    badgeColor : 'green'
-  });
-
-  // check the states
-
-  assert.equal(button.label, 'my button',
-    'global label unchanged');
-  assert.equal(button.icon, './icon.png',
-    'global icon unchanged');
-  assert.equal(button.disabled, false,
-    'global disabled unchanged');
-  assert.equal(button.badge, '+1',
-    'global badge unchanged');
-  assert.equal(button.badgeColor, 'red',
-    'global badgeColor unchanged');
-
-  let state = button.state(mainWindow);
-
-  assert.equal(state.label, 'my button',
-    'previous window label unchanged');
-  assert.equal(state.icon, './icon.png',
-    'previous window icon unchanged');
-  assert.equal(state.disabled, false,
-    'previous window disabled unchanged');
-  assert.deepEqual(button.badge, '+1',
-    'previouswindow badge unchanged');
-  assert.deepEqual(button.badgeColor, 'red',
-    'previous window badgeColor unchanged');
-
-  state = button.state(activeWindow);
-
-  assert.equal(state.label, 'New label',
-    'active window label updated');
-  assert.equal(state.icon, './new-icon.png',
-    'active window icon updated');
-  assert.equal(state.disabled, true,
-    'active disabled updated');
-  assert.equal(state.badge, '+2',
-    'active badge updated');
-  assert.equal(state.badgeColor, 'green',
-    'active badgeColor updated');
-
-  // change the global state, only the windows without a state are affected
-
-  button.label = 'A good label';
-  button.badge = '+3';
-
-  assert.equal(button.label, 'A good label',
-    'global label updated');
-  assert.equal(button.state(mainWindow).label, 'A good label',
-    'previous window label updated');
-  assert.equal(button.state(activeWindow).label, 'New label',
-    'active window label unchanged');
-  assert.equal(button.state(activeWindow).badge, '+2',
-    'active badge unchanged');
-  assert.equal(button.state(activeWindow).badgeColor, 'green',
-    'active badgeColor unchanged');
-  assert.equal(button.state(mainWindow).badge, '+3',
-    'previous window badge updated');
-  assert.equal(button.state(mainWindow).badgeColor, 'red',
-    'previous window badgeColor unchanged');
-
-  // delete the window state will inherits the global state again
-
-  button.state(activeWindow, null);
-
-  state = button.state(activeWindow);
-
-  assert.equal(state.label, 'A good label',
-    'active window label inherited');
-  assert.equal(state.badge, '+3',
-    'previous window badge inherited');
-  assert.equal(button.badgeColor, 'red',
-    'previous window badgeColor inherited');
-
-  // check the nodes properties
-  let node = nodes[0];
-
-  state = button.state(mainWindow);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute("badge"), state.badge,
-    'badge is correct');
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  node = nodes[1];
-  state = button.state(activeWindow);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute('badge'), state.badge,
-    'badge is correct');
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  yield close(window);
-
-  loader.unload();
-};
-
-
-exports['test button tab state'] = function*(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let tabs = loader.require('sdk/tabs');
-
-  let button = ToggleButton({
-    id: 'my-button-7',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let mainTab = tabs.activeTab;
-  let node = getWidget(button.id).node;
-
-  tabs.open('about:blank');
-
-  yield wait(tabs, 'ready');
-
-  let tab = tabs.activeTab;
-  let { activeWindow } = browserWindows;
-
-  // set window state
-  button.state(activeWindow, {
-    label: 'Window label',
-    icon: './window-icon.png',
-    badge: 'win',
-    badgeColor: 'blue'
-  });
-
-  // set previous active tab state
-  button.state(mainTab, {
-    label: 'Tab label',
-    icon: './tab-icon.png',
-    badge: 'tab',
-    badgeColor: 'red'
-  });
-
-  // set current active tab state
-  button.state(tab, {
-    icon: './another-tab-icon.png',
-    disabled: true,
-    badge: 't1',
-    badgeColor: 'green'
-  });
-
-  // check the states, be sure they won't be gc'ed
-  yield gc();
-
-  assert.equal(button.label, 'my button',
-    'global label unchanged');
-  assert.equal(button.icon, './icon.png',
-    'global icon unchanged');
-  assert.equal(button.disabled, false,
-    'global disabled unchanged');
-  assert.equal(button.badge, undefined,
-    'global badge unchanged')
-
-  let state = button.state(mainTab);
-
-  assert.equal(state.label, 'Tab label',
-    'previous tab label updated');
-  assert.equal(state.icon, './tab-icon.png',
-    'previous tab icon updated');
-  assert.equal(state.disabled, false,
-    'previous tab disabled unchanged');
-  assert.equal(state.badge, 'tab',
-    'previous tab badge unchanged')
-  assert.equal(state.badgeColor, 'red',
-    'previous tab badgeColor unchanged')
-
-  state = button.state(tab);
-
-  assert.equal(state.label, 'Window label',
-    'active tab inherited from window state');
-  assert.equal(state.icon, './another-tab-icon.png',
-    'active tab icon updated');
-  assert.equal(state.disabled, true,
-    'active disabled updated');
-  assert.equal(state.badge, 't1',
-    'active badge updated');
-  assert.equal(state.badgeColor, 'green',
-    'active badgeColor updated');
-
-  // change the global state
-  button.icon = './good-icon.png';
-
-  // delete the tab state
-  button.state(tab, null);
-
-  assert.equal(button.icon, './good-icon.png',
-    'global icon updated');
-  assert.equal(button.state(mainTab).icon, './tab-icon.png',
-    'previous tab icon unchanged');
-  assert.equal(button.state(tab).icon, './window-icon.png',
-    'tab icon inherited from window');
-  assert.equal(button.state(mainTab).badge, 'tab',
-    'previous tab badge is unchaged');
-  assert.equal(button.state(tab).badge, 'win',
-    'tab badge is inherited from window');
-
-  // delete the window state
-  button.state(activeWindow, null);
-
-  state = button.state(tab);
-
-  assert.equal(state.icon, './good-icon.png',
-    'tab icon inherited from global');
-  assert.equal(state.badge, undefined,
-    'tab badge inherited from global');
-  assert.equal(state.badgeColor, undefined,
-    'tab badgeColor inherited from global');
-
-  // check the node properties
-  yield wait();
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'node disabled is correct');
-  assert.equal(node.getAttribute('badge'), '',
-    'badge text is correct');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, '',
-    'badge color is correct');
-
-  mainTab.activate();
-
-  yield wait(tabs, 'activate');
-
-  // This is made in order to avoid to check the node before it
-  // is updated, need a better check
-  yield wait();
-
-  state = button.state(mainTab);
-
-  assert.equal(node.getAttribute('label'), state.label,
-    'node label is correct');
-  assert.equal(node.getAttribute('tooltiptext'), state.label,
-    'node tooltip is correct');
-  assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)),
-    'node image is correct');
-  assert.equal(node.hasAttribute('disabled'), state.disabled,
-    'disabled is correct');
-  assert.equal(node.getAttribute('badge'), state.badge,
-    'badge text is correct');
-  assert.equal(badgeNodeFor(node).style.backgroundColor, state.badgeColor,
-    'badge color is correct');
-
-  tab.close(loader.unload);
-
-  loader.unload();
-};
-
-exports['test button click'] = function*(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let labels = [];
-
-  let button = ToggleButton({
-    id: 'my-button-8',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: ({label}) => labels.push(label)
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let chromeWindow = getMostRecentBrowserWindow();
-
-  let window = yield openBrowserWindow().then(focus);
-
-  button.state(mainWindow, { label: 'nothing' });
-  button.state(mainWindow.tabs.activeTab, { label: 'foo'})
-  button.state(browserWindows.activeWindow, { label: 'bar' });
-
-  button.click();
-
-  yield focus(chromeWindow);
-
-  button.click();
-
-  assert.deepEqual(labels, ['bar', 'foo'],
-    'button click works');
-
-  yield close(window);
-
-  loader.unload();
-}
-
-exports['test button icon set'] = function(assert) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  // Test remote icon set
-  assert.throws(
-    () => ToggleButton({
-      id: 'my-button-10',
-      label: 'my button',
-      icon: {
-        '16': 'http://www.mozilla.org/favicon.ico'
-      }
-    }),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  let button = ToggleButton({
-    id: 'my-button-11',
-    label: 'my button',
-    icon: {
-      '5': './icon5.png',
-      '16': './icon16.png',
-      '32': './icon32.png',
-      '64': './icon64.png'
-    }
-  });
-
-  let { node, id: widgetId } = getWidget(button.id);
-  let { devicePixelRatio } = node.ownerGlobal;
-
-  let size = 16 * devicePixelRatio;
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon[size].substr(2)),
-    'the icon is set properly in navbar');
-
-  size = 32 * devicePixelRatio;
-
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_PANEL);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon[size].substr(2)),
-    'the icon is set properly in panel');
-
-  // Using `loader.unload` without move back the button to the original area
-  // raises an error in the CustomizableUI. This is doesn't happen if the
-  // button is moved manually from navbar to panel. I believe it has to do
-  // with `addWidgetToArea` method, because even with a `timeout` the issue
-  // persist.
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
-
-  loader.unload();
-}
-
-exports['test button icon set with only one option'] = function(assert) {
-  const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  // Test remote icon set
-  assert.throws(
-    () => ToggleButton({
-      id: 'my-button-10',
-      label: 'my button',
-      icon: {
-        '16': 'http://www.mozilla.org/favicon.ico'
-      }
-    }),
-    /^The option "icon"/,
-    'throws on no valid icon given');
-
-  let button = ToggleButton({
-    id: 'my-button-11',
-    label: 'my button',
-    icon: {
-      '5': './icon5.png'
-    }
-  });
-
-  let { node, id: widgetId } = getWidget(button.id);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon['5'].substr(2)),
-    'the icon is set properly in navbar');
-
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_PANEL);
-
-  assert.equal(node.getAttribute('image'), data.url(button.icon['5'].substr(2)),
-    'the icon is set properly in panel');
-
-  // Using `loader.unload` without move back the button to the original area
-  // raises an error in the CustomizableUI. This is doesn't happen if the
-  // button is moved manually from navbar to panel. I believe it has to do
-  // with `addWidgetToArea` method, because even with a `timeout` the issue
-  // persist.
-  CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
-
-  loader.unload();
-}
-
-exports['test button state validation'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ToggleButton({
-    id: 'my-button-12',
-    label: 'my button',
-    icon: './icon.png'
-  })
-
-  let state = button.state(button);
-
-  assert.throws(
-    () => button.state(button, { icon: 'http://www.mozilla.org/favicon.ico' }),
-    /^The option "icon"/,
-    'throws on remote icon given');
-
-  assert.throws(
-    () => button.state(button, { badge: true } ),
-    /^The option "badge"/,
-    'throws on wrong badge value given');
-
-  loader.unload();
-};
-
-exports['test button are not in private windows'] = function(assert, done) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let{ isPrivate } = loader.require('sdk/private-browsing');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ToggleButton({
-    id: 'my-button-13',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  openPrivateBrowserWindow().then(window => {
-    assert.ok(isPrivate(window),
-      'the new window is private');
-
-    let { node } = getWidget(button.id, window);
-
-    assert.ok(!node || node.style.display === 'none',
-      'the button is not added / is not visible on private window');
-
-    return window;
-  }).
-  then(close).
-  then(loader.unload).
-  then(done, assert.fail)
-}
-
-exports['test button state are snapshot'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let tabs = loader.require('sdk/tabs');
-
-  let button = ToggleButton({
-    id: 'my-button-14',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let state = button.state(button);
-  let windowState = button.state(browserWindows.activeWindow);
-  let tabState = button.state(tabs.activeTab);
-
-  assert.deepEqual(windowState, state,
-    'window state has the same properties of button state');
-
-  assert.deepEqual(tabState, state,
-    'tab state has the same properties of button state');
-
-  assert.notEqual(windowState, state,
-    'window state is not the same object of button state');
-
-  assert.notEqual(tabState, state,
-    'tab state is not the same object of button state');
-
-  assert.deepEqual(button.state(button), state,
-    'button state has the same content of previous button state');
-
-  assert.deepEqual(button.state(browserWindows.activeWindow), windowState,
-    'window state has the same content of previous window state');
-
-  assert.deepEqual(button.state(tabs.activeTab), tabState,
-    'tab state has the same content of previous tab state');
-
-  assert.notEqual(button.state(button), state,
-    'button state is not the same object of previous button state');
-
-  assert.notEqual(button.state(browserWindows.activeWindow), windowState,
-    'window state is not the same object of previous window state');
-
-  assert.notEqual(button.state(tabs.activeTab), tabState,
-    'tab state is not the same object of previous tab state');
-
-  loader.unload();
-}
-
-exports['test button icon object is a snapshot'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let icon = {
-    '16': './foo.png'
-  };
-
-  let button = ToggleButton({
-    id: 'my-button-17',
-    label: 'my button',
-    icon: icon
-  });
-
-  assert.deepEqual(button.icon, icon,
-    'button.icon has the same properties of the object set in the constructor');
-
-  assert.notEqual(button.icon, icon,
-    'button.icon is not the same object of the object set in the constructor');
-
-  assert.throws(
-    () => button.icon[16] = './bar.png',
-    /16 is read-only/,
-    'properties of button.icon are ready-only'
-  );
-
-  let newIcon = {'16': './bar.png'};
-  button.icon = newIcon;
-
-  assert.deepEqual(button.icon, newIcon,
-    'button.icon has the same properties of the object set');
-
-  assert.notEqual(button.icon, newIcon,
-    'button.icon is not the same object of the object set');
-
-  loader.unload();
-}
-
-exports['test button after destroy'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let { activeTab } = loader.require('sdk/tabs');
-
-  let button = ToggleButton({
-    id: 'my-button-15',
-    label: 'my button',
-    icon: './icon.png',
-    onClick: () => assert.fail('onClick should not be called')
-  });
-
-  button.destroy();
-
-  assert.throws(
-    () => button.click(),
-    /^The state cannot be set or get/,
-    'button.click() not executed');
-
-  assert.throws(
-    () => button.label,
-    /^The state cannot be set or get/,
-    'button.label cannot be get after destroy');
-
-  assert.throws(
-    () => button.label = 'my label',
-    /^The state cannot be set or get/,
-    'button.label cannot be set after destroy');
-
-  assert.throws(
-    () => {
-      button.state(browserWindows.activeWindow, {
-        label: 'window label'
-      });
-    },
-    /^The state cannot be set or get/,
-    'window state label cannot be set after destroy');
-
-  assert.throws(
-    () => button.state(browserWindows.activeWindow).label,
-    /^The state cannot be set or get/,
-    'window state label cannot be get after destroy');
-
-  assert.throws(
-    () => {
-      button.state(activeTab, {
-        label: 'tab label'
-      });
-    },
-    /^The state cannot be set or get/,
-    'tab state label cannot be set after destroy');
-
-  assert.throws(
-    () => button.state(activeTab).label,
-    /^The state cannot be set or get/,
-    'window state label cannot se get after destroy');
-
-  loader.unload();
-};
-
-exports['test button badge property'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-18',
-    label: 'my button',
-    icon: './icon.png',
-    badge: 123456
-  });
-
-  assert.equal(button.badge, 123456,
-    'badge is set');
-
-  assert.equal(button.badgeColor, undefined,
-    'badge color is not set');
-
-  let { node } = getWidget(button.id);
-  let { getComputedStyle } = node.ownerGlobal;
-  let badgeNode = badgeNodeFor(node);
-
-  assert.equal('1234', node.getAttribute('badge'),
-    'badge text is displayed up to four characters');
-
-  assert.equal(getComputedStyle(badgeNode).backgroundColor, 'rgb(217, 0, 0)',
-    'badge color is the default one');
-
-  button.badge = '危機';
-
-  assert.equal(button.badge, '危機',
-    'badge is properly set');
-
-  assert.equal('危機', node.getAttribute('badge'),
-    'badge text is displayed');
-
-  button.badge = '🐶🐰🐹';
-
-  assert.equal(button.badge, '🐶🐰🐹',
-    'badge is properly set');
-
-  assert.equal('🐶🐰🐹', node.getAttribute('badge'),
-    'badge text is displayed');
-
-  loader.unload();
-}
-exports['test button badge color'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-
-  let button = ToggleButton({
-    id: 'my-button-19',
-    label: 'my button',
-    icon: './icon.png',
-    badge: '+1',
-    badgeColor: 'blue'
-  });
-
-  assert.equal(button.badgeColor, 'blue',
-    'badge color is set');
-
-  let { node } = getWidget(button.id);
-  let { getComputedStyle } = node.ownerGlobal;
-  let badgeNode = badgeNodeFor(node);
-
-  assert.equal(badgeNodeFor(node).style.backgroundColor, 'blue',
-    'badge color is displayed properly');
-  assert.equal(getComputedStyle(badgeNode).backgroundColor, 'rgb(0, 0, 255)',
-    'badge color overrides the default one');
-
-  loader.unload();
-}
-
-// toggle button only
-exports['test button checked'] = function(assert, done) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let events = [];
-
-  let button = ToggleButton({
-    id: 'my-button-9',
-    label: 'my button',
-    icon: './icon.png',
-    checked: true,
-    onClick: ({label}) => events.push('clicked:' + label),
-    onChange: state => events.push('changed:' + state.label + ':' + state.checked)
-  });
-
-  let { node } = getWidget(button.id);
-
-  assert.equal(node.getAttribute('type'), 'checkbox',
-    'node type is properly set');
-
-  let mainWindow = browserWindows.activeWindow;
-  let chromeWindow = getMostRecentBrowserWindow();
-
-  openBrowserWindow().then(focus).then(window => {
-    button.state(mainWindow, { label: 'nothing' });
-    button.state(mainWindow.tabs.activeTab, { label: 'foo'})
-    button.state(browserWindows.activeWindow, { label: 'bar' });
-
-    button.click();
-    button.click();
-
-    focus(chromeWindow).then(() => {
-      button.click();
-      button.click();
-
-      assert.deepEqual(events, [
-          'clicked:bar', 'changed:bar:false', 'clicked:bar', 'changed:bar:true',
-          'clicked:foo', 'changed:foo:false', 'clicked:foo', 'changed:foo:true'
-        ],
-        'button change events works');
-
-      close(window).
-        then(loader.unload).
-        then(done, assert.fail);
-    })
-  }).catch(assert.fail);
-}
-
-exports['test button is checked on window level'] = function(assert, done) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-  let tabs = loader.require('sdk/tabs');
-
-  let button = ToggleButton({
-    id: 'my-button-20',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let mainTab = tabs.activeTab;
-
-  assert.equal(button.checked, false,
-    'global state, checked is `false`.');
-  assert.equal(button.state(mainTab).checked, false,
-    'tab state, checked is `false`.');
-  assert.equal(button.state(mainWindow).checked, false,
-    'window state, checked is `false`.');
-
-  button.click();
-
-  tabs.open({
-    url: 'about:blank',
-    onActivate: function onActivate(tab) {
-      tab.removeListener('activate', onActivate);
-
-      assert.notEqual(mainTab, tab,
-        'the current tab is not the same.');
-
-      assert.equal(button.checked, false,
-        'global state, checked is `false`.');
-      assert.equal(button.state(mainTab).checked, true,
-        'previous tab state, checked is `true`.');
-      assert.equal(button.state(tab).checked, true,
-        'current tab state, checked is `true`.');
-      assert.equal(button.state(mainWindow).checked, true,
-        'window state, checked is `true`.');
-
-      openBrowserWindow().then(focus).then(window => {
-        let { activeWindow } = browserWindows;
-        let { activeTab } = activeWindow.tabs;
-
-        assert.equal(button.checked, false,
-          'global state, checked is `false`.');
-        assert.equal(button.state(activeTab).checked, false,
-          'tab state, checked is `false`.');
-
-        assert.equal(button.state(activeWindow).checked, false,
-          'window state, checked is `false`.');
-
-        tab.close(()=> {
-          close(window).
-            then(loader.unload).
-            then(done, assert.fail);
-        })
-      }).
-      catch(assert.fail);
-    }
-  });
-
-};
-
-exports['test button click do not messing up states'] = function(assert) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { browserWindows } = loader.require('sdk/windows');
-
-  let button = ToggleButton({
-    id: 'my-button-21',
-    label: 'my button',
-    icon: './icon.png'
-  });
-
-  let mainWindow = browserWindows.activeWindow;
-  let { activeTab } = mainWindow.tabs;
-
-  button.state(mainWindow, { icon: './new-icon.png' });
-  button.state(activeTab, { label: 'foo'})
-
-  assert.equal(button.state(mainWindow).label, 'my button',
-    'label property for window state, properly derived from global state');
-
-  assert.equal(button.state(activeTab).icon, './new-icon.png',
-    'icon property for tab state, properly derived from window state');
-
-  button.click();
-
-  button.label = 'bar';
-
-  assert.equal(button.state(mainWindow).label, 'bar',
-    'label property for window state, properly derived from global state');
-
-  button.state(mainWindow, null);
-
-  assert.equal(button.state(activeTab).icon, './icon.png',
-    'icon property for tab state, properly derived from window state');
-
-  loader.unload();
-}
-
-exports['test buttons can have anchored panels'] = function(assert, done) {
-  let loader = Loader(module);
-  let { ToggleButton } = loader.require('sdk/ui');
-  let { Panel } = loader.require('sdk/panel');
-  let { identify } = loader.require('sdk/ui/id');
-  let { getActiveView } = loader.require('sdk/view/core');
-
-  let b1 = ToggleButton({
-    id: 'my-button-22',
-    label: 'my button',
-    icon: './icon.png',
-    onChange: ({checked}) => checked && panel.show()
-  });
-
-  let b2 = ToggleButton({
-    id: 'my-button-23',
-    label: 'my button',
-    icon: './icon.png',
-    onChange: ({checked}) => checked && panel.show({position: b2})
-  });
-
-  let panel = Panel({
-    position: b1
-  });
-
-  let { document } = getMostRecentBrowserWindow();
-  let b1Node = document.getElementById(identify(b1));
-  let b2Node = document.getElementById(identify(b2));
-  let panelNode = getActiveView(panel);
-
-  panel.once('show', () => {
-    assert.ok(b1.state('window').checked,
-      'button is checked');
-
-    assert.equal(panelNode.getAttribute('type'), 'arrow',
-      'the panel is a arrow type');
-
-    assert.strictEqual(b1Node, panelNode.anchorNode,
-      'the panel is anchored properly to the button given in costructor');
-
-    panel.hide();
-
-    panel.once('show', () => {
-      assert.ok(b2.state('window').checked,
-        'button is checked');
-
-      assert.equal(panelNode.getAttribute('type'), 'arrow',
-        'the panel is a arrow type');
-
-      // test also that the button passed in `show` method, takes the precedence
-      // over the button set in panel's constructor.
-      assert.strictEqual(b2Node, panelNode.anchorNode,
-        'the panel is anchored properly to the button passed to show method');
-
-      loader.unload();
-
-      done();
-    });
-
-    b2.click();
-  });
-
-  b1.click();
-}
-
-
-if (packaging.isNative) {
-  module.exports = {
-    "test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
-  };
-}
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-ui-toolbar.js
+++ /dev/null
@@ -1,511 +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 = {
-  "engines": {
-    "Firefox": "*"
-  }
-};
-
-const { Toolbar } = require("sdk/ui/toolbar");
-const { Loader } = require("sdk/test/loader");
-const { identify } = require("sdk/ui/id");
-const { getMostRecentBrowserWindow, open, getOuterId } = require("sdk/window/utils");
-const { ready, close } = require("sdk/window/helpers");
-const { defer } = require("sdk/core/promise");
-const { send, stop, Reactor } = require("sdk/event/utils");
-const { object } = require("sdk/util/sequence");
-const { CustomizationInput } = require("sdk/input/customizable-ui");
-const { OutputPort } = require("sdk/output/system");
-const output = new OutputPort({ id: "toolbar-change" });
-const { cleanUI } = require('sdk/test/utils');
-const tabs = require("sdk/tabs");
-
-const wait = (toolbar, event) => {
-  let { promise, resolve } = defer();
-  toolbar.once(event, resolve);
-  return promise;
-};
-
-const show = ({id}) => send(output, object([id, {collapsed: false}]));
-const hide = ({id}) => send(output, object([id, {collapsed: true}]));
-const retitle = ({id}, title) => send(output, object([id, {title: title}]));
-
-const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
-  !!window.document.getElementById(id);
-
-const isCollapsed = ({id}, window=getMostRecentBrowserWindow()) =>
-  window.document.getElementById(id).getAttribute("collapsed") === "true";
-
-const closeViaButton = ({id}, window=getMostRecentBrowserWindow()) =>
-  window.document.getElementById("close-" + id).click();
-
-const readTitle = ({id}, window=getMostRecentBrowserWindow()) =>
-  window.document.getElementById(id).getAttribute("toolbarname");
-
-exports["test toolbar API"] = function*(assert) {
-  assert.throws(() => new Toolbar(),
-                /The `option.title`/,
-                "toolbar requires title");
-
-  assert.throws(() => new Toolbar({ hidden: false }),
-                /The `option.title`/,
-                "toolbar requires title");
-
-  const t1 = new Toolbar({ title: "foo" });
-
-  assert.throws(() => new Toolbar({ title: "foo" }),
-                /already exists/,
-                "can't create identical toolbars");
-
-  assert.ok(t1.id, "toolbar has an id");
-  assert.equal(t1.id, identify(t1), "identify returns toolbar id");
-  assert.deepEqual(t1.items, [], "toolbar items are empty");
-  assert.equal(t1.title, void(0), "title is void until attached");
-  assert.equal(t1.hidden, void(0), "hidden is void until attached");
-
-  yield wait(t1, "attach");
-
-  assert.equal(t1.title, "foo", "title is set after attach");
-  assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
-
-  assert.throws(() => new Toolbar({ title: "foo" }),
-                /already exists/,
-                "still can't create identical toolbar");
-
-
-  const t2 = new Toolbar({ title: "bar", hidden: true });
-  assert.pass("can create different toolbar though");
-
-  assert.ok(t2.id, "toolbar has an id");
-  assert.equal(t2.id, identify(t2), "identify returns toolbar id");
-  assert.notEqual(t2.id, t1.id, "each toolbar has unique id");
-
-  yield wait(t2, "attach");
-
-  assert.equal(t2.title, "bar", "title is set after attach");
-  assert.equal(t2.hidden, true, "toolbar is hidden as specified");
-
-  t2.destroy();
-  t1.destroy();
-
-  yield wait(t1, "detach");
-
-  assert.equal(t1.title, void(0), "title is voided after detach");
-  assert.equal(t1.hidden, void(0), "hidden is void fater detach");
-
-
-  const t3 = new Toolbar({ title: "foo" });
-  assert.pass("Can create toolbar after identical was detached");
-
-  assert.equal(t3.id, t1.id, "toolbar has a same id");
-  assert.equal(t3.id, identify(t3), "identify returns toolbar.id");
-  assert.equal(t3.title, void(0), "title is void before attach");
-  assert.equal(t3.hidden, void(0), "hidden is void before attach");
-
-  yield wait(t3, "attach");
-
-  assert.equal(t3.title, "foo", "title is set");
-  assert.equal(t3.hidden, false, "toolbar is hidden");
-
-  t3.destroy();
-
-  yield wait(t3, "detach");
-};
-
-exports["test show / hide toolbar"] = function*(assert) {
-  const t1 = new Toolbar({ title: "foo" });
-
-  yield wait(t1, "attach");
-
-  assert.equal(t1.title, "foo", "title is set after attach");
-  assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
-  assert.ok(isAttached(t1), "toolbar was actually attarched");
-  assert.ok(!isCollapsed(t1), "toolbar isn't collapsed");
-
-  hide(t1);
-  assert.equal(t1.hidden, false, "not hidden yet");
-
-  yield wait(t1, "hide");
-  assert.equal(t1.hidden, true, "toolbar got hidden");
-  assert.ok(isCollapsed(t1), "toolbar is collapsed");
-
-  show(t1);
-
-  yield wait(t1, "show");
-  assert.equal(t1.hidden, false, "toolbar got shown");
-  assert.ok(!isCollapsed(t1), "toolbar isn't collapsed");
-
-  t1.destroy();
-  yield wait(t1, "detach");
-  assert.ok(!isAttached(t1), "toolbar is no longer attached");
-};
-
-exports["test multiple windows & toolbars"] = function*(assert) {
-  const w1 = getMostRecentBrowserWindow();
-  const t1 = new Toolbar({ title: "multi window" });
-
-  yield wait(t1, "attach");
-
-  assert.equal(t1.title, "multi window", "title is set after attach");
-  assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
-  assert.ok(isAttached(t1, w1), "toolbar was actually attarched");
-  assert.ok(!isCollapsed(t1, w1), "toolbar isn't collapsed");
-
-  const w2 = open();
-  yield ready(w2);
-
-  assert.ok(isAttached(t1, w2), "toolbar was attached to second window");
-  assert.ok(!isCollapsed(t1, w2), "toolbar isn't collabsed");
-
-  hide(t1);
-  yield wait(t1, "hide");
-
-  assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2),
-            "toolbar is collabsed");
-
-
-  const w3 = open();
-  yield ready(w3);
-
-  assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3),
-            "toolbar is attached to all windows");
-  assert.ok(isCollapsed(t1, w3) && isCollapsed(t1, w3) && isCollapsed(t1, w3),
-            "toolbar still collapsed in all windows");
-
-
-  const t2 = new Toolbar({ title: "multi hidden", hidden: true });
-
-  yield wait(t2, "attach");
-
-  assert.equal(t2.title, "multi hidden", "title is set after attach");
-  assert.equal(t2.hidden, true, "isn't hidden as specified");
-
-  assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3),
-            "toolbar#1 is still attached");
-  assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3),
-            "toolbar#2 was attached to all windows");
-
-  assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2) && isCollapsed(t1, w3),
-            "toolbar#1 is still collapsed");
-
-  assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w2) && isCollapsed(t2, w3),
-            "toolbar#2 is collapsed");
-
-  t1.destroy();
-  yield wait(t1, "detach");
-
-  assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2) && !isAttached(t1, w3),
-            "toolbar#1 was detached from all windows");
-  assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3),
-            "toolbar#2 is still attached to all windows");
-
-  yield close(w2);
-
-  assert.ok(isAttached(t2, w1) && isAttached(t2, w3),
-            "toolbar#2 is still attached to remaining windows");
-  assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w3),
-            "toolbar#2 is still collapsed");
-
-  show(t2);
-  yield wait(t2, "show");
-
-  assert.ok(!isCollapsed(t2, w1) && !isCollapsed(t2, w3),
-            "toolbar#2 is not collapsed");
-
-  yield close(w3);
-
-  assert.ok(isAttached(t2, w1), "still attached to last window");
-  assert.ok(!isCollapsed(t2, w1), "still isn't collapsed");
-
-  t2.destroy();
-  yield wait(t2, "detach");
-
-  assert.ok(!isAttached(t2, w1), "toolbar was removed");
-
-  yield cleanUI();
-};
-
-exports["test toolbar persistence"] = function*(assert) {
-  const t1 = new Toolbar({ title: "per sist ence" });
-
-  yield wait(t1, "attach");
-
-  assert.equal(t1.hidden, false, "toolbar is visible");
-
-  hide(t1);
-  yield wait(t1, "hide");
-
-  assert.equal(t1.hidden, true, "toolbar is hidden");
-  assert.ok(isCollapsed(t1), "toolbar is collapsed");
-
-  t1.destroy();
-
-  yield wait(t1, "detach");
-
-  const t2 = new Toolbar({ title: "per sist ence" });
-
-  yield wait(t2, "attach");
-
-  assert.equal(t2.hidden, true, "toolbar persisted state");
-  assert.ok(isCollapsed(t2), "toolbar is collapsed");
-
-  show(t2);
-  t2.destroy();
-
-  yield wait(t2, "detach");
-
-  const t3 = new Toolbar({ title: "per sist ence", hidden: true });
-
-  yield wait(t3, "attach");
-
-  assert.equal(t3.hidden, false, "toolbar persisted state & ignored option");
-  assert.ok(!isCollapsed(t3), "toolbar isn1t collapsed");
-
-  t3.destroy();
-
-  yield wait(t3, "detach");
-
-  yield cleanUI();
-};
-
-
-exports["test toolbar unload"] = function*(assert) {
-  // We override add-on id, otherwise two instances of Toolbar host (view.js)
-  // handling same updates, cause message port is bound to add-on id.
-  const loader = Loader(module, null, null, {id: "toolbar-unload-addon"});
-  const { Toolbar } = loader.require("sdk/ui/toolbar");
-
-  const w1 = getMostRecentBrowserWindow();
-  const w2 = open();
-
-  yield ready(w2);
-
-  const t1 = new Toolbar({ title: "unload" });
-
-  yield wait(t1, "attach");
-
-  assert.ok(isAttached(t1, w1) && isAttached(t1, w2),
-            "attached to both windows");
-
-
-  loader.unload();
-
-
-  assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2),
-            "detached from both windows on unload");
-
-  yield cleanUI();
-};
-
-exports["test toolbar close button"] = function*(assert) {
-  const t1 = new Toolbar({ title: "close with button" });
-
-  yield wait(t1, "attach");
-  const w1 = getMostRecentBrowserWindow();
-  const w2 = open();
-
-  yield ready(w2);
-
-  assert.ok(!isCollapsed(t1, w1) && !isCollapsed(t1, w2),
-            "toolbar isn't collapsed");
-
-  closeViaButton(t1);
-
-  yield wait(t1, "hide");
-
-  assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2),
-            "toolbar was collapsed");
-
-  t1.destroy();
-  yield wait(t1, "detach");
-  yield cleanUI();
-};
-
-exports["test title change"] = function*(assert) {
-  const w1 = getMostRecentBrowserWindow();
-  const w2 = open();
-
-  yield ready(w2);
-
-  const t1 = new Toolbar({ title: "first title" });
-  const id = t1.id;
-
-  yield wait(t1, "attach");
-
-
-  assert.equal(t1.title, "first title",
-               "correct title is set");
-  assert.equal(readTitle(t1, w1), "first title",
-               "title set in the view of first window");
-  assert.equal(readTitle(t1, w2), "first title",
-               "title set in the view of second window");
-
-  retitle(t1, "second title");
-
-  // Hide & show so to make sure changes go through a round
-  // loop.
-  hide(t1);
-  yield wait(t1, "hide");
-  show(t1);
-  yield wait(t1, "show");
-
-  assert.equal(t1.id, id, "id remains same");
-  assert.equal(t1.title, "second title", "instance title was updated");
-  assert.equal(readTitle(t1, w1), "second title",
-               "title updated in first window");
-  assert.equal(readTitle(t1, w2), "second title",
-               "title updated in second window");
-
-  t1.destroy();
-  yield wait(t1, "detach");
-  yield cleanUI();
-};
-
-exports["test toolbar is not customizable"] = function*(assert, done) {
-  const { window, document, gCustomizeMode } = getMostRecentBrowserWindow();
-  const outerId = getOuterId(window);
-  const input = new CustomizationInput();
-  const customized = defer();
-  const customizedEnd = defer();
-
-  // open a new tab so that the customize tab replaces it
-  // and does not replace the start tab.
-  yield new Promise(resolve => {
-    tabs.open({
-      url: "about:blank",
-      onReady: resolve
-    });
-  });
-
-  new Reactor({ onStep: value => {
-    if (value[outerId] === true)
-      customized.resolve();
-    if (value[outerId] === null)
-      customizedEnd.resolve();
-  }}).run(input);
-
-  const toolbar = new Toolbar({ title: "foo" });
-  yield wait(toolbar, "attach");
-
-  let view = document.getElementById(toolbar.id);
-  let label = view.querySelector("label");
-  let inner = view.querySelector("toolbar");
-
-  assert.equal(view.getAttribute("customizable"), "false",
-    "The outer toolbar is not customizable.");
-
-  assert.ok(label.collapsed,
-    "The label is not displayed.")
-
-  assert.equal(inner.getAttribute("customizable"), "true",
-    "The inner toolbar is customizable.");
-
-  assert.equal(window.getComputedStyle(inner).visibility, "visible",
-    "The inner toolbar is visible.");
-
-  // Enter in customization mode
-  gCustomizeMode.toggle();
-
-  yield customized.promise;
-
-  assert.equal(view.getAttribute("customizable"), "false",
-    "The outer toolbar is not customizable.");
-
-  assert.equal(label.collapsed, false,
-    "The label is displayed.")
-
-  assert.equal(inner.getAttribute("customizable"), "true",
-    "The inner toolbar is customizable.");
-
-  assert.equal(window.getComputedStyle(inner).visibility, "hidden",
-    "The inner toolbar is hidden.");
-
-  // Exit from customization mode
-  gCustomizeMode.toggle();
-
-  yield customizedEnd.promise;
-
-  assert.equal(view.getAttribute("customizable"), "false",
-    "The outer toolbar is not customizable.");
-
-  assert.ok(label.collapsed,
-    "The label is not displayed.")
-
-  assert.equal(inner.getAttribute("customizable"), "true",
-    "The inner toolbar is customizable.");
-
-  assert.equal(window.getComputedStyle(inner).visibility, "visible",
-    "The inner toolbar is visible.");
-
-  toolbar.destroy();
-
-  yield cleanUI();
-};
-
-exports["test button are attached to toolbar"] = function*(assert) {
-  const { document } = getMostRecentBrowserWindow();
-  const { ActionButton, ToggleButton } = require("sdk/ui");
-  const { identify } = require("sdk/ui/id");
-
-  let action = ActionButton({
-    id: "btn-1",
-    label: "action",
-    icon: "./placeholder.png"
-  });
-
-  let toggle = ToggleButton({
-    id: "btn-2",
-    label: "toggle",
-    icon: "./placeholder.png"
-  });
-
-  const toolbar = new Toolbar({
-    title: "foo",
-    items: [action, toggle]
-  });
-
-  yield wait(toolbar, "attach");
-
-  let actionNode = document.getElementById(identify(action));
-  let toggleNode = document.getElementById(identify(toggle));
-
-  assert.notEqual(actionNode, null,
-    "action button exists in the document");
-
-  assert.notEqual(actionNode, null,
-    "action button exists in the document");
-
-  assert.notEqual(toggleNode, null,
-    "toggle button exists in the document");
-
-  assert.equal(actionNode.nextElementSibling, toggleNode,
-    "action button is placed before toggle button");
-
-  assert.equal(actionNode.parentNode.parentNode.id, toolbar.id,
-    "buttons are placed in the correct toolbar");
-
-  toolbar.destroy();
-
-  yield cleanUI();
-};
-
-exports["test toolbar are not in private windows"] = function*(assert) {
-  const w = open(null, {features: {toolbar: true, private: true}});
-
-  yield ready(w);
-
-  const t = new Toolbar({title: "foo"});
-
-  yield wait(t, "attach");
-
-  assert.ok(!isAttached(t), "toolbar wasn't actually attached");
-
-  t.destroy();
-
-  yield cleanUI();
-}
-
-require("sdk/test").run(module.exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-unit-test-finder.js
+++ /dev/null
@@ -1,57 +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 { makeFilters } = require("sdk/deprecated/unit-test-finder");
-
-const testFiles = [ "test-clipboard", "test-timers" ]
-const testMethods = [ "test set clipboard", "test setTimeout" ]
-
-exports["test makeFilters no options"] = (assert) => {
-  let { fileFilter, testFilter } = makeFilters();
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using no options on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using no options on method name " + m + " works"));
-}
-
-exports["test makeFilters no filter"] = (assert) => {
-  let { fileFilter, testFilter } = makeFilters({});
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using no options on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using no options on method name " + m + " works"));
-}
-
-exports["test makeFilters no method filter"] = (assert) => {
-  let { fileFilter, testFilter } = makeFilters({ filter: "i" });
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i' on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i' on method name " + m + " works"));
-
-  ({ fileFilter, testFilter } = makeFilters({ filter: "i:" }));
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i:' on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i:' on method name " + m + " works"));
-
-  ({ fileFilter, testFilter } = makeFilters({ filter: "z:" }));
-  testFiles.forEach(f => assert.ok(!fileFilter(f), "using filter 'z:' on filename " + f + " dnw"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'z:' on method name " + m + " works"));
-}
-
-exports["test makeFilters no file filter"] = (assert) => {
-  let { fileFilter, testFilter } = makeFilters({ filter: ":i" });
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using filter ':i' on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using filter ':i' on method name " + m + " works"));
-
-  ({ fileFilter, testFilter } = makeFilters({ filter: ":z" }));
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using filter ':z' on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(!testFilter(m), "using filter ':z' on method name " + m + " dnw"));
-}
-
-exports["test makeFilters both filters"] = (assert) => {
-  let { fileFilter, testFilter } = makeFilters({ filter: "i:i" });
-  testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i:i' on filename " + f + " works"));
-  testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i:i' on method name " + m + " works"));
-
-  ({ fileFilter, testFilter } = makeFilters({ filter: "z:z" }));
-  testFiles.forEach(f => assert.ok(!fileFilter(f), "using filter 'z:z' on filename " + f + " dnw"));
-  testMethods.forEach(m => assert.ok(!testFilter(m), "using filter 'z:z' on method name " + m + " dnw"));
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-unit-test.js
+++ /dev/null
@@ -1,270 +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 timer = require("sdk/timers");
-
-var setupCalled = false, teardownCalled = false;
-
-exports.setup = function() {
-    setupCalled = true;
-};
-
-exports.teardown = function() {
-    teardownCalled = true;
-    setupCalled = false;
-};
-
-// Important note - unit tests are run in alphabetical order.  The following
-// unit tests for setup/teardown are order dependent, sometimes the result of
-// one test is checked in the next test (testing for teardown does this).  When
-// tests are cohesively a single unit, they are named <test_name> - partN where
-// N is their order in the sequence.  Secondly, because these tests should be
-// run before all others, they start with an A.
-exports.testASetupTeardownSyncTestPart1 = function(test) {
-    test.assertEqual(true, setupCalled, 'setup function was called before this');
-    test.assertEqual(false, teardownCalled, 'teardown function was not called before this');
-};
-
-exports.testASetupTeardownSyncTestPart2 = function(test) {
-    test.assertEqual(true, setupCalled, 'setup was re-called before this');
-    test.assertEqual(true, teardownCalled, 'teardown was called after first function');
-};
-
-exports.testATeardownAsyncTestPart1 = function(test) {
-    teardownCalled = false;
-    timer.setTimeout(_ => {
-        test.assertEqual(false, teardownCalled, "teardown not called until done");
-        test.done();
-    }, 20);
-    test.waitUntilDone();
-};
-
-exports.testATeardownAsyncTestPart2 = function(test) {
-    test.assertEqual(true, teardownCalled, "teardown called after done");
-};
-
-exports.testWaitUntilInstant = function(test) {
-  test.waitUntilDone();
-
-  test.waitUntil(() => true, "waitUntil with instant true pass")
-      .then(() => test.done());
-}
-
-exports.testWaitUntil = function(test) {
-  test.waitUntilDone();
-  let succeed = false;
-
-  test.waitUntil(_ => succeed, "waitUntil pass")
-      .then(test.done);
-
-  timer.setTimeout(_ => {
-    test.pass("succeed");
-    succeed = true;
-  }, 20);
-}
-
-exports.testWaitUntilEqual = function(test) {
-  test.waitUntilDone();
-  let succeed = false;
-
-  test.waitUntilEqual("foo", _ => succeed ? "foo" : "bar",
-                      "waitUntilEqual pass")
-      .then(test.done);
-
-  timer.setTimeout(_ => {
-    test.pass("succeed");
-    succeed = true;
-  }, 20);
-}
-
-exports.testWaitUntilNotEqual = function(test) {
-  test.waitUntilDone();
-  let succeed = false;
-
-  test.waitUntilNotEqual("foo", _ => succeed ? "bar" : "foo",
-                         "waitUntilNotEqual pass")
-      .then(test.done);
-
-  timer.setTimeout(_ => {
-    test.pass("succeed");
-    succeed = true;
-  }, 20);
-}
-
-exports.testWaitUntilMatches = function(test) {
-  test.waitUntilDone();
-  let succeed = false;
-
-  test.waitUntilMatches(_ => succeed ? "foo" : "bar",
-                        /foo/, "waitUntilEqual pass")
-      .then(test.done);
-
-  timer.setTimeout(_ => {
-    test.pass("succeed");
-    succeed = true;
-  }, 20);
-}
-
-exports.testWaitUntilErrorInCallback = function(test) {
-  test.waitUntilDone();
-  test.expectFail(_ => {
-    test.waitUntil(_ => { throw "oops"; }, "waitUntil pass")
-        .then(test.done);
-  });
-}
-
-exports.testWaitUntilTimeoutInCallback = function(test) {
-  test.waitUntilDone();
-
-  let expected = [];
-  let message = 0;
-  if (require("sdk/test/options").parseable) {
-    expected.push(["print", "TEST-START | wait4ever\n"]);
-    expected.push(["error", "fail:", "Timed out (after: START)"]);
-    expected.push(["error", "test assertion never became true:\n", "assertion failed, value is false\n"]);
-  }
-  else {
-    expected.push(["info",  "executing 'wait4ever'"]);
-    expected.push(["error", "fail:", "Timed out (after: START)"]);
-    expected.push(["error", "test assertion never became true:\n", "assertion failed, value is false\n"]);
-  }
-
-  function checkExpected(name, args) {
-    var index = message;
-    if (message++ >= expected.length) {
-      return;
-    }
-
-    let expectedArgs = expected[index].slice(1);
-    for (let i = 0; i < expectedArgs.length; i++) {
-      test.assertEqual(args[i], expectedArgs[i], "Should have seen the right message in argument " + i + " of message " + message);
-    }
-
-    if (message >= expected.length) {
-      test.done();
-    }
-  }
-
-  let runner = new (require("sdk/deprecated/unit-test").TestRunner)({
-    console: {
-      error: function() {
-        checkExpected("error", Array.slice(arguments));
-      },
-      info: function () {
-        checkExpected("info", Array.slice(arguments));
-      },
-      trace: function () {},
-      exception: function () {},
-      print: function () {
-        checkExpected("print", Array.slice(arguments));
-      }
-    }
-  });
-
-  runner.start({
-    test: {
-      name: "wait4ever",
-      testFunction: function(test) {
-        test.waitUntilDone(100);
-        test.waitUntil(() => false);
-      }
-    },
-    onDone: function() {}
-  });
-};
-
-exports.testExpectFail = function(test) {
-    test.expectFail(function() {
-        test.fail('expectFail masking .fail');
-    });
-
-    test.expectFail(function() {
-        test.assert(false, 'expectFail masking .assert');
-    });
-
-    test.assert(true, 'assert should pass with no expectFail');
-/*
-    test.expectFail(function() {
-        test.expectFail(function() {
-            test.fail('this should blow up');
-        });
-    });
-*/
-};
-
-exports.testAssertFunction = function(test) {
-    test.assertFunction(function() {}, 'assertFunction with function');
-    test.expectFail(function() {
-        test.assertFunction(null, 'assertFunction with non-function');
-    });
-};
-
-exports.testAssertUndefined = function(test) {
-    test.assertUndefined(undefined, 'assertUndefined with undefined');
-    test.expectFail(function() {
-        test.assertUndefined(null, 'assertUndefined with null');
-    });
-    test.expectFail(function() {
-        test.assertUndefined(false, 'assertUndefined with false');
-    });
-    test.expectFail(function() {
-        test.assertUndefined(0, 'assertUndefined with 0');
-    });
-};
-
-exports.testAssertNotUndefined = function(test) {
-    test.expectFail(function() {
-        test.assertNotUndefined(undefined, 'assertNotUndefined with undefined');
-    });
-    test.assertNotUndefined(null, 'assertNotUndefined with null');
-    test.assertNotUndefined(false, 'assertNotUndefined with false');
-    test.assertNotUndefined(0, 'assertNotUndefined with 0');
-};
-
-exports.testAssertNull = function(test) {
-    test.assertNull(null, 'assertNull with null');
-    test.expectFail(function() {
-        test.assertNull(undefined, 'assertNull with undefined');
-    });
-    test.expectFail(function() {
-        test.assertNull(false, 'assertNull with false');
-    });
-    test.expectFail(function() {
-        test.assertNull(0, 'assertNull with 0');
-    });
-};
-
-exports.testAssertNotNull = function(test) {
-    test.assertNotNull(undefined, 'assertNotNull with undefined');
-    test.assertNotNull(false, 'assertNotNull with false');
-    test.assertNotNull(0, 'assertNotNull with 0');
-
-    test.expectFail(function() {
-        test.assertNotNull(null, 'testAssertNotNull with null');
-    });
-};
-
-exports.testAssertObject = function(test) {
-    test.assertObject({}, 'assertObject with {}' );
-    test.assertObject(new Object(), 'assertObject with new Object');
-    test.expectFail(function() {
-        test.assertObject('fail', 'assertObject with string');
-    });
-};
-
-exports.testAssertString = function(test) {
-    test.assertString('', 'assertString with ""');
-    test.assertString(new String(), 'assertString with new String');
-};
-
-exports.testAssertArray = function(test) {
-    test.assertArray([], 'assertArray with []');
-    test.assertArray(new Array(), 'assertArray with new Array');
-};
-
-exports.testNumber = function(test) {
-    test.assertNumber(1, 'assertNumber with 1');
-    test.assertNumber(new Number('2'), 'assertNumber with new Number("2")' );
-};
-
deleted file mode 100644
--- a/addon-sdk/source/test/test-unload.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-var unload = require("sdk/system/unload");
-var { Loader, LoaderWithHookedConsole } = require("sdk/test/loader");
-
-exports.testUnloading = function(assert) {
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  var ul = loader.require("sdk/system/unload");
-  var unloadCalled = 0;
-  function unload() {
-    unloadCalled++;
-    throw new Error("error");
-  }
-  ul.when(unload);
-
-  // This should be ignored, as we already registered it
-  ul.when(unload);
-
-  function unload2() { unloadCalled++; }
-  ul.when(unload2);
-  loader.unload();
-  assert.equal(unloadCalled, 2,
-                   "Unloader functions are called on unload.");
-  assert.equal(messages.length, 1,
-                   "One unload handler threw exception 1/2");
-  assert.equal(messages[0].type, "exception",
-                   "One unload handler threw exception 2/2");
-};
-
-exports.testEnsure = function(assert) {
-  assert.throws(function() { unload.ensure({}); },
-                /object has no 'unload' property/,
-                "passing obj with no unload prop should fail");
-  assert.throws(function() { unload.ensure({}, "destroy"); },
-                /object has no 'destroy' property/,
-                "passing obj with no custom unload prop should fail");
-
-  var called = 0;
-  var obj = {unload: function() { called++; }};
-
-  unload.ensure(obj);
-  obj.unload();
-  assert.equal(called, 1,
-                   "unload() should be called");
-  obj.unload();
-  assert.equal(called, 1,
-                   "unload() should be called only once");
-};
-
-exports.testReason = function (assert) {
-  var reason = "Reason doesn't actually have to be anything in particular.";
-  var loader = Loader(module);
-  var ul = loader.require("sdk/system/unload");
-  ul.when(function (rsn) {
-    assert.equal(rsn, reason,
-                     "when() reason should be reason given to loader");
-  });
-  var obj = {
-    unload: function (rsn) {
-      assert.equal(rsn, reason,
-                       "ensure() reason should be reason given to loader");
-    }
-  };
-  ul.ensure(obj);
-  loader.unload(reason);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-unsupported-skip.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const app = require('sdk/system/xul-app');
-
-/*
- * Include a module that is unsupported for the current system.
- * The `Unsupported Application` error should be caught by the test loader
- * and no errors should occur
- */
-if (!app.is('Firefox')) {
-  require('./fixtures/loader/unsupported/firefox');
-}
-else {
-  require('./fixtures/loader/unsupported/fennec');
-}
-
-exports.testRunning = function (assert) {
-  assert.fail('Tests should not run in unsupported applications');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-uri-resource.js
+++ /dev/null
@@ -1,43 +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 {mount, unmount, resolve} = require("sdk/uri/resource");
-const {tmpdir} = require("node/os");
-const {fromFilename} = require("sdk/url");
-
-const mountURI = fromFilename(tmpdir());
-
-exports.testAPI = assert => {
-  const domain = Math.random().toString(16).substr(2)
-
-  assert.equal(resolve(`resource://${domain}`),
-               null,
-               "domain isn't mounted");
-
-  mount(domain, mountURI);
-
-  assert.equal(resolve(`resource://${domain}`),
-               mountURI,
-               "domain was mounted");
-
-
-  assert.equal(resolve(`resource://${domain}/foo.js`),
-               `${mountURI}foo.js`,
-               "uri resolves to a file in mounted location");
-
-  unmount(domain);
-
-  assert.equal(resolve(`resource://${domain}`),
-               null,
-               "domain is no longer mounted");
-
-
-  assert.equal(resolve(`resource://${domain}/foo.js`),
-               null,
-               "uris under unmounted domain resolve to null");
-
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-url.js
+++ /dev/null
@@ -1,502 +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 {
-  URL,
-  toFilename,
-  fromFilename,
-  isValidURI,
-  getTLD,
-  DataURL,
-  isLocalURL } = require('sdk/url');
-
-const { pathFor } = require('sdk/system');
-const file = require('sdk/io/file');
-const tabs = require('sdk/tabs');
-const { decode } = require('sdk/base64');
-
-const httpd = require('./lib/httpd');
-const port = 8099;
-
-exports.testResolve = function(assert) {
-  assert.equal(URL('bar', 'http://www.foo.com/').toString(),
-                   'http://www.foo.com/bar');
-
-  assert.equal(URL('bar', 'http://www.foo.com'),
-                   'http://www.foo.com/bar');
-
-  assert.equal(URL('http://bar.com/', 'http://foo.com/'),
-                   'http://bar.com/',
-                   'relative should override base');
-
-  assert.throws(function() { URL('blah'); },
-                    /malformed URI: blah/i,
-                    'url.resolve() should throw malformed URI on base');
-
-  assert.throws(function() { URL('chrome://global'); },
-                    /invalid URI: chrome:\/\/global/i,
-                    'url.resolve() should throw invalid URI on base');
-
-  assert.throws(function() { URL('chrome://foo/bar'); },
-                    /invalid URI: chrome:\/\/foo\/bar/i,
-                    'url.resolve() should throw on bad chrome URI');
-
-  assert.equal(URL('', 'http://www.foo.com'),
-                   'http://www.foo.com/',
-                   'url.resolve() should add slash to end of domain');
-};
-
-exports.testParseHttp = function(assert) {
-  var aUrl = 'http://sub.foo.com/bar?locale=en-US&otherArg=%20x%20#myhash';
-  var info = URL(aUrl);
-
-  assert.equal(info.scheme, 'http');
-  assert.equal(info.protocol, 'http:');
-  assert.equal(info.host, 'sub.foo.com');
-  assert.equal(info.hostname, 'sub.foo.com');
-  assert.equal(info.port, null);
-  assert.equal(info.userPass, null);
-  assert.equal(info.path, '/bar?locale=en-US&otherArg=%20x%20#myhash');
-  assert.equal(info.pathname, '/bar');
-  assert.equal(info.href, aUrl);
-  assert.equal(info.hash, '#myhash');
-  assert.equal(info.search, '?locale=en-US&otherArg=%20x%20');
-  assert.equal(info.fileName, 'bar');
-};
-
-exports.testParseHttpSearchAndHash = function (assert) {
-  var info = URL('https://www.moz.com/some/page.html');
-  assert.equal(info.hash, '');
-  assert.equal(info.search, '');
-
-  var hashOnly = URL('https://www.sub.moz.com/page.html#justhash');
-  assert.equal(hashOnly.search, '');
-  assert.equal(hashOnly.hash, '#justhash');
-
-  var queryOnly = URL('https://www.sub.moz.com/page.html?my=query');
-  assert.equal(queryOnly.search, '?my=query');
-  assert.equal(queryOnly.hash, '');
-
-  var qMark = URL('http://www.moz.org?');
-  assert.equal(qMark.search, '');
-  assert.equal(qMark.hash, '');
-
-  var hash = URL('http://www.moz.org#');
-  assert.equal(hash.search, '');
-  assert.equal(hash.hash, '');
-
-  var empty = URL('http://www.moz.org?#');
-  assert.equal(hash.search, '');
-  assert.equal(hash.hash, '');
-
-  var strange = URL('http://moz.org?test1#test2?test3');
-  assert.equal(strange.search, '?test1');
-  assert.equal(strange.hash, '#test2?test3');
-};
-
-exports.testParseHttpWithPort = function(assert) {
-  var info = URL('http://foo.com:5/bar');
-  assert.equal(info.port, 5);
-};
-
-exports.testParseChrome = function(assert) {
-  var info = URL('chrome://global/content/blah');
-  assert.equal(info.scheme, 'chrome');
-  assert.equal(info.host, 'global');
-  assert.equal(info.port, null);
-  assert.equal(info.userPass, null);
-  assert.equal(info.path, '/content/blah');
-  assert.equal(info.fileName, 'blah');
-};
-
-exports.testParseAbout = function(assert) {
-  var info = URL('about:boop');
-  assert.equal(info.scheme, 'about');
-  assert.equal(info.host, null);
-  assert.equal(info.port, null);
-  assert.equal(info.userPass, null);
-  assert.equal(info.path, 'boop');
-};
-
-exports.testParseFTP = function(assert) {
-  var info = URL('ftp://1.2.3.4/foo');
-  assert.equal(info.scheme, 'ftp');
-  assert.equal(info.host, '1.2.3.4');
-  assert.equal(info.port, null);
-  assert.equal(info.userPass, null);
-  assert.equal(info.path, '/foo');
-  assert.equal(info.fileName, 'foo');
-};
-
-exports.testParseFTPWithUserPass = function(assert) {
-  var info = URL('ftp://user:pass@1.2.3.4/foo');
-  assert.equal(info.userPass, 'user:pass');
-};
-
-exports.testToFilename = function(assert) {
-  assert.throws(
-    function() { toFilename('resource://nonexistent'); },
-    /resource does not exist: resource:\/\/nonexistent\//i,
-    'toFilename() on nonexistent resources should throw'
-  );
-
-  assert.throws(
-    function() { toFilename('http://foo.com/'); },
-    /cannot map to filename: http:\/\/foo.com\//i,
-    'toFilename() on http: URIs should raise error'
-  );
-
-  try {
-    assert.ok(
-      /.*console\.xul$/.test(toFilename('chrome://global/content/console.xul')),
-      'toFilename() w/ console.xul works when it maps to filesystem'
-    );
-  }
-  catch (e) {
-    if (/chrome url isn\'t on filesystem/.test(e.message))
-      assert.pass('accessing console.xul in jar raises exception');
-    else
-      assert.fail('accessing console.xul raises ' + e);
-  }
-
-  // TODO: Are there any chrome URLs that we're certain exist on the
-  // filesystem?
-  // assert.ok(/.*main\.js$/.test(toFilename('chrome://myapp/content/main.js')));
-};
-
-exports.testFromFilename = function(assert) {
-  var profileDirName = require('sdk/system').pathFor('ProfD');
-  var fileUrl = fromFilename(profileDirName);
-  assert.equal(URL(fileUrl).scheme, 'file',
-                   'toFilename() should return a file: url');
-  assert.equal(fromFilename(toFilename(fileUrl)), fileUrl);
-};
-
-exports.testURL = function(assert) {
-  assert.ok(URL('h:foo') instanceof URL, 'instance is of correct type');
-  assert.throws(() => URL(),
-                    /malformed URI: undefined/i,
-                    'url.URL should throw on undefined');
-  assert.throws(() => URL(''),
-                    /malformed URI: /i,
-                    'url.URL should throw on empty string');
-  assert.throws(() => URL('foo'),
-                    /malformed URI: foo/i,
-                    'url.URL should throw on invalid URI');
-  assert.ok(URL('h:foo').scheme, 'has scheme');
-  assert.equal(URL('h:foo').toString(),
-                   'h:foo',
-                   'toString should roundtrip');
-  // test relative + base
-  assert.equal(URL('mypath', 'http://foo').toString(),
-                   'http://foo/mypath',
-                   'relative URL resolved to base');
-  // test relative + no base
-  assert.throws(() => URL('path').toString(),
-                    /malformed URI: path/i,
-                    'no base for relative URI should throw');
-
-  let a = URL('h:foo');
-  let b = URL(a);
-  assert.equal(b.toString(),
-                   'h:foo',
-                   'a URL can be initialized from another URL');
-  assert.notStrictEqual(a, b,
-                            'a URL initialized from another URL is not the same object');
-  assert.ok(a == 'h:foo',
-              'toString is implicit when a URL is compared to a string via ==');
-  assert.strictEqual(a + '', 'h:foo',
-                         'toString is implicit when a URL is concatenated to a string');
-};
-
-exports.testStringInterface = function(assert) {
-  var EM = 'about:addons';
-  var a = URL(EM);
-
-  // make sure the standard URL properties are enumerable and not the String interface bits
-  assert.equal(Object.keys(a),
-    'fileName,scheme,userPass,host,hostname,port,path,pathname,hash,href,origin,protocol,search',
-    'enumerable key list check for URL.');
-  assert.equal(
-      JSON.stringify(a),
-      JSON.stringify(EM),
-      'JSON.stringify on url should return the url as a flat string');
-      // JSON.parse(JSON.stringify(url)) wont work like an url object
-      // (missing methods). this makes it easier to re-create an url
-      // instance from the whole string, and every place that
-      // accepts an url also works with a flat string.
-
-  // make sure that the String interface exists and works as expected
-  assert.equal(a.indexOf(':'), EM.indexOf(':'), 'indexOf on URL works');
-  assert.equal(a.valueOf(), EM.valueOf(), 'valueOf on URL works.');
-  assert.equal(a.toSource(), EM.toSource(), 'toSource on URL works.');
-  assert.equal(a.lastIndexOf('a'), EM.lastIndexOf('a'), 'lastIndexOf on URL works.');
-  assert.equal(a.match('t:').toString(), EM.match('t:').toString(), 'match on URL works.');
-  assert.equal(a.toUpperCase(), EM.toUpperCase(), 'toUpperCase on URL works.');
-  assert.equal(a.toLowerCase(), EM.toLowerCase(), 'toLowerCase on URL works.');
-  assert.equal(a.split(':').toString(), EM.split(':').toString(), 'split on URL works.');
-  assert.equal(a.charAt(2), EM.charAt(2), 'charAt on URL works.');
-  assert.equal(a.charCodeAt(2), EM.charCodeAt(2), 'charCodeAt on URL works.');
-  assert.equal(a.concat(EM), EM.concat(a), 'concat on URL works.');
-  assert.equal(a.substr(2,3), EM.substr(2,3), 'substr on URL works.');
-  assert.equal(a.substring(2,3), EM.substring(2,3), 'substring on URL works.');
-  assert.equal(a.trim(), EM.trim(), 'trim on URL works.');
-  assert.equal(a.trimRight(), EM.trimRight(), 'trimRight on URL works.');
-  assert.equal(a.trimLeft(), EM.trimLeft(), 'trimLeft on URL works.');
-}
-
-exports.testDataURLwithouthURI = function (assert) {
-  let dataURL = new DataURL();
-
-  assert.equal(dataURL.base64, false, 'base64 is false for empty uri')
-  assert.equal(dataURL.data, '', 'data is an empty string for empty uri')
-  assert.equal(dataURL.mimeType, '', 'mimeType is an empty string for empty uri')
-  assert.equal(Object.keys(dataURL.parameters).length, 0, 'parameters is an empty object for empty uri');
-
-  assert.equal(dataURL.toString(), 'data:,');
-}
-
-exports.testDataURLwithMalformedURI = function (assert) {
-  assert.throws(function() {
-      let dataURL = new DataURL('http://www.mozilla.com/');
-    },
-    /Malformed Data URL: http:\/\/www.mozilla.com\//i,
-    'DataURL raises an exception for malformed data uri'
-  );
-}
-
-exports.testDataURLparse = function (assert) {
-  let dataURL = new DataURL('data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E');
-
-  assert.equal(dataURL.base64, false, 'base64 is false for non base64 data uri')
-  assert.equal(dataURL.data, '<h1>Hello!</h1>', 'data is properly decoded')
-  assert.equal(dataURL.mimeType, 'text/html', 'mimeType is set properly')
-  assert.equal(Object.keys(dataURL.parameters).length, 1, 'one parameters specified');
-  assert.equal(dataURL.parameters['charset'], 'US-ASCII', 'charset parsed');
-
-  assert.equal(dataURL.toString(), 'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E');
-}
-
-exports.testDataURLparseBase64 = function (assert) {
-  let text = 'Awesome!';
-  let b64text = 'QXdlc29tZSE=';
-  let dataURL = new DataURL('data:text/plain;base64,' + b64text);
-
-  assert.equal(dataURL.base64, true, 'base64 is true for base64 encoded data uri')
-  assert.equal(dataURL.data, text, 'data is properly decoded')
-  assert.equal(dataURL.mimeType, 'text/plain', 'mimeType is set properly')
-  assert.equal(Object.keys(dataURL.parameters).length, 1, 'one parameters specified');
-  assert.equal(dataURL.parameters['base64'], '', 'parameter set without value');
-  assert.equal(dataURL.toString(), 'data:text/plain;base64,' + encodeURIComponent(b64text));
-}
-
-exports.testIsValidURI = function (assert) {
-  validURIs().forEach(function (aUri) {
-    assert.equal(isValidURI(aUri), true, aUri + ' is a valid URL');
-  });
-};
-
-exports.testIsInvalidURI = function (assert) {
-  invalidURIs().forEach(function (aUri) {
-    assert.equal(isValidURI(aUri), false, aUri + ' is an invalid URL');
-  });
-};
-
-exports.testURLFromURL = function(assert) {
-  let aURL = URL('http://mozilla.org');
-  let bURL = URL(aURL);
-  assert.equal(aURL.toString(), bURL.toString(), 'Making a URL from a URL works');
-};
-
-exports.testTLD = function(assert) {
-  let urls = [
-    { url: 'http://my.sub.domains.mozilla.co.uk', tld: 'co.uk' },
-    { url: 'http://my.mozilla.com', tld: 'com' },
-    { url: 'http://my.domains.mozilla.org.hk', tld: 'org.hk' },
-    { url: 'chrome://global/content/blah', tld: 'global' },
-    { url: 'data:text/plain;base64,QXdlc29tZSE=', tld: null },
-    { url: 'https://1.2.3.4', tld: null }
-  ];
-
-  urls.forEach(function (uri) {
-    assert.equal(getTLD(uri.url), uri.tld);
-    assert.equal(getTLD(URL(uri.url)), uri.tld);
-  });
-}
-
-exports.testWindowLocationMatch = function (assert, done) {
-  let server = httpd.startServerAsync(port);
-  server.registerPathHandler('/index.html', function (request, response) {
-    response.write('<html><head></head><body><h1>url tests</h1></body></html>');
-  });
-
-  let aUrl = 'http://localhost:' + port + '/index.html?q=aQuery#somehash';
-  let urlObject = URL(aUrl);
-
-  tabs.open({
-    url: aUrl,
-    onReady: function (tab) {
-      tab.attach({
-        onMessage: function (loc) {
-          for (let prop in loc) {
-            assert.equal(urlObject[prop], loc[prop], prop + ' matches');
-          }
-
-          tab.close(() => server.stop(done));
-        },
-        contentScript: '(' + function () {
-          let res = {};
-          // `origin` is `null` in this context???
-          let props = 'hostname,port,pathname,hash,href,protocol,search'.split(',');
-          props.forEach(function (prop) {
-            res[prop] = window.location[prop];
-          });
-          self.postMessage(res);
-        } + ')()'
-      });
-    }
-  })
-};
-
-exports.testURLInRegExpTest = function(assert) {
-  let url = 'https://mozilla.org';
-  assert.equal((new RegExp(url).test(URL(url))), true, 'URL instances work in a RegExp test');
-}
-
-exports.testLocalURL = function(assert) {
-  [
-    'data:text/html;charset=utf-8,foo and bar',
-    'data:text/plain,foo and bar',
-    'resource://gre/modules/commonjs/',
-    'chrome://browser/content/browser.xul'
-  ].forEach(aUri => {
-    assert.ok(isLocalURL(aUri), aUri + ' is a Local URL');
-  })
-
-}
-
-exports.testLocalURLwithRemoteURL = function(assert) {
-  validURIs().filter(url => !url.startsWith('data:')).forEach(aUri => {
-    assert.ok(!isLocalURL(aUri), aUri + ' is an invalid Local URL');
-  });
-}
-
-exports.testLocalURLwithInvalidURL = function(assert) {
-  invalidURIs().concat([
-    'data:foo and bar',
-    'resource:// must fail',
-    'chrome:// here too'
-  ]).forEach(aUri => {
-    assert.ok(!isLocalURL(aUri), aUri + ' is an invalid Local URL');
-  });
-}
-
-exports.testFileName = function(assert) {
-  let urls = [
-    ['https://foo/bar.js', 'bar.js'],
-    ['chrome://gaia/content/myfxosapp/file.js', 'file.js'],
-    ['http://localhost:8888/file.js', 'file.js'],
-    ['http://foo/bar.js#hash', 'bar.js'],
-    ['http://foo/bar.js?q=go&query=yeah', 'bar.js'],
-    ['chrome://browser/content/content.js', 'content.js'],
-    ['resource://gre/foo.js', 'foo.js'],
-  ];
-
-  urls.forEach(([url, fileName]) => assert.equal(URL(url).fileName, fileName, 'file names are equal'));
-};
-
-function validURIs() {
-  return [
-  'http://foo.com/blah_blah',
-  'http://foo.com/blah_blah/',
-  'http://foo.com/blah_blah_(wikipedia)',
-  'http://foo.com/blah_blah_(wikipedia)_(again)',
-  'http://www.example.com/wpstyle/?p=364',
-  'https://www.example.com/foo/?bar=baz&amp;inga=42&amp;quux',
-  'http://✪df.ws/123',
-  'http://userid:password@example.com:8080',
-  'http://userid:password@example.com:8080/',
-  'http://userid@example.com',
-  'http://userid@example.com/',
-  'http://userid@example.com:8080',
-  'http://userid@example.com:8080/',
-  'http://userid:password@example.com',
-  'http://userid:password@example.com/',
-  'http://142.42.1.1/',
-  'http://142.42.1.1:8080/',
-  'http://➡.ws/䨹',
-  'http://⌘.ws',
-  'http://⌘.ws/',
-  'http://foo.com/blah_(wikipedia)#cite-1',
-  'http://foo.com/blah_(wikipedia)_blah#cite-1',
-  'http://foo.com/unicode_(✪)_in_parens',
-  'http://foo.com/(something)?after=parens',
-  'http://☺.damowmow.com/',
-  'http://code.google.com/events/#&amp;product=browser',
-  'http://j.mp',
-  'ftp://foo.bar/baz',
-  'http://foo.bar/?q=Test%20URL-encoded%20stuff',
-  'http://مثال.إختبار',
-  'http://例子.测试',
-  'http://उदाहरण.परीक्षा',
-  'http://-.~_!$&amp;\'()*+,;=:%40:80%2f::::::@example.com',
-  'http://1337.net',
-  'http://a.b-c.de',
-  'http://223.255.255.254',
-  // Also want to validate data-uris, localhost
-  'http://localhost:8432/some-file.js',
-  'data:text/plain;base64,',
-  'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E',
-  'data:text/html;charset=utf-8,'
-  ];
-}
-
-// Some invalidURIs are valid according to the regex used,
-// can be improved in the future, but better to pass some
-// invalid URLs than prevent valid URLs
-
-function invalidURIs () {
-  return [
-//  'http://',
-//  'http://.',
-//  'http://..',
-//  'http://../',
-//  'http://?',
-//  'http://??',
-//  'http://??/',
-//  'http://#',
-//  'http://##',
-//  'http://##/',
-//  'http://foo.bar?q=Spaces should be encoded',
-  'not a url',
-  '//',
-  '//a',
-  '///a',
-  '///',
-//  'http:///a',
-  'foo.com',
-  'http:// shouldfail.com',
-  ':// should fail',
-//  'http://foo.bar/foo(bar)baz quux',
-//  'http://-error-.invalid/',
-//  'http://a.b--c.de/',
-//  'http://-a.b.co',
-//  'http://a.b-.co',
-//  'http://0.0.0.0',
-//  'http://10.1.1.0',
-//  'http://10.1.1.255',
-//  'http://224.1.1.1',
-//  'http://1.1.1.1.1',
-//  'http://123.123.123',
-//  'http://3628126748',
-//  'http://.www.foo.bar/',
-//  'http://www.foo.bar./',
-//  'http://.www.foo.bar./',
-//  'http://10.1.1.1',
-//  'http://10.1.1.254'
-  ];
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-uuid.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { uuid } = require('sdk/util/uuid');
-
-exports['test generate uuid'] = function(assert) {
-  let signature = /{[0-9a-f\-]+}/
-  let first = String(uuid());
-  let second = String(uuid());
-
-  assert.ok(signature.test(first), 'first guid has a correct signature');
-  assert.ok(signature.test(second), 'second guid has a correct signature');
-  assert.notEqual(first, second, 'guid generates new guid on each call');
-};
-
-exports['test parse uuid'] = function(assert) {
-  let firefoxUUID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
-  let actual = uuid(firefoxUUID);
-
-  assert.equal(actual.number, firefoxUUID, 'uuid parsed given string');
-  assert.equal(String(actual), firefoxUUID, 'serializes to the same value');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-weak-set.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Cu } = require("chrome");
-const memory = require("sdk/test/memory");
-const { add, remove, has, clear, iterator } = require("sdk/lang/weak-set");
-const { setInterval, clearInterval } = require("sdk/timers");
-
-function gc(assert) {
-  let wait = 1;
-  let interval = setInterval(function() {
-    assert.pass("waited " + (wait++ * 0.250) + "secs for gc()..");
-  }, 250);
-
-  return memory.gc().then(() => {
-    assert.pass("gc completed!");
-    clearInterval(interval);
-  });
-}
-
-exports['test add/remove/iterate/clear item'] = function*(assert) {
-  let addItems = {};
-  let removeItems = {};
-  let iterateItems = {};
-  let clearItems = {};
-  let nonReferencedItems = {};
-
-  let item = {};
-  let addedItems = [{}, {}];
-
-  assert.pass("adding things to items");
-  add(addItems, item);
-  add(removeItems, item);
-  add(iterateItems, addedItems[0]);
-  add(iterateItems, addedItems[1]);
-  add(iterateItems, addedItems[0]); // weak set shouldn't add this twice
-  add(clearItems, addedItems[0]);
-  add(clearItems, addedItems[1]);
-  add(nonReferencedItems, {});
-
-  assert.pass("removing things from removeItems");
-  remove(removeItems, item);
-
-  assert.pass("clear things from clearItems");
-  clear(clearItems);
-
-  assert.pass("starting gc..");
-  yield gc(assert);
-  let count = 0;
-
-  assert.equal(has(addItems, item), true, 'the addItems is in the weak set');
-  assert.equal(has(removeItems, item), false, 'the removeItems is not in weak set');
-
-  assert.pass("iterating iterateItems..");
-  for (let item of iterator(iterateItems)) {
-    assert.equal(item, addedItems[count], "item in the expected order");
-    count++;
-  }
-
-  assert.equal(count, 2, 'items in the expected number');
-
-  assert.pass("iterating clearItems..");
-  for (let item of iterator(clearItems)) {
-    assert.fail("the loop should not be executed");
-    count++
-  }
-
-  for (let item of iterator(nonReferencedItems)) {
-    assert.fail("the loop should not be executed");
-    count++
-  }
-
-  assert.equal(count, 2, 'items in the expected number');
-};
-
-exports['test adding non object or null item'] = function(assert) {
-  let items = {};
-
-  assert.throws(() => {
-    add(items, 'foo');
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(items, 0);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(items, undefined);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(items, null);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(items, true);
-  },
-  TypeError,
-  'only non-null object are allowed');
-};
-
-exports['test adding to non object or null item'] = function(assert) {
-  let item = {};
-
-  assert.throws(() => {
-    add('foo', item);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(0, item);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(undefined, item);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(null, item);
-  },
-  TypeError,
-  'only non-null object are allowed');
-
-  assert.throws(() => {
-    add(true, item);
-  },
-  TypeError,
-  'only non-null object are allowed');
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-window-events.js
+++ /dev/null
@@ -1,63 +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";
-
-// Opening new windows in Fennec causes issues
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { Loader } = require("sdk/test/loader");
-const { open, getMostRecentBrowserWindow, getOuterId } = require("sdk/window/utils");
-
-exports["test browser events"] = function(assert, done) {
-  let loader = Loader(module);
-  let { events } = loader.require("sdk/window/events");
-  let { on, off } = loader.require("sdk/event/core");
-  let actual = [];
-
-  on(events, "data", function handler(e) {
-    actual.push(e);
-
-    if (e.type === "open") {
-      assert.pass("window open has occured");
-    }
-    else if (e.type === "DOMContentLoaded") {
-      assert.pass("window DOMContentLoaded has occured");
-    }
-    else if (e.type === "load") {
-      assert.pass("window load has occured");
-      window.close();
-    }
-    else if (e.type === "close") {
-      // confirm the ordering of events
-      let [ open, ready, load, close ] = actual;
-      assert.equal(open.type, "open")
-      assert.equal(open.target, window, "window is open")
-
-      assert.equal(ready.type, "DOMContentLoaded")
-      assert.equal(ready.target, window, "window ready")
-
-      assert.equal(load.type, "load")
-      assert.equal(load.target, window, "window load")
-
-      assert.equal(close.type, "close")
-      assert.equal(close.target, window, "window load")
-
-      // Note: If window is closed right after this GC won't have time
-      // to claim loader and there for this listener. It's better to remove
-      // remove listener here to avoid race conditions.
-      off(events, "data", handler);
-      loader.unload();
-      done();
-    }
-  });
-
-  // Open window and close it to trigger observers.
-  let window = open();
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-window-observer.js
+++ /dev/null
@@ -1,61 +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 { Loader } = require("sdk/test/loader");
-const { open, close } = require("sdk/window/helpers");
-const { browserWindows: windows } = require("sdk/windows");
-const { isBrowser } = require('sdk/window/utils');
-const app = require("sdk/system/xul-app");
-
-exports["test unload window observer"] = function(assert, done) {
-  // Hacky way to be able to create unloadable modules via makeSandboxedLoader.
-  let loader = Loader(module);
-  let observer = loader.require("sdk/windows/observer").observer;
-  let opened = 0;
-  let closed = 0;
-  let windowsOpen = windows.length;
-
-  observer.on("open", onOpen);
-  observer.on("close", onClose);
-
-  // On Fennec, only test that the module does not throw an error
-  if (app.is("Fennec")) {
-    assert.pass("Windows observer did not throw on Fennec");
-    return cleanUp();
-  }
-
-  // Open window and close it to trigger observers.
-  open().
-    then(close).
-    then(loader.unload).
-    then(open).
-    then(close).
-    then(function() {
-      // Enqueuing asserts to make sure that assertion is not performed early.
-      assert.equal(1, opened, "observer open was called before unload only");
-      assert.equal(windowsOpen + 1, closed, "observer close was called before unload only");
-    }).
-    then(cleanUp, assert.fail);
-
-  function cleanUp () {
-    observer.removeListener("open", onOpen);
-    observer.removeListener("close", onClose);
-    done();
-  }
-
-  function onOpen(window) {
-    // Ignoring non-browser windows
-    if (isBrowser(window))
-      opened++;
-  }
-  function onClose(window) {
-    // Ignore non-browser windows & already opened `activeWindow` (unload will
-    // emit close on it even though it is not actually closed).
-    if (isBrowser(window))
-      closed++;
-  }
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-window-utils-private-browsing.js
+++ /dev/null
@@ -1,210 +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';
-
-// Fennec support tracked in bug #809412
-module.metadata = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const windowUtils = require('sdk/deprecated/window-utils');
-const { Cc, Ci } = require('chrome');
-const { isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { getFrames, getWindowTitle, onFocus, isWindowPrivate } = require('sdk/window/utils');
-const { open, close, focus } = require('sdk/window/helpers');
-const WM = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
-const { isPrivate } = require('sdk/private-browsing');
-const { fromIterator: toArray } = require('sdk/util/array');
-const { defer } = require('sdk/core/promise');
-const { setTimeout } = require('sdk/timers');
-
-function tick() {
-  let deferred = defer();
-  setTimeout(deferred.resolve);
-  return deferred.promise;
-}
-
-function makeEmptyBrowserWindow(options) {
-  options = options || {};
-  return open('chrome://browser/content/browser.xul', {
-    features: {
-      chrome: true,
-      private: !!options.private
-    }
-  });
-}
-
-exports.testWindowTrackerIgnoresPrivateWindows = function(assert, done) {
-  var myNonPrivateWindow, myPrivateWindow;
-  var finished = false;
-  var privateWindow;
-  var privateWindowClosed = false;
-
-  let wt = windowUtils.WindowTracker({
-    onTrack: function(window) {
-      assert.ok(!isWindowPrivate(window), 'private window was not tracked!');
-    },
-    onUntrack: function(window) {
-      assert.ok(!isWindowPrivate(window), 'private window was not tracked!');
-      // PWPB case
-      if (window === myPrivateWindow && isWindowPBSupported) {
-        privateWindowClosed = true;
-      }
-      if (window === myNonPrivateWindow) {
-        assert.ok(!privateWindowClosed);
-        wt.unload();
-        done();
-      }
-    }
-  });
-
-  // make a new private window
-  makeEmptyBrowserWindow({
-    private: true
-  }).then(function(window) {
-    myPrivateWindow = window;
-
-    assert.equal(isWindowPrivate(window), isWindowPBSupported);
-    assert.ok(getFrames(window).length > 1, 'there are frames for private window');
-    assert.equal(getWindowTitle(window), window.document.title,
-                 'getWindowTitle works');
-
-    return close(window).then(function() {
-      return makeEmptyBrowserWindow().then(function(window) {
-        myNonPrivateWindow = window;
-        assert.pass('opened new window');
-        return close(window);
-      });
-    });
-  }).catch(assert.fail);
-};
-
-// Test setting activeWIndow and onFocus for private windows
-exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
-  let browserWindow = WM.getMostRecentWindow("navigator:browser");
-
-  assert.equal(windowUtils.activeBrowserWindow, browserWindow,
-               "Browser window is the active browser window.");
-  assert.ok(!isPrivate(browserWindow), "Browser window is not private.");
-
-  // make a new private window
-  makeEmptyBrowserWindow({ private: true }).then(focus).then(window => {
-    // PWPB case
-    if (isWindowPBSupported) {
-      assert.ok(isPrivate(window), "window is private");
-      assert.notStrictEqual(windowUtils.activeBrowserWindow, browserWindow);
-    }
-    // Global case
-    else {
-      assert.ok(!isPrivate(window), "window is not private");
-    }
-
-    assert.strictEqual(windowUtils.activeBrowserWindow, window,
-                 "Correct active browser window pb supported");
-    assert.notStrictEqual(browserWindow, window,
-                 "The window is not the old browser window");
-
-
-    return onFocus(windowUtils.activeWindow = browserWindow).then(_ => {
-      assert.strictEqual(windowUtils.activeWindow, browserWindow,
-                         "Correct active window [1]");
-      assert.strictEqual(windowUtils.activeBrowserWindow, browserWindow,
-                         "Correct active browser window [1]");
-
-      // test focus(window)
-      return focus(window).then(w => {
-        assert.strictEqual(w, window, 'require("sdk/window/helpers").focus on window works');
-      }).then(tick);
-    }).then(_ => {
-      assert.strictEqual(windowUtils.activeBrowserWindow, window,
-                         "Correct active browser window [2]");
-      assert.strictEqual(windowUtils.activeWindow, window,
-                         "Correct active window [2]");
-
-      // test setting a private window
-      return onFocus(windowUtils.activeWindow = window);
-    }).then(function() {
-      assert.strictEqual(windowUtils.activeBrowserWindow, window,
-                         "Correct active browser window [3]");
-      assert.strictEqual(windowUtils.activeWindow, window,
-                         "Correct active window [3]");
-
-      // just to get back to original state
-      return onFocus(windowUtils.activeWindow = browserWindow);
-    }).then(_ => {
-      assert.strictEqual(windowUtils.activeBrowserWindow, browserWindow,
-                         "Correct active browser window when pb mode is supported [4]");
-      assert.strictEqual(windowUtils.activeWindow, browserWindow,
-                         "Correct active window when pb mode is supported [4]");
-
-      return close(window);
-    })
-  }).then(done).catch(assert.fail);
-};
-
-exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
-  // make a new private window
-  makeEmptyBrowserWindow({
-    private: true
-  }).then(function(window) {
-    // PWPB case
-    if (isWindowPBSupported) {
-      assert.equal(isPrivate(windowUtils.activeWindow), true,
-                   "active window is private");
-      assert.equal(isPrivate(windowUtils.activeBrowserWindow), true,
-                   "active browser window is private");
-      assert.ok(isWindowPrivate(window), "window is private");
-      assert.ok(isPrivate(window), "window is private");
-
-      // pb mode is supported
-      assert.ok(
-        isWindowPrivate(windowUtils.activeWindow),
-        "active window is private when pb mode is supported");
-      assert.ok(
-        isWindowPrivate(windowUtils.activeBrowserWindow),
-        "active browser window is private when pb mode is supported");
-      assert.ok(isPrivate(windowUtils.activeWindow),
-                "active window is private when pb mode is supported");
-      assert.ok(isPrivate(windowUtils.activeBrowserWindow),
-        "active browser window is private when pb mode is supported");
-    }
-    // Global case
-    else {
-      assert.equal(isPrivate(windowUtils.activeWindow), false,
-                   "active window is not private");
-      assert.equal(isPrivate(windowUtils.activeBrowserWindow), false,
-                   "active browser window is not private");
-      assert.equal(isWindowPrivate(window), false, "window is not private");
-      assert.equal(isPrivate(window), false, "window is not private");
-    }
-
-    return close(window);
-  }).then(done).catch(assert.fail);
-}
-
-exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
-  // make a new private window
-  makeEmptyBrowserWindow({
-    private: true
-  }).then(function(window) {
-    // PWPB case
-    if (isWindowPBSupported) {
-      assert.ok(isWindowPrivate(window), "window is private");
-      assert.equal(toArray(windowUtils.windowIterator()).indexOf(window), -1,
-                   "window is not in windowIterator()");
-    }
-    // Global case
-    else {
-      assert.equal(isWindowPrivate(window), false, "window is not private");
-      assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) > -1,
-                "window is in windowIterator()");
-    }
-
-    return close(window);
-  }).then(done).catch(assert.fail);
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-window-utils.js
+++ /dev/null
@@ -1,265 +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 = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const windowUtils = require("sdk/deprecated/window-utils");
-const timer = require("sdk/timers");
-const { Cc, Ci } = require("chrome");
-const { Loader } = require("sdk/test/loader");
-const { open, getFrames, getWindowTitle, onFocus, windows } = require('sdk/window/utils');
-const { close } = require('sdk/window/helpers');
-const { fromIterator: toArray } = require('sdk/util/array');
-
-const WM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
-
-function makeEmptyWindow(options) {
-  options = options || {};
-  var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-  var blankXul = ('<?xml version="1.0"?>' +
-                  '<?xml-stylesheet href="chrome://global/skin/" ' +
-                  '                 type="text/css"?>' +
-                  '<window xmlns="' + xulNs + '" windowtype="test:window">' +
-                  '</window>');
-
-  return open("data:application/vnd.mozilla.xul+xml;charset=utf-8," + escape(blankXul), {
-    features: {
-      chrome: true,
-      width: 10,
-      height: 10
-    }
-  });
-}
-
-exports.testWindowTracker = function(assert, done) {
-  var myWindow = makeEmptyWindow();
-  assert.pass('window was created');
-
-  myWindow.addEventListener("load", function() {
-    assert.pass("test window has opened");
-
-    // test bug 638007 (new is optional), using new
-    var wt = new windowUtils.WindowTracker({
-      onTrack: window => {
-        if (window === myWindow) {
-          assert.pass("onTrack() called with our test window");
-          close(window);
-        }
-      },
-      onUntrack: window => {
-        if (window === myWindow) {
-          assert.pass("onUntrack() called with our test window");
-          wt.unload();
-          timer.setTimeout(done);
-        }
-      }
-    });
-  }, {once: true});
-};
-
-exports['test window watcher untracker'] = function(assert, done) {
-  var myWindow;
-  var tracks = 0;
-  var unloadCalled = false;
-
-  var delegate = {
-    onTrack: function(window) {
-      tracks = tracks + 1;
-      if (window == myWindow) {
-        assert.pass("onTrack() called with our test window");
-        timer.setTimeout(function() {
-          myWindow.close();
-        }, 1);
-      }
-    },
-    onUntrack: function(window) {
-      tracks = tracks - 1;
-      if (window == myWindow && !unloadCalled) {
-        unloadCalled = true;
-        timer.setTimeout(function() {
-          wt.unload();
-        }, 1);
-      }
-      if (0 > tracks) {
-        assert.fail("WindowTracker onUntrack was called more times than onTrack..");
-      }
-      else if (0 == tracks) {
-        timer.setTimeout(function() {
-            myWindow = null;
-            done();
-        }, 1);
-      }
-    }
-  };
-
-  // test bug 638007 (new is optional), not using new
-  var wt = windowUtils.WindowTracker(delegate);
-  myWindow = makeEmptyWindow();
-};
-
-// test that _unregWindow calls _unregLoadingWindow
-exports['test window watcher unregs 4 loading wins'] = function(assert, done) {
-  var myWindow;
-  var finished = false;
-  let browserWindow =  WM.getMostRecentWindow("navigator:browser");
-  var counter = 0;
-
-  var delegate = {
-    onTrack: function(window) {
-      var type = window.document.documentElement.getAttribute("windowtype");
-      if (type == "test:window")
-        assert.fail("onTrack shouldn't have been executed.");
-    }
-  };
-  var wt = new windowUtils.WindowTracker(delegate);
-
-  // make a new window
-  myWindow = makeEmptyWindow();
-
-  // make sure that the window hasn't loaded yet
-  assert.notEqual(
-      myWindow.document.readyState,
-      "complete",
-      "window hasn't loaded yet.");
-
-  // unload WindowTracker
-  wt.unload();
-
-  // make sure that the window still hasn't loaded, which means that the onTrack
-  // would have been removed successfully assuming that it doesn't execute.
-  assert.notEqual(
-      myWindow.document.readyState,
-      "complete",
-      "window still hasn't loaded yet.");
-
-  // wait for the window to load and then close it. onTrack wouldn't be called
-  // until the window loads, so we must let it load before closing it to be
-  // certain that onTrack was removed.
-  myWindow.addEventListener("load", function() {
-    // allow all of the load handles to execute before closing
-    myWindow.setTimeout(function() {
-      myWindow.addEventListener("unload", function() {
-        // once the window unloads test is done
-        done();
-      });
-      myWindow.close();
-    }, 0);
-  });
-}
-
-exports['test window watcher without untracker'] = function(assert, done) {
-  let myWindow;
-  let wt = new windowUtils.WindowTracker({
-    onTrack: function(window) {
-      if (window == myWindow) {
-        assert.pass("onTrack() called with our test window");
-
-        close(myWindow).then(function() {
-          wt.unload();
-          done();
-        }, assert.fail);
-      }
-    }
-  });
-
-  myWindow = makeEmptyWindow();
-};
-
-exports['test active window'] = function(assert, done) {
-  let browserWindow = WM.getMostRecentWindow("navigator:browser");
-  let continueAfterFocus = window => onFocus(window).then(nextTest);
-
-  assert.equal(windowUtils.activeBrowserWindow, browserWindow,
-               "Browser window is the active browser window.");
-
-
-  let testSteps = [
-    function() {
-      continueAfterFocus(windowUtils.activeWindow = browserWindow);
-    },
-    function() {
-      assert.equal(windowUtils.activeWindow, browserWindow,
-                       "Correct active window [1]");
-      nextTest();
-    },
-    function() {
-      assert.equal(windowUtils.activeBrowserWindow, browserWindow,
-                       "Correct active browser window [2]");
-      continueAfterFocus(windowUtils.activeWindow = browserWindow);
-    },
-    function() {
-      assert.equal(windowUtils.activeWindow, browserWindow,
-                       "Correct active window [3]");
-      nextTest();
-    },
-    function() {
-      assert.equal(windowUtils.activeBrowserWindow, browserWindow,
-                       "Correct active browser window [4]");
-      done();
-    }
-  ];
-
-  function nextTest() {
-    if (testSteps.length)
-      testSteps.shift()();
-  }
-  nextTest();
-};
-
-exports.testWindowIterator = function(assert, done) {
-  // make a new window
-  let window = makeEmptyWindow();
-
-  // make sure that the window hasn't loaded yet
-  assert.notEqual(
-      window.document.readyState,
-      "complete",
-      "window hasn't loaded yet.");
-
-  // this window should only appear in windowIterator() while its loading
-  assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) === -1,
-            "window isn't in windowIterator()");
-
-  // Then it should be in windowIterator()
-  window.addEventListener("load", function onload() {
-    window.addEventListener("load", onload);
-    assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) !== -1,
-              "window is now in windowIterator()");
-
-    // Wait for the window unload before ending test
-    close(window).then(done);
-  });
-};
-
-exports.testIgnoreClosingWindow = function(assert, done) {
-  assert.equal(windows().length, 1, "Only one window open");
-
-  // make a new window
-  let window = makeEmptyWindow();
-
-  assert.equal(windows().length, 2, "Two windows open");
-
-  window.addEventListener("load", function onload() {
-    window.addEventListener("load", onload);
-
-    assert.equal(windows().length, 2, "Two windows open");
-
-    // Wait for the window unload before ending test
-    let checked = false;
-
-    close(window).then(function() {
-      assert.ok(checked, 'the test is finished');
-    }).then(done, assert.fail)
-
-    assert.equal(windows().length, 1, "Only one window open");
-    checked = true;
-  });
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-window-utils2.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-// Opening new windows in Fennec causes issues
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { Ci } = require('chrome');
-const { open, windows, isBrowser,
-        getXULWindow, getBaseWindow, getToplevelWindow, getMostRecentWindow,
-        getMostRecentBrowserWindow } = require('sdk/window/utils');
-const { close } = require('sdk/window/helpers');
-const windowUtils = require('sdk/deprecated/window-utils');
-
-exports['test get nsIBaseWindow from nsIDomWindow'] = function(assert) {
-  let active = windowUtils.activeBrowserWindow;
-
-  assert.ok(!(active instanceof Ci.nsIBaseWindow),
-            'active window is not nsIBaseWindow');
-
-  assert.ok(getBaseWindow(active) instanceof Ci.nsIBaseWindow,
-            'base returns nsIBaseWindow');
-};
-
-exports['test get nsIXULWindow from nsIDomWindow'] = function(assert) {
-  let active = windowUtils.activeBrowserWindow;
-  assert.ok(!(active instanceof Ci.nsIXULWindow),
-            'active window is not nsIXULWindow');
-  assert.ok(getXULWindow(active) instanceof Ci.nsIXULWindow,
-            'base returns nsIXULWindow');
-};
-
-exports['test getToplevelWindow'] = function(assert) {
-  let active = windowUtils.activeBrowserWindow;
-  assert.equal(getToplevelWindow(active), active,
-               'getToplevelWindow of toplevel window returns the same window');
-  assert.equal(getToplevelWindow(active.content), active,
-               'getToplevelWindow of tab window returns the browser window');
-  assert.ok(getToplevelWindow(active) instanceof Ci.nsIDOMWindow,
-            'getToplevelWindow returns nsIDOMWindow');
-};
-
-exports['test top window creation'] = function(assert, done) {
-  let window = open('data:text/html;charset=utf-8,Hello top window');
-  assert.ok(~windows().indexOf(window), 'window was opened');
-
-  // Wait for the window unload before ending test
-  close(window).then(done);
-};
-
-exports['test new top window with options'] = function(assert, done) {
-  let window = open('data:text/html;charset=utf-8,Hi custom top window', {
-    name: 'test',
-    features: { height: 100, width: 200, toolbar: true }
-  });
-  assert.ok(~windows().indexOf(window), 'window was opened');
-  assert.equal(window.name, 'test', 'name was set');
-  assert.equal(window.innerHeight, 100, 'height is set');
-  assert.equal(window.innerWidth, 200, 'height is set');
-  assert.equal(window.toolbar.visible, true, 'toolbar was set');
-
-  // Wait for the window unload before ending test
-  close(window).then(done);
-};
-
-exports['test new top window with various URIs'] = function(assert, done) {
-  let msg = 'only chrome, resource and data uris are allowed';
-  assert.throws(function () {
-    open('foo');
-  }, msg);
-  assert.throws(function () {
-    open('http://foo');
-  }, msg);
-  assert.throws(function () {
-    open('https://foo');
-  }, msg);
-  assert.throws(function () {
-    open('ftp://foo');
-  }, msg);
-  assert.throws(function () {
-    open('//foo');
-  }, msg);
-
-  let chromeWindow = open('chrome://foo/content/');
-  assert.ok(~windows().indexOf(chromeWindow), 'chrome URI works');
-
-  let resourceWindow = open('resource://foo');
-  assert.ok(~windows().indexOf(resourceWindow), 'resource URI works');
-
-  // Wait for the window unload before ending test
-  close(chromeWindow).then(close.bind(null, resourceWindow)).then(done);
-};
-
-exports.testIsBrowser = function(assert) {
-  // dummy window, bad type
-  assert.equal(isBrowser({ document: { documentElement: { getAttribute: function() {
-    return 'navigator:browserx';
-  }}}}), false, 'dummy object with correct stucture and bad type does not pass');
-
-  assert.ok(isBrowser(getMostRecentBrowserWindow()), 'active browser window is a browser window');
-  assert.ok(!isBrowser({}), 'non window is not a browser window');
-  assert.ok(!isBrowser({ document: {} }), 'non window is not a browser window');
-  assert.ok(!isBrowser({ document: { documentElement: {} } }), 'non window is not a browser window');
-  assert.ok(!isBrowser(), 'no argument is not a browser window');
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-windows-common.js
+++ /dev/null
@@ -1,104 +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 { Loader } = require('sdk/test/loader');
-const { browserWindows } = require('sdk/windows');
-const { isFocused } = require('sdk/window/utils');
-const { viewFor } = require('sdk/view/core');
-const { modelFor } = require('sdk/model/core');
-const { Ci } = require("chrome");
-const { isBrowser, getWindowTitle } = require("sdk/window/utils");
-const { after, cleanUI } = require("sdk/test/utils");
-
-// TEST: browserWindows Iterator
-exports.testBrowserWindowsIterator = function(assert) {
-  let activeWindowCount = 0;
-  let windows = [];
-  let i = 0;
-  for (let window of browserWindows) {
-    if (window === browserWindows.activeWindow)
-      activeWindowCount++;
-
-    assert.equal(windows.indexOf(window), -1, 'window not already in iterator');
-    assert.equal(browserWindows[i++], window, 'browserWindows[x] works');
-    windows.push(window);
-  }
-  assert.equal(activeWindowCount, 1, 'activeWindow was found in the iterator');
-
-  i = 0;
-  for (let j in browserWindows) {
-    assert.equal(j, i++, 'for (x in browserWindows) works');
-  }
-};
-
-exports.testActiveWindowIsFocused = function(assert) {
-  assert.ok(isFocused(browserWindows.activeWindow), 'the active window is focused');
-}
-
-exports.testWindowTabsObject_alt = function(assert, done) {
-  let window = browserWindows.activeWindow;
-  window.tabs.open({
-    url: 'data:text/html;charset=utf-8,<title>tab 2</title>',
-    inBackground: true,
-    onReady: function onReady(tab) {
-      assert.equal(tab.title, 'tab 2', 'Correct new tab title');
-      assert.notEqual(window.tabs.activeTab, tab, 'Correct active tab');
-
-      // end test
-      tab.close(done);
-    }
-  });
-};
-
-// TEST: browserWindows.activeWindow
-exports.testWindowActivateMethod_simple = function(assert) {
-  let window = browserWindows.activeWindow;
-  let tab = window.tabs.activeTab;
-
-  window.activate();
-
-  assert.equal(browserWindows.activeWindow, window,
-               'Active window is active after window.activate() call');
-  assert.equal(window.tabs.activeTab, tab,
-               'Active tab is active after window.activate() call');
-};
-
-
-exports["test getView(window)"] = function*(assert) {
-  let window = yield new Promise(resolve => {
-    browserWindows.once("open", resolve);
-    browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
-  });
-
-  const view = viewFor(window);
-
-  assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
-  assert.ok(isBrowser(view), "view is a browser window");
-  assert.equal(getWindowTitle(view), window.title,
-               "window has a right title");
-};
-
-
-exports["test modelFor(window)"] = function(assert, done) {
-  browserWindows.once("open", window => {
-    const view = viewFor(window);
-
-    assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
-    assert.ok(isBrowser(view), "view is a browser window");
-    assert.ok(modelFor(view) === window, "modelFor(browserWindow) is SDK window");
-
-    window.close(done);
-  });
-
-
-  browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
-};
-
-after(exports, function*(name, assert) {
-  assert.pass("cleaning the ui.");
-  yield cleanUI();
-});
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-windows.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const app = require("sdk/system/xul-app");
-const packaging = require("@loader/options");
-
-if (app.is("Firefox")) {
-  module.exports = require("./windows/test-firefox-windows");
-}
-else if (app.is("Fennec")) {
-  module.exports = require("./windows/test-fennec-windows");
-}
-else {
-  module.exports = {
-    "test Unsupported Application": (assert) => {
-      assert.pass(
-        "The windows module currently supports only Firefox and Fennec." +
-        "In the future we would like it to support other applications, however.");
-    }
-  };
-  require("sdk/test").run(exports);
-}
deleted file mode 100644
--- a/addon-sdk/source/test/test-xhr.js
+++ /dev/null
@@ -1,88 +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 { XMLHttpRequest } = require('sdk/net/xhr');
-const { LoaderWithHookedConsole } = require('sdk/test/loader');
-const { set: setPref } = require("sdk/preferences/service");
-const data = require("./fixtures");
-
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-exports.testAPIExtension = function(assert) {
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  let { XMLHttpRequest } = loader.require("sdk/net/xhr");
-  setPref(DEPRECATE_PREF, true);
-
-  let xhr = new XMLHttpRequest();
-  assert.equal(typeof(xhr.forceAllowThirdPartyCookie), "function",
-               "forceAllowThirdPartyCookie is defined");
-  assert.equal(xhr.forceAllowThirdPartyCookie(), undefined,
-               "function can be called");
-
-  assert.ok(messages[0].msg.indexOf("`xhr.forceAllowThirdPartyCookie()` is deprecated") >= 0,
-            "deprecation warning was dumped");
-  assert.ok(xhr.mozBackgroundRequest, "is background request");
-
-  loader.unload();
-};
-
-exports.testAbortedXhr = function(assert, done) {
-  let req = new XMLHttpRequest();
-  req.open('GET', data.url('testLocalXhr.json'));
-  req.addEventListener("abort", function() {
-    assert.pass("request was aborted");
-    done();
-  });
-  req.send(null);
-  req.abort();
-};
-
-exports.testLocalXhr = function(assert, done) {
-  let req = new XMLHttpRequest();
-  let ready = false;
-
-  req.overrideMimeType('text/plain');
-  req.open('GET', data.url('testLocalXhr.json'));
-  req.onreadystatechange = function() {
-    if (req.readyState == 4 && (req.status == 0 || req.status == 200)) {
-      ready = true;
-      assert.equal(req.responseText, '{}\n', 'XMLHttpRequest should get local files');
-    }
-  };
-  req.addEventListener('load', function() {
-    assert.pass('addEventListener for load event worked');
-    assert.ok(ready, 'onreadystatechange listener worked');
-    done();
-  }, {once: true});
-  req.send(null);
-};
-
-
-exports.testResponseHeaders = function(assert, done) {
-  let req = new XMLHttpRequest();
-
-  req.overrideMimeType('text/plain');
-  req.open('GET', module.uri);
-  req.onreadystatechange = function() {
-    if (req.readyState == 4 && (req.status == 0 || req.status == 200)) {
-      var headers = req.getAllResponseHeaders();
-      headers = headers.split("\r\n");
-      if (headers.length == 1) {
-        headers = headers[0].split("\n");
-      }
-      for (let i in headers) {
-        if (headers[i] && headers[i].search('Content-Type') >= 0) {
-          assert.equal(headers[i], 'Content-Type: text/plain',
-                       'XHR\'s headers are valid');
-        }
-      }
-
-      done();
-    }
-  };
-  req.send(null);
-}
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-xpcom.js
+++ /dev/null
@@ -1,231 +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 xpcom = require("sdk/platform/xpcom");
-const { Cc, Ci, Cm, Cr } = require("chrome");
-const { isCIDRegistered } = Cm.QueryInterface(Ci.nsIComponentRegistrar);
-const { Class } = require("sdk/core/heritage");
-const { Loader } = require("sdk/test/loader");
-const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-
-exports['test Unknown implements nsISupports'] = function(assert) {
-  let actual = xpcom.Unknown();
-  assert.equal(actual.QueryInterface(Ci.nsISupports),
-               actual,
-               'component implements nsISupports');
-};
-
-exports['test implement xpcom interfaces'] = function(assert) {
-  let WeakReference = Class({
-    extends: xpcom.Unknown,
-    interfaces: [ 'nsIWeakReference' ],
-    QueryReferent: function() {}
-  });
-  let weakReference = WeakReference()
-
-  assert.equal(weakReference.QueryInterface(Ci.nsISupports),
-               weakReference,
-               'component implements nsISupports');
-  assert.equal(weakReference.QueryInterface(Ci.nsIWeakReference),
-               weakReference,
-               'component implements specified interface');
-
-  assert.throws(function() {
-    component.QueryInterface(Ci.nsIObserver);
-  }, "component does not implements interface");
-
-  let Observer = Class({
-    extends: WeakReference,
-    interfaces: [ 'nsIObserver', 'nsIRequestObserver' ],
-    observe: function() {},
-    onStartRequest: function() {},
-    onStopRequest: function() {}
-  });
-  let observer = Observer()
-
-  assert.equal(observer.QueryInterface(Ci.nsISupports),
-               observer,
-               'derived component implements nsISupports');
-  assert.equal(observer.QueryInterface(Ci.nsIWeakReference),
-               observer,
-               'derived component implements supers interface');
-  assert.equal(observer.QueryInterface(Ci.nsIObserver),
-               observer.QueryInterface(Ci.nsIRequestObserver),
-               'derived component implements specified interfaces');
-};
-
-exports['test implement factory without contract'] = function(assert) {
-  let actual = xpcom.Factory({
-    get wrappedJSObject() {
-      return this;
-    },
-  });
-
-  assert.ok(isCIDRegistered(actual.id), 'factory is regiseterd');
-  xpcom.unregister(actual);
-  assert.ok(!isCIDRegistered(actual.id), 'factory is unregistered');
-};
-
-exports['test implement xpcom factory'] = function(assert) {
-  let Component = Class({
-    extends: xpcom.Unknown,
-    interfaces: [ 'nsIObserver' ],
-    get wrappedJSObject() {
-      return this;
-    },
-    observe: function() {}
-  });
-
-  let factory = xpcom.Factory({
-    register: false,
-    contract: '@jetpack/test/factory;1',
-    Component: Component
-  });
-
-  assert.ok(!isCIDRegistered(factory.id), 'factory is not registered');
-  xpcom.register(factory);
-  assert.ok(isCIDRegistered(factory.id), 'factory is registered');
-
-  let actual = Cc[factory.contract].createInstance(Ci.nsIObserver);
-
-  assert.ok(actual.wrappedJSObject instanceof Component,
-            "createInstance returnes wrapped factory instances");
-
-  assert.notEqual(Cc[factory.contract].createInstance(Ci.nsIObserver),
-                  Cc[factory.contract].createInstance(Ci.nsIObserver),
-                  "createInstance returns new instance each time");
-};
-
-exports['test implement xpcom service'] = function(assert) {
-  let actual = xpcom.Service({
-    contract: '@jetpack/test/service;1',
-    register: false,
-    Component: Class({
-      extends: xpcom.Unknown,
-      interfaces: [ 'nsIObserver'],
-      get wrappedJSObject() {
-        return this;
-      },
-      observe: function() {},
-      name: 'my-service'
-    })
-  });
-
-  assert.ok(!isCIDRegistered(actual.id), 'component is not registered');
-  xpcom.register(actual);
-  assert.ok(isCIDRegistered(actual.id), 'service is regiseterd');
-  assert.ok(Cc[actual.contract].getService(Ci.nsIObserver).observe,
-            'service can be accessed via get service');
-  assert.equal(Cc[actual.contract].getService(Ci.nsIObserver).wrappedJSObject,
-               actual.component,
-               'wrappedJSObject is an actual component');
-  xpcom.unregister(actual);
-  assert.ok(!isCIDRegistered(actual.id), 'service is unregistered');
-};
-
-
-function testRegister(assert, text) {
-
-  const service = xpcom.Service({
-    description: 'test about:boop page',
-    contract: '@mozilla.org/network/protocol/about;1?what=boop',
-    register: false,
-    Component: Class({
-      extends: xpcom.Unknown,
-      get wrappedJSObject() {
-        return this;
-      },
-      interfaces: [ 'nsIAboutModule' ],
-      newChannel : function(aURI, aLoadInfo) {
-        var ios = Cc["@mozilla.org/network/io-service;1"].
-                  getService(Ci.nsIIOService);
-
-        var uri = ios.newURI("data:text/plain;charset=utf-8," + text);
-        var channel = ios.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
-
-        channel.originalURI = aURI;
-        return channel;
-      },
-      getURIFlags: function(aURI) {
-        return Ci.nsIAboutModule.ALLOW_SCRIPT;
-      }
-    })
-  });
-
-  xpcom.register(service);
-
-  assert.equal(isCIDRegistered(service.id), true);
-
-  var aboutFactory = xpcom.factoryByContract(service.contract);
-  var about = aboutFactory.createInstance(Ci.nsIAboutModule);
-
-  var ios = Cc["@mozilla.org/network/io-service;1"].
-            getService(Ci.nsIIOService);
-  assert.equal(
-    about.getURIFlags(ios.newURI("http://foo.com")),
-    Ci.nsIAboutModule.ALLOW_SCRIPT
-  );
-
-  var channel = NetUtil.newChannel({
-    uri: "about:boop",
-    loadUsingSystemPrincipal: true
-  });
-  var iStream = channel.open2();
-  var siStream = Cc['@mozilla.org/scriptableinputstream;1']
-                 .createInstance(Ci.nsIScriptableInputStream);
-  siStream.init(iStream);
-  var data = new String();
-  data += siStream.read(-1);
-  siStream.close();
-  iStream.close();
-  assert.equal(data, text);
-
-  xpcom.unregister(service);
-  assert.equal(isCIDRegistered(service.id), false);
-}
-
-exports["test register"] = function(assert) {
-  testRegister(assert, "hai2u");
-};
-
-exports["test re-register"] = function(assert) {
-  testRegister(assert, "hai2u again");
-};
-
-exports["test unload"] = function(assert) {
-  let loader = Loader(module);
-  let sbxpcom = loader.require("sdk/platform/xpcom");
-
-  let auto = sbxpcom.Factory({
-    contract: "@mozilla.org/test/auto-unload;1",
-    description: "test auto",
-    name: "auto"
-  });
-
-  let manual = sbxpcom.Factory({
-    contract: "@mozilla.org/test/manual-unload;1",
-    description: "test manual",
-    register: false,
-    unregister: false,
-    name: "manual"
-  });
-
-  assert.equal(isCIDRegistered(auto.id), true, 'component registered');
-  assert.equal(isCIDRegistered(manual.id), false, 'component not registered');
-
-  sbxpcom.register(manual)
-  assert.equal(isCIDRegistered(manual.id), true,
-                   'component was automatically registered on first instance');
-  loader.unload();
-
-  assert.equal(isCIDRegistered(auto.id), false,
-                   'component was atumatically unregistered on unload');
-  assert.equal(isCIDRegistered(manual.id), true,
-                   'component was not automatically unregistered on unload');
-  sbxpcom.unregister(manual);
-  assert.equal(isCIDRegistered(manual.id), false,
-                   'component was manually unregistered on unload');
-};
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/test-xul-app.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-var xulApp = require("sdk/system/xul-app");
-
-exports["test xulapp"] = function (assert) {
-  assert.equal(typeof(xulApp.ID), "string",
-                   "ID is a string");
-  assert.equal(typeof(xulApp.name), "string",
-                   "name is a string");
-  assert.equal(typeof(xulApp.version), "string",
-                   "version is a string");
-  assert.equal(typeof(xulApp.platformVersion), "string",
-                   "platformVersion is a string");
-
-  assert.throws(() => xulApp.is("blargy"),
-      /Unkown Mozilla Application: blargy/,
-      "is() throws error on bad app name");
-
-  assert.throws(() => xulApp.isOneOf(["blargy"]),
-      /Unkown Mozilla Application: blargy/,
-      "isOneOf() throws error on bad app name");
-
-  function testSupport(name) {
-    var item = xulApp.is(name);
-    assert.ok(item === true || item === false,
-                  "is('" + name + "') is true or false.");
-  }
-
-  var apps = ["Firefox", "Mozilla", "SeaMonkey", "Fennec", "Thunderbird"];
-
-  apps.forEach(testSupport);
-
-  assert.ok(xulApp.isOneOf(apps) == true || xulApp.isOneOf(apps) == false,
-                "isOneOf() returns true or false.");
-
-  assert.equal(xulApp.versionInRange(xulApp.platformVersion, "1.9", "*"),
-                   true, "platformVersion in range [1.9, *)");
-  assert.equal(xulApp.versionInRange("3.6.4", "3.6.4", "3.6.*"),
-                   true, "3.6.4 in [3.6.4, 3.6.*)");
-  assert.equal(xulApp.versionInRange("1.9.3", "1.9.2", "1.9.3"),
-                   false, "1.9.3 not in [1.9.2, 1.9.3)");
-};
-
-exports["test satisfies version range"] = function (assert) {
-  [ ["1.0.0 - 2.0.0", "1.2.3"],
-    ["1.0.0", "1.0.0"],
-    [">=*", "0.2.4"],
-    ["", "1.0.0"],
-    ["*", "1.2.3"],
-    [">=1.0.0", "1.0.0"],
-    [">=1.0.0", "1.0.1"],
-    [">=1.0.0", "1.1.0"],
-    [">1.0.0", "1.0.1"],
-    [">1.0.0", "1.1.0"],
-    ["<=2.0.0", "2.0.0"],
-    ["<=2.0.0", "1.9999.9999"],
-    ["<=2.0.0", "0.2.9"],
-    ["<2.0.0", "1.9999.9999"],
-    ["<2.0.0", "0.2.9"],
-    [">= 1.0.0", "1.0.0"],
-    [">=  1.0.0", "1.0.1"],
-    [">=   1.0.0", "1.1.0"],
-    ["> 1.0.0", "1.0.1"],
-    [">  1.0.0", "1.1.0"],
-    ["<1", "1.0.0beta"],
-    ["< 1", "1.0.0beta"],
-    ["<=   2.0.0", "2.0.0"],
-    ["<= 2.0.0", "1.9999.9999"],
-    ["<=  2.0.0", "0.2.9"],
-    ["<    2.0.0", "1.9999.9999"],
-    ["<\t2.0.0", "0.2.9"],
-    [">=0.1.97", "0.1.97"],
-    ["0.1.20 || 1.2.4", "1.2.4"],
-    [">=0.2.3 || <0.0.1", "0.0.0"],
-    [">=0.2.3 || <0.0.1", "0.2.3"],
-    [">=0.2.3 || <0.0.1", "0.2.4"],
-    ["||", "1.3.4"],
-    ["2.x.x", "2.1.3"],
-    ["1.2.x", "1.2.3"],
-    ["1.2.x || 2.x", "2.1.3"],
-    ["1.2.x || 2.x", "1.2.3"],
-    ["x", "1.2.3"],
-    ["2.*.*", "2.1.3"],
-    ["1.2.*", "1.2.3"],
-    ["1.2.* || 2.*", "2.1.3"],
-    ["1.2.* || 2.*", "1.2.3"],
-    ["*", "1.2.3"],
-    ["2.*", "2.1.2"],
-    [">=1", "1.0.0"],
-    [">= 1", "1.0.0"],
-    ["<1.2", "1.1.1"],
-    ["< 1.2", "1.1.1"],
-    ["=0.7.x", "0.7.2"],
-    [">=0.7.x", "0.7.2"],
-    ["<=0.7.x", "0.6.2"],
-    ["<=0.7.x", "0.7.2"]
-  ].forEach(function (v) {
-    assert.ok(xulApp.satisfiesVersion(v[1], v[0]), v[0] + " satisfied by " + v[1]);
-  });
-}
-exports["test not satisfies version range"] = function (assert) {
-  [ ["1.0.0 - 2.0.0", "2.2.3"],
-    ["1.0.0", "1.0.1"],
-    [">=1.0.0", "0.0.0"],
-    [">=1.0.0", "0.0.1"],
-    [">=1.0.0", "0.1.0"],
-    [">1.0.0", "0.0.1"],
-    [">1.0.0", "0.1.0"],
-    ["<=2.0.0", "3.0.0"],
-    ["<=2.0.0", "2.9999.9999"],
-    ["<=2.0.0", "2.2.9"],
-    ["<2.0.0", "2.9999.9999"],
-    ["<2.0.0", "2.2.9"],
-    [">=0.1.97", "v0.1.93"],
-    [">=0.1.97", "0.1.93"],
-    ["0.1.20 || 1.2.4", "1.2.3"],
-    [">=0.2.3 || <0.0.1", "0.0.3"],
-    [">=0.2.3 || <0.0.1", "0.2.2"],
-    ["2.x.x", "1.1.3"],
-    ["2.x.x", "3.1.3"],
-    ["1.2.x", "1.3.3"],
-    ["1.2.x || 2.x", "3.1.3"],
-    ["1.2.x || 2.x", "1.1.3"],
-    ["2.*.*", "1.1.3"],
-    ["2.*.*", "3.1.3"],
-    ["1.2.*", "1.3.3"],
-    ["1.2.* || 2.*", "3.1.3"],
-    ["1.2.* || 2.*", "1.1.3"],
-    ["2", "1.1.2"],
-    ["2.3", "2.3.1"],
-    ["2.3", "2.4.1"],
-    ["<1", "1.0.0"],
-    [">=1.2", "1.1.1"],
-    ["1", "2.0.0beta"],
-    ["=0.7.x", "0.8.2"],
-    [">=0.7.x", "0.6.2"],
-  ].forEach(function (v) {
-    assert.ok(!xulApp.satisfiesVersion(v[1], v[0]), v[0] + " not satisfied by " + v[1]);
-  });
-}
-
-require("sdk/test").run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/traits/assert.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var BaseAssert = require("sdk/test/assert").Assert;
-
-const getOwnIdentifiers = x => [...Object.getOwnPropertyNames(x),
-                                ...Object.getOwnPropertySymbols(x)];
-
-/**
- * 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);
-}
-
-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;
-}
-
-/**
- * Whether or not given `target` array contains all the element
- * from a given `source` array.
- */
-function containsSet(source, target) {
-  return source.some(function(element) {
-    return 0 > target.indexOf(element);
-  });
-}
-
-/**
- * Whether or not given two arrays contain all elements from another.
- */
-function equivalentSets(source, target) {
-  return containsSet(source, target) && containsSet(target, source);
-}
-
-/**
- * Finds name of the property from `source` property descriptor map, that
- * is not equivalent of the name named property in the `target` property
- * descriptor map. If not found `null` is returned instead.
- */
-function findNonEquivalentPropertyName(source, target) {
-  var value = null;
-  getOwnIdentifiers(source).some(function(key) {
-    var areEquivalent = false;
-    if (!equivalentDescriptors(source[key], target[key])) {
-      value = key;
-      areEquivalent = true;
-    }
-    return areEquivalent;
-  });
-  return value;
-}
-
-var AssertDescriptor = {
-  equalTraits: {
-    value: function equivalentTraits(actual, expected, message) {
-      var difference;
-      var actualKeys = getOwnIdentifiers(actual);
-      var expectedKeys = getOwnIdentifiers(expected);
-
-      if (equivalentSets(actualKeys, expectedKeys)) {
-        this.fail({
-          operator: "equalTraits",
-          message: "Traits define different properties",
-          actual: actualKeys.sort().join(","),
-          expected: expectedKeys.sort().join(","),
-        });
-      }
-      else if ((difference = findNonEquivalentPropertyName(actual, expected))) {
-        this.fail({
-          operator: "equalTraits",
-          message: "Traits define non-equivalent property `" + difference + "`",
-          actual: actual[difference],
-          expected: expected[difference]
-        });
-      }
-      else {
-        this.pass(message || "Traits are equivalent.");
-      }
-    }
-  }
-};
-
-exports.Assert = function Assert() {
-  return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor);
-};
deleted file mode 100644
--- a/addon-sdk/source/test/traits/utils.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var ERR_CONFLICT = "Remaining conflicting property: ";
-var ERR_REQUIRED = "Missing required property: ";
-
-exports.Data = function Data(value, enumerable, configurable, writable) {
-  return ({
-    value: value,
-    enumerable: enumerable !== false,
-    configurable: configurable !== false,
-    writable: writable !== false
-  });
-};
-
-exports.Method = function Method(method, enumerable, configurable, writable) {
-  return ({
-    value: method,
-    enumerable: enumerable !== false,
-    configurable: configurable !== false,
-    writable: writable !== false
-  });
-};
-
-exports.Accessor = function Accessor(get, set, enumerable, configurable) {
-  return ({
-    get: get,
-    set: set,
-    enumerable: enumerable !== false,
-    configurable: configurable !== false
-  });
-};
-
-exports.Required = function Required(name) {
-  function required() { throw new Error(ERR_REQUIRED + name) }
-
-  return ({
-    get: required,
-    set: required,
-    required: true
-  });
-};
-
-exports.Conflict = function Conflict(name) {
-  function conflict() { throw new Error(ERR_CONFLICT + name) }
-
-  return ({
-    get: conflict,
-    set: conflict,
-    conflict: true
-  });
-};
-
deleted file mode 100644
--- a/addon-sdk/source/test/util.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const {Cc, Ci} = require("chrome");
-const {getMostRecentBrowserWindow, open} = require("sdk/window/utils");
-const tabUtils = require("sdk/tabs/utils");
-const {when} = require("sdk/dom/events");
-
-
-var observerService = Cc["@mozilla.org/observer-service;1"]
-                      .getService(Ci.nsIObserverService);
-
-const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
-const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
-const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
-
-const getActiveTab = (window=getMostRecentBrowserWindow()) =>
-  tabUtils.getActiveTab(window)
-
-const openWindow = () => {
-  const window = open();
-  return new Promise((resolve) => {
-    addObserver({
-      observe(subject, topic) {
-        if (subject === window) {
-          removeObserver(this, topic);
-          resolve(subject);
-        }
-      }
-    }, "browser-delayed-startup-finished", false);
-  });
-};
-exports.openWindow = openWindow;
-
-const closeWindow = (window) => {
-  const closed = when(window, "unload", true).then(_ => window);
-  window.close();
-  return closed;
-};
-exports.closeWindow = closeWindow;
-
-const openTab = (url, window=getMostRecentBrowserWindow()) => {
-  const tab = tabUtils.openTab(window, url);
-  const browser = tabUtils.getBrowserForTab(tab);
-
-  return when(browser, "load", true).then(_ => tab);
-};
-exports.openTab = openTab;
-
-const closeTab = (tab) => {
-  const result = when(tab, "TabClose").then(_ => tab);
-  tabUtils.closeTab(tab);
-
-  return result;
-};
-exports.closeTab = closeTab;
-
-const withTab = (test, uri="about:blank") => function*(assert) {
-  const tab = yield openTab(uri);
-  try {
-    yield* test(assert, tab);
-  }
-  finally {
-    yield closeTab(tab);
-  }
-};
-exports.withTab = withTab;
-
-const withWindow = () => function*(assert) {
-  const window = yield openWindow();
-  try {
-    yield* test(assert, window);
-  }
-  finally {
-    yield closeWindow(window);
-  }
-};
-exports.withWindow = withWindow;
-
-const receiveMessage = (manager, name) => new Promise((resolve) => {
-  manager.addMessageListener(name, {
-    receiveMessage(message) {
-      manager.removeMessageListener(name, this);
-      resolve(message);
-    }
-  });
-});
-exports.receiveMessage = receiveMessage;
deleted file mode 100644
--- a/addon-sdk/source/test/windows/test-fennec-windows.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { setTimeout } = require('sdk/timers');
-const { Loader } = require('sdk/test/loader');
-const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
-           getService(Ci.nsIWindowMediator);
-const { browserWindows } = require('sdk/windows');
-
-const ERR_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
-
-// TEST: browserWindows.length for Fennec
-exports.testBrowserWindowsLength = function(assert) {
-  assert.equal(browserWindows.length, 1, "Only one window open");
-};
-
-// TEST: open & close window
-exports.testOpenWindow = function(assert) {
-  let tabCount = browserWindows.activeWindow.tabs.length;
-  let url = "data:text/html;charset=utf-8,<title>windows%20API%20test</title>";
-
-  try {
-    browserWindows.open({url: url});
-    assert.fail('Error was not thrown');
-  }
-  catch(e) {
-    assert.equal(e.message, ERR_MSG, 'Error is thrown on windows.open');
-    assert.equal(browserWindows.length, 1, "Only one window open");
-  }
-};
-
-exports.testCloseWindow = function(assert) {
-  let window = browserWindows.activeWindow;
-
-  try {
-    window.close();
-    assert.fail('Error was not thrown');
-  }
-  catch(e) {
-    assert.equal(e.message, ERR_MSG, 'Error is thrown on windows.close');
-    assert.equal(browserWindows.length, 1, "Only one window open");
-  }
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/windows/test-firefox-windows.js
+++ /dev/null
@@ -1,621 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-const { Cc, Ci } = require('chrome');
-const { setTimeout } = require('sdk/timers');
-const { Loader } = require('sdk/test/loader');
-const { onFocus, getMostRecentWindow, windows, isBrowser, getWindowTitle, isFocused } = require('sdk/window/utils');
-const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
-const { browserWindows } = require("sdk/windows");
-const tabs = require("sdk/tabs");
-const winUtils = require("sdk/deprecated/window-utils");
-const { isPrivate } = require('sdk/private-browsing');
-const { isWindowPBSupported } = require('sdk/private-browsing/utils');
-const { viewFor } = require("sdk/view/core");
-const { defer } = require("sdk/lang/functional");
-const { cleanUI } = require("sdk/test/utils");
-const { after } = require("sdk/test/utils");
-const { merge } = require("sdk/util/object");
-const self = require("sdk/self");
-const { openTab } = require("../tabs/utils");
-const { set: setPref, reset: resetPref } = require("sdk/preferences/service");
-const OPEN_IN_NEW_WINDOW_PREF = 'browser.link.open_newwindow';
-const DISABLE_POPUP_PREF = 'dom.disable_open_during_load';
-const { wait } = require('../event/helpers');
-
-// TEST: open & close window
-exports.testOpenAndCloseWindow = function(assert, done) {
-  assert.equal(browserWindows.length, 1, "Only one window open");
-  let title = 'testOpenAndCloseWindow';
-
-  browserWindows.open({
-    url: "data:text/html;charset=utf-8,<title>" + title + "</title>",
-    onOpen: function(window) {
-      assert.equal(this, browserWindows, "The 'this' object is the windows object.");
-      assert.equal(window.tabs.length, 1, "Only one tab open");
-      assert.equal(browserWindows.length, 2, "Two windows open");
-
-      window.tabs.activeTab.once('ready', function onReady(tab) {
-        assert.pass(RegExp(title).test(window.title), "URL correctly loaded");
-        window.close();
-      });
-    },
-    onClose: function(window) {
-      assert.equal(window.tabs.length, 0, "Tabs were cleared");
-      assert.equal(browserWindows.length, 1, "Only one window open");
-      done();
-    }
-  });
-};
-
-exports.testNeWindowIsFocused = function(assert, done) {
-  let mainWindow = browserWindows.activeWindow;
-
-  browserWindows.open({
-    url: "about:blank",
-    onOpen: function(window) {
-      focus(viewFor(window)).then((window) => {
-        assert.ok(isFocused(window), 'the new window is focused');
-        assert.ok(isFocused(browserWindows.activeWindow), 'the active window is focused');
-        assert.ok(!isFocused(mainWindow), 'the main window is not focused');
-        done();
-      })
-    }
-  });
-}
-
-exports.testOpenRelativePathWindow = function*(assert) {
-  assert.equal(browserWindows.length, 1, "Only one window open");
-
-  let loader = Loader(module, null, null, {
-    modules: {
-      "sdk/self": merge({}, self, {
-        data: merge({}, self.data, require("./../fixtures"))
-      })
-    }
-  });
-  assert.pass("Created a new loader");
-
-  let tabReady = new Promise(resolve => {
-    loader.require("sdk/tabs").on("ready", (tab) => {
-      if (!/test\.html$/.test(tab.url))
-        return;
-      assert.equal(tab.title, "foo",
-        "tab opened a document with relative path");
-      resolve();
-    });
-  });
-
-
-  yield new Promise(resolve => {
-    loader.require("sdk/windows").browserWindows.open({
-      url: "./test.html",
-      onOpen: (window) => {
-        assert.pass("Created a new window");
-        resolve();
-      }
-    })
-  });
-
-  yield tabReady;
-  loader.unload();
-}
-
-exports.testAutomaticDestroy = function(assert, done) {
-  let windows = browserWindows;
-
-  // Create a second windows instance that we will unload
-  let called = false;
-  let loader = Loader(module);
-  let windows2 = loader.require("sdk/windows").browserWindows;
-
-  windows2.on("open", function() {
-    called = true;
-  });
-
-  loader.unload();
-
-  // Fire a windows event and check that this unloaded instance is inactive
-  windows.open({
-    url: "data:text/html;charset=utf-8,foo",
-    onOpen: function(window) {
-      setTimeout(function () {
-        assert.ok(!called, "Unloaded windows instance is destroyed and inactive");
-        done();
-      });
-    }
-  });
-};
-
-exports.testWindowTabsObject = function(assert, done) {
-  let window, count = 0;
-  function runTest() {
-    if (++count != 2)
-      return;
-
-    assert.equal(window.tabs.length, 1, "Only 1 tab open");
-    assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
-
-    window.tabs.open({
-      url: "data:text/html;charset=utf-8,<title>tab 2</title>",
-      inBackground: true,
-      onReady: function onReady(newTab) {
-        assert.equal(window.tabs.length, 2, "New tab open");
-        assert.equal(newTab.title, "tab 2", "Correct new tab title");
-        assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab");
-
-        let i = 1;
-        for (let tab of window.tabs)
-          assert.equal(tab.title, "tab " + i++, "Correct title");
-
-        window.close();
-      }
-    });
-  }
-
-  tabs.once("ready", runTest);
-
-  browserWindows.open({
-    url: "data:text/html;charset=utf-8,<title>tab 1</title>",
-    onActivate: function onActivate(win) {
-      window = win;
-      runTest();
-    },
-    onClose: function onClose(window) {
-      assert.equal(window.tabs.length, 0, "No more tabs on closed window");
-      done();
-    }
-  });
-};
-
-exports.testOnOpenOnCloseListeners = function(assert, done) {
-  let windows = browserWindows;
-
-  assert.equal(browserWindows.length, 1, "Only one window open");
-
-  let received = {
-    listener1: false,
-    listener2: false,
-    listener3: false,
-    listener4: false
-  }
-
-  function listener1() {
-    assert.equal(this, windows, "The 'this' object is the windows object.");
-
-    if (received.listener1)
-      assert.fail("Event received twice");
-    received.listener1 = true;
-  }
-
-  function listener2() {
-    if (received.listener2)
-      assert.fail("Event received twice");
-    received.listener2 = true;
-  }
-
-  function listener3() {
-    assert.equal(this, windows, "The 'this' object is the windows object.");
-    if (received.listener3)
-      assert.fail("Event received twice");
-    received.listener3 = true;
-  }
-
-  function listener4() {
-    if (received.listener4)
-      assert.fail("Event received twice");
-    received.listener4 = true;
-  }
-
-  windows.on('open', listener1);
-  windows.on('open', listener2);
-  windows.on('close', listener3);
-  windows.on('close', listener4);
-
-  windows.open({
-    url: "data:text/html;charset=utf-8,foo",
-    onOpen: function(window) {
-      window.close(function() {
-        assert.ok(received.listener1, "onOpen handler called");
-        assert.ok(received.listener2, "onOpen handler called");
-        assert.ok(received.listener3, "onClose handler called");
-        assert.ok(received.listener4, "onClose handler called");
-
-        windows.removeListener('open', listener1);
-        windows.removeListener('open', listener2);
-        windows.removeListener('close', listener3);
-        windows.removeListener('close', listener4);
-
-        done();
-      });
-    }
-  });
-};
-
-exports.testActiveWindow = function*(assert) {
-  let windows = browserWindows;
-  let window = getMostRecentWindow();
-
-  // Raw window objects
-  let rawWindow2 =  yield windowPromise(window.OpenBrowserWindow(), "load").then(focus);
-  assert.pass("Window 2 was created");
-
-  // open a tab in window 2
-  yield openTab(rawWindow2, "data:text/html;charset=utf-8,<title>window 2</title>");
-
-  assert.equal(rawWindow2.content.document.title, "window 2", "Got correct raw window 2");
-  assert.equal(rawWindow2.document.title, windows[1].title, "Saw correct title on window 2");
-
-  let rawWindow3 =  yield windowPromise(window.OpenBrowserWindow(), "load").then(focus);;
-  assert.pass("Window 3 was created");
-
-  // open a tab in window 3
-  yield openTab(rawWindow3, "data:text/html;charset=utf-8,<title>window 3</title>");
-
-  assert.equal(rawWindow3.content.document.title, "window 3", "Got correct raw window 3");
-  assert.equal(rawWindow3.document.title, windows[2].title, "Saw correct title on window 3");
-
-  assert.equal(windows.length, 3, "Correct number of browser windows");
-
-  let count = 0;
-  for (let window in windows) {
-    count++;
-  }
-  assert.equal(count, 3, "Correct number of windows returned by iterator");
-  assert.equal(windows.activeWindow.title, windows[2].title, "Correct active window title - 3");
-  let window3 = windows[2];
-
-  yield focus(rawWindow2);
-
-  assert.equal(windows.activeWindow.title, windows[1].title, "Correct active window title - 2");
-  let window2 = windows[1];
-
-  yield new Promise(resolve => {
-    onFocus(rawWindow2).then(resolve);
-    window2.activate();
-    assert.pass("activating window2");
-  });
-
-  assert.equal(windows.activeWindow.title, windows[1].title, "Correct active window - 2");
-
-  yield new Promise(resolve => {
-    onFocus(rawWindow3).then(resolve);
-    window3.activate();
-    assert.pass("activating window3");
-  });
-
-  assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3");
-
-  yield close(rawWindow2);
-  yield close(rawWindow3);
-
-  assert.equal(windows.length, 1, "Correct number of browser windows");
-  assert.equal(window.closed, false, "Original window is still open");
-};
-
-exports.testTrackWindows = function(assert, done) {
-  let windows = [];
-  let actions = [];
-
-  let expects = [
-    "activate 0", "global activate 0", "deactivate 0", "global deactivate 0",
-    "activate 1", "global activate 1", "deactivate 1", "global deactivate 1",
-    "activate 2", "global activate 2"
-  ];
-
-  function windowsActivation(window) {
-    let index = windows.indexOf(window);
-    // only concerned with windows opened for this test
-    if (index < 0)
-      return;
-
-    assert.equal(actions.join(), expects.slice(0, index*4 + 1).join(), expects[index*4 + 1]);
-    actions.push("global activate " + index)
-  }
-
-  function windowsDeactivation(window) {
-    let index = windows.indexOf(window);
-    // only concerned with windows opened for this test
-    if (index < 0)
-      return;
-
-    assert.equal(actions.join(), expects.slice(0, index*4 + 3).join(), expects[index*4 + 3]);
-    actions.push("global deactivate " + index)
-  }
-
-  // listen to global activate events
-  browserWindows.on("activate", windowsActivation);
-
-  // listen to global deactivate events
-  browserWindows.on("deactivate", windowsDeactivation);
-
-  function openWindow() {
-    windows.push(browserWindows.open({
-      url: "data:text/html;charset=utf-8,<i>testTrackWindows</i>",
-      onActivate: function(window) {
-        let index = windows.indexOf(window);
-
-        // Guard against windows that have already been removed.
-        // See bug 874502 comment 32.
-        if (index == -1)
-          return;
-
-        assert.equal(actions.join(),
-                     expects.slice(0, index*4).join(),
-                     "expecting " + expects[index*4]);
-        actions.push("activate " + index);
-
-        if (windows.length < 3) {
-          openWindow()
-        }
-        else {
-          (function closeWindows(windows) {
-            if (!windows.length) {
-              assert.pass('the last window was closed');
-              browserWindows.removeListener("activate", windowsActivation);
-              browserWindows.removeListener("deactivate", windowsDeactivation);
-              assert.pass('removed listeners');
-              return done();
-            }
-
-            return windows.pop().close(function() {
-              assert.pass('window was closed');
-              closeWindows(windows);
-            });
-          })(windows)
-        }
-      },
-      onDeactivate: function(window) {
-        let index = windows.indexOf(window);
-
-        // Guard against windows that have already been removed.
-        // See bug 874502 comment 32.
-        if (index == -1)
-          return;
-
-        assert.equal(actions.join(),
-                     expects.slice(0, index*4 + 2).join(),
-                     "expecting " + expects[index*4 + 2]);
-        actions.push("deactivate " + index)
-      }
-    }));
-  }
-  openWindow();
-}
-
-// test that it is not possible to open a private window by default
-exports.testWindowOpenPrivateDefault = function*(assert) {
-  const TITLE = "yo";
-  const URL = "data:text/html,<title>" + TITLE + "</title>";
-
-  let tabReady = new Promise(resolve => {
-    tabs.on('ready', function onTabReady(tab) {
-      if (tab.url != URL)
-        return;
-
-      tabs.removeListener('ready', onTabReady);
-      assert.equal(tab.title, TITLE, 'opened correct tab');
-      assert.equal(isPrivate(tab), false, 'tab is not private');
-      resolve();
-    });
-  })
-
-  yield new Promise(resolve => browserWindows.open({
-    url: URL,
-    isPrivate: true,
-    onOpen: function(window) {
-      assert.pass("the new window was opened");
-      resolve();
-    }
-  }));
-
-  yield tabReady;
-}
-
-// test that it is not possible to find a private window in
-// windows module's iterator
-exports.testWindowIteratorPrivateDefault = function*(assert) {
-  assert.equal(browserWindows.length, 1, 'only one window open');
-
-  let window = yield open('chrome://browser/content/browser.xul', {
-    features: {
-      private: true,
-      chrome: true
-    }
-  });
-
-  yield focus(window);
-
-  // test that there is a private window opened
-  assert.equal(isPrivate(window), true, 'there is a private window open');
-  assert.strictEqual(window, winUtils.activeWindow);
-  assert.strictEqual(window, getMostRecentWindow());
-
-  assert.ok(!isPrivate(browserWindows.activeWindow));
-
-  assert.equal(browserWindows.length, 1, 'only one window in browserWindows');
-  assert.equal(windows().length, 1, 'only one window in windows()');
-
-  assert.equal(windows(null, { includePrivate: true }).length, 2);
-
-  // test that all windows in iterator are not private
-  for (let window of browserWindows) {
-    assert.ok(!isPrivate(window), 'no window in browserWindows is private');
-  }
-};
-
-exports["test getView(window)"] = function(assert, done) {
-  browserWindows.once("open", window => {
-    const view = viewFor(window);
-
-    assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
-    assert.ok(isBrowser(view), "view is a browser window");
-    assert.equal(getWindowTitle(view), window.title,
-                 "window has a right title");
-
-    window.close();
-    // Defer handler cause window is destroyed after event is dispatched.
-    browserWindows.once("close", defer(_ => {
-      assert.equal(viewFor(window), null, "window view is gone");
-      done();
-    }));
-  });
-
-  browserWindows.open({ url: "data:text/html,<title>yo</title>" });
-};
-
-// Tests that the this property is correct in event listeners called from
-// the windows API.
-exports.testWindowEventBindings = function(assert, done) {
-  let loader = Loader(module);
-  let { browserWindows } = loader.require("sdk/windows");
-  let firstWindow = browserWindows.activeWindow;
-  let { viewFor } = loader.require("sdk/view/core");
-
-  let EVENTS = ["open", "close", "activate", "deactivate"];
-
-  let windowBoundEventHandler = (event) => function(window) {
-    // Close event listeners are always bound to browserWindows.
-    if (event == "close")
-      assert.equal(this, browserWindows, "window listener for " + event + " event should be bound to the browserWindows object.");
-    else
-      assert.equal(this, window, "window listener for " + event + " event should be bound to the window object.");
-  };
-
-  let windowsBoundEventHandler = (event) => function(window) {
-    assert.equal(this, browserWindows, "windows listener for " + event + " event should be bound to the browserWindows object.");
-  }
-  for (let event of EVENTS)
-    browserWindows.on(event, windowsBoundEventHandler(event));
-
-  let windowsOpenEventHandler = (event) => function(window) {
-    // Open and close event listeners are always bound to browserWindows.
-    if (event == "open" || event == "close")
-      assert.equal(this, browserWindows, "windows open listener for " + event + " event should be bound to the browserWindows object.");
-    else
-      assert.equal(this, window, "windows open listener for " + event + " event should be bound to the window object.");
-  }
-
-  let openArgs = {
-    url: "data:text/html;charset=utf-8,binding-test",
-    onOpen: function(window) {
-      windowsOpenEventHandler("open").call(this, window);
-
-      for (let event of EVENTS)
-        window.on(event, windowBoundEventHandler(event));
-
-      let rawWindow = viewFor(window);
-      onFocus(rawWindow).then(() => {
-        window.once("deactivate", () => {
-          window.once("close", () => {
-            loader.unload();
-            done();
-          });
-
-          window.close();
-        });
-
-        firstWindow.activate();
-      });
-    }
-  };
-  // Listen to everything except onOpen
-  for (let event of EVENTS.slice(1)) {
-    openArgs["on" + event.slice(0, 1).toUpperCase() + event.slice(1)] = windowsOpenEventHandler(event);
-  }
-
-  browserWindows.open(openArgs);
-}
-
-// Tests that the this property is correct in event listeners called from
-// manipulating window.tabs.
-exports.testWindowTabEventBindings = function(assert, done) {
-  let loader = Loader(module);
-  let { browserWindows } = loader.require("sdk/windows");
-  let firstWindow = browserWindows.activeWindow;
-  let tabs = loader.require("sdk/tabs");
-  let windowTabs = firstWindow.tabs;
-  let firstTab = firstWindow.tabs.activeTab;
-
-  let EVENTS = ["open", "close", "activate", "deactivate",
-                "load", "ready", "pageshow"];
-
-  let tabBoundEventHandler = (event) => function(tab) {
-    assert.equal(this, tab, "tab listener for " + event + " event should be bound to the tab object.");
-  };
-
-  let windowTabsBoundEventHandler = (event) => function(tab) {
-    assert.equal(this, windowTabs, "window tabs listener for " + event + " event should be bound to the windowTabs object.");
-  }
-  for (let event of EVENTS)
-    windowTabs.on(event, windowTabsBoundEventHandler(event));
-
-  let windowTabsOpenEventHandler = (event) => function(tab) {
-    assert.equal(this, tab, "window tabs open listener for " + event + " event should be bound to the tab object.");
-  }
-
-  let openArgs = {
-    url: "data:text/html;charset=utf-8,binding-test",
-    onOpen: function(tab) {
-      windowTabsOpenEventHandler("open").call(this, tab);
-
-      for (let event of EVENTS)
-        tab.on(event, tabBoundEventHandler(event));
-
-      tab.once("pageshow", () => {
-        tab.once("deactivate", () => {
-          tab.once("close", () => {
-            loader.unload();
-            done();
-          });
-
-          tab.close();
-        });
-
-        firstTab.activate();
-      });
-    }
-  };
-  // Listen to everything except onOpen
-  for (let event of EVENTS.slice(1)) {
-    let eventProperty = "on" + event.slice(0, 1).toUpperCase() + event.slice(1);
-    openArgs[eventProperty] = windowTabsOpenEventHandler(event);
-  }
-
-  windowTabs.open(openArgs);
-}
-
-// related to bug #989288
-// https://bugzilla.mozilla.org/show_bug.cgi?id=989288
-exports["test window events after window.open"] = function*(assert, done) {
-  // ensure popups open in a new windows and disable popup blocker
-  setPref(OPEN_IN_NEW_WINDOW_PREF, 2);
-  setPref(DISABLE_POPUP_PREF, false);
-
-  // open window to trigger observers
-  tabs.activeTab.attach({
-    contentScript: "window.open('about:blank', '', " +
-                   "'width=800,height=600,resizable=no,status=no,location=no');"
-  });
-
-  let window = yield wait(browserWindows, "open");
-  assert.pass("tab open has occured");
-  window.close();
-
-  yield wait(browserWindows,"close");
-  assert.pass("tab close has occured");
-};
-
-after(exports, function*(name, assert) {
-  resetPopupPrefs();
-  yield cleanUI();
-});
-
-const resetPopupPrefs = () => {
-  resetPref(OPEN_IN_NEW_WINDOW_PREF);
-  resetPref(DISABLE_POPUP_PREF);
-};
-
-require('sdk/test').run(exports);
deleted file mode 100644
--- a/addon-sdk/source/test/zip/utils.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { Ci, Cc } = require("chrome");
-const { defer, all } = require("sdk/core/promise");
-
-const PR_RDONLY      = 0x01;
-const PR_WRONLY      = 0x02;
-const PR_RDWR        = 0x04;
-const PR_CREATE_FILE = 0x08;
-const PR_APPEND      = 0x10;
-const PR_TRUNCATE    = 0x20;
-const PR_SYNC        = 0x40;
-const PR_EXCL        = 0x80;
-
-// Default compression level:
-const { COMPRESSION_DEFAULT } = Ci.nsIZipWriter;
-
-function createNsFile(path) {
-  let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
-  try {
-    file.initWithPath(path);
-  } catch(e) {
-    throw new Error("This zip file path is not valid : " + path + "\n" + e);
-  }
-  return file;
-}
-exports.createNsFile = createNsFile;
-
-const converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
-                  createInstance(Ci.nsIScriptableUnicodeConverter);
-converter.charset = "UTF-8";
-function streamForData(data) {
-  return converter.convertToInputStream(data);
-}
-
-exports.ZipWriter = function (zipPath, mode) {
-  mode = mode ? mode : PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE;
-
-  let zw = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
-  zw.open(createNsFile(zipPath), mode);
-
-  // Create a directory entry.
-  // Returns true if the entry was created, or false if the entry already exists
-  this.mkdir = function mkdir(pathInZip) {
-    try {
-      zw.addEntryDirectory(pathInZip, 0, false);
-    }
-    catch(e) {
-      if (e.name === "NS_ERROR_FILE_ALREADY_EXISTS")
-        return false;
-      throw e
-    }
-    return true;
-  }
-
-  this.addFile = function addFile(pathInZip, filePath) {
-    let { promise, reject, resolve } = defer();
-
-    let nsfile = createNsFile(filePath);
-    if (!nsfile.exists()) {
-      reject(new Error("This file doesn't exist: " + nsfile.path));
-      return promise;
-    }
-
-    // Case 1/ Regular file
-    if (!nsfile.isDirectory()) {
-      try {
-        zw.addEntryFile(pathInZip, COMPRESSION_DEFAULT, nsfile, false);
-        resolve();
-      }
-      catch (e) {
-        reject(new Error("Unable to add following file in zip: " + nsfile.path + "\n" + e));
-      }
-      return promise;
-    }
-
-    // Case 2/ Directory
-    if (pathInZip.substr(-1) !== '/')
-      pathInZip += "/";
-    let entries = nsfile.directoryEntries;
-    let array = [];
-
-    zw.addEntryDirectory(pathInZip, nsfile.lastModifiedTime, false);
-
-    while(entries.hasMoreElements()) {
-      let file = entries.getNext().QueryInterface(Ci.nsIFile);
-      if (file.leafName === "." || file.leafName === "..")
-        continue;
-      let path = pathInZip + file.leafName;
-      if (path.substr(0, 1) == '/') {
-        path = path.substr(1);
-      }
-      this.addFile(path, file.path);
-    }
-
-    resolve();
-    return promise;
-  }
-
-  this.addData = function (pathInZip, data) {
-    let deferred = defer();
-
-    try {
-      let stream = streamForData(data);
-      zw.addEntryStream(pathInZip, 0, COMPRESSION_DEFAULT, stream, false);
-    } catch(e) {
-      throw new Error("Unable to add following data in zip: " +
-                      data.substr(0, 20) + "\n" + e);
-    }
-
-    deferred.resolve();
-    return deferred.promise;
-  }
-
-  this.close = function close() {
-    let deferred = defer();
-
-    zw.close();
-
-    deferred.resolve();
-    return deferred.promise;
-  }
-}
deleted file mode 100644
--- a/addon-sdk/test/Math.jsm
+++ /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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["Math"];
-
-this.Math = {
-  square: function (x) { return x * x; }
-};
deleted file mode 100644
--- a/addon-sdk/test/browser.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-[DEFAULT]
-support-files =
-  head.js
-  Math.jsm
-  math.js
-  data.json
-  invalid.json
-[browser_sdk_loader_sdk_modules.js]
-[browser_sdk_loader_jsm_modules.js]
-[browser_sdk_loader_js_modules.js]
-[browser_sdk_loader_json.js]
-[browser_sdk_loader_chrome.js]
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_chrome.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", gTestPath);
-  let require = Require(loader, module);
-
-  const { Ci, Cc, Cu, components } = require("chrome");
-
-  let { generateUUID } = Cc["@mozilla.org/uuid-generator;1"]
-                         .getService(Ci.nsIUUIDGenerator);
-  ok(isUUID(generateUUID()), "chrome.Cc and chrome.Ci works");
-  
-  let { ID: parseUUID } = components;
-  let uuidString = "00001111-2222-3333-4444-555566667777";
-  let parsed = parseUUID(uuidString);
-  is(parsed, "{" + uuidString + "}", "chrome.components works");
-
-  const { defer } = Cu.import("resource://gre/modules/Promise.jsm").Promise;
-  let { promise, resolve } = defer();
-  resolve(5);
-  promise.then(val => {
-    is(val, 5, "chrome.Cu works");
-    finish();
-  });
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_chrome_in_sdk.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", gTestPath);
-  let require = Require(loader, module);
-
-  // sdk/util/uuid uses Cc, Ci, components
-  const { uuid } = require("sdk/util/uuid");
-
-  ok(isUUID(uuid()), "chrome.Cc and chrome.Ci works in SDK includes");
-
-  let uuidString = '00001111-2222-3333-4444-555566667777';
-  let parsed = uuid(uuidString);
-  is(parsed, '{' + uuidString + '}', "chrome.components works in SDK includes");
-
-  // sdk/base64 uses Cu
-  const { encode } = require("sdk/base64");
-  is(encode("hello"), "aGVsbG8=", "chrome.Cu works in SDK includes");
-  finish();
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_js_modules.js
+++ /dev/null
@@ -1,33 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", gTestPath);
-  let require = Require(loader, module);
-
-  try {
-    let Model = require("./cant-find-me");
-    ok(false, "requiring a JS module that doesn't exist should throw");
-  }
-  catch (e) {
-    ok(e, "requiring a JS module that doesn't exist should throw");
-  }
-
-
-  /*
-   * Relative resource:// URI of JS
-   */
-
-  let { square } = require("./math");
-  is(square(5), 25, "loads relative URI of JS");
-
-  /*
-   * Absolute resource:// URI of JS
-   */
-
-  let { has } = require("resource://gre/modules/commonjs/sdk/util/array");
-  let testArray = ['rock', 'paper', 'scissors'];
-
-  ok(has(testArray, 'rock'), "loads absolute resource:// URI of JS");
-  ok(!has(testArray, 'dragon'), "loads absolute resource:// URI of JS");
-
-  finish();
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_jsm_modules.js
+++ /dev/null
@@ -1,31 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", gTestPath);
-  let require = Require(loader, module);
-
-  try {
-    let Model = require("resource://gre/modules/BlinkTag.jsm");
-    ok(false, "requiring a JS module that doesn't exist should throw");
-  }
-  catch (e) {
-    ok(e, "requiring a JS module that doesn't exist should throw");
-  }
-
-  /*
-   * Relative resource:// URI of JSM
-   */
-
-  let { square } = require("./Math.jsm").Math;
-  is(square(5), 25, "loads relative URI of JSM");
-
-  /*
-   * Absolute resource:// URI of JSM
-   */
-  let { defer } = require("resource://gre/modules/Promise.jsm").Promise;
-  let { resolve, promise } = defer();
-  resolve(5);
-  promise.then(val => {
-    is(val, 5, "loads absolute resource:// URI of JSM");
-  }).then(finish);
-
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_json.js
+++ /dev/null
@@ -1,23 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", gTestPath);
-  let require = Require(loader, module);
-
-  /*
-   * Relative resource:// URI of json
-   */
-
-  let data = require("./data.json");
-  is(data.title, "jetpack mochitests", "loads relative JSON");
-  is(data.dependencies.underscore, "1.0.0", "loads relative JSON");
-
-  try {
-    let data = require("./invalid.json");
-    ok(false, "parsing an invalid JSON should throw");
-  }
-  catch (e) {
-    ok(e, "parsing an invalid JSON should throw");
-  }
-
-  finish();
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_sdk_gui_modules.js
+++ /dev/null
@@ -1,18 +0,0 @@
-function test () {
-  // Load `constructor` as global since tabs uses `traits`
-  // that use this module
-  let loader = makeLoader({ globals: constructor });
-  let module = Module("./main", "scratchpad://");
-  let require = Require(loader, module);
-
-  let tabs = require("sdk/tabs");
-
-  tabs.open({
-    url: "about:blank",
-    onReady: function (tab) {
-      is(tab.url, "about:blank", "correct uri for tab");
-      is(tabs.activeTab, tab, "correctly active tab");
-      tab.close(finish);
-    }
-  });
-}
deleted file mode 100644
--- a/addon-sdk/test/browser_sdk_loader_sdk_modules.js
+++ /dev/null
@@ -1,22 +0,0 @@
-function test () {
-  let loader = makeLoader();
-  let module = Module("./main", "scratchpad://");
-  let require = Require(loader, module);
-
-  let { has } = require("sdk/util/array");
-  let { extend } = require("sdk/util/object");
-  let testArray = [1, 'hello', 2, 'hi'];
-
-  ok(has(testArray, 1), 'loader loading simple array utils');
-  ok(has(testArray, 'hello'), 'loader loading simple array utils');
-  ok(!has(testArray, 4), 'loader loading simple array utils');
-
-  let testObj1 = { strings: 6, prop: [] };
-  let testObj2 = { name: 'Tosin Abasi', strings: 8 };
-  let extended = extend(testObj1, testObj2);
-
-  is(extended.name, 'Tosin Abasi', 'loader loading simple object utils');
-  is(extended.strings, 8, 'loader loading simple object utils');
-  is(extended.prop, testObj1.prop, 'loader loading simple object utils');
-  finish();
-}
deleted file mode 100644
--- a/addon-sdk/test/data.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "title": "jetpack mochitests",
-  "dependencies": {
-    "underscore": "1.0.0"
-  }
-}
deleted file mode 100644
--- a/addon-sdk/test/head.js
+++ /dev/null
@@ -1,79 +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 { utils: Cu } = Components;
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-const LoaderModule = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {}).Loader;
-const { console } = Cu.import("resource://gre/modules/Console.jsm", {});
-var {
-  Loader, main, Module, Require, unload
-} = LoaderModule;
-
-var CURRENT_DIR = gTestPath.replace(/\/[^\/]*\.js$/,'/');
-var loaders = [];
-
-// All tests are asynchronous.
-waitForExplicitFinish();
-
-var gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
-Services.prefs.setBoolPref("devtools.debugger.log", true);
-
-registerCleanupFunction(() => {
-  info("finish() was called, cleaning up...");
-  loaders.forEach(unload);
-  Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
-});
-
-function makePaths (root) {
-  return {
-    './': CURRENT_DIR,
-    '': 'resource://gre/modules/commonjs/'
-  };
-}
-
-function makeLoader (options) {
-  let { paths, globals } = options || {};
-
-  // We have to have `console` as a global, otherwise
-  // many SDK modules will fail
-  // bug 961252
-  let globalDefaults = {
-    console: console
-  };
-
-  let loader = Loader({
-    paths: paths || makePaths(),
-    globals: extend({}, globalDefaults, globals) || null,
-    modules: {
-      // Needed because sdk/ modules reference utilities in
-      // `toolkit/loader`, until Bug 961194 is completed
-      'toolkit/loader': LoaderModule
-    },
-    // We need rootURI due to `sdk/self` (or are using native loader)
-    // which overloads with pseudo modules
-    // bug 961245
-    rootURI: CURRENT_DIR,
-    // We also need metadata dummy object
-    // bug 961245
-    metadata: {}
-  });
-
-  loaders.push(loader);
-  return loader;
-}
-
-function isUUID (string) {
-  return /^\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}$/.test(string);
-}
-
-function extend (...objs) {
-  if (objs.length === 0 || objs.length === 1)
-    return objs[0] || {};
-
-  for (let i = objs.length; i > 1; i--) {
-    for (var prop in objs[i - 1])
-      objs[0][prop] = objs[i - 1][prop];
-  }
-  return objs[0];
-}
deleted file mode 100644
--- a/addon-sdk/test/invalid.json
+++ /dev/null
@@ -1,1 +0,0 @@
-this isnt json
deleted file mode 100644
--- a/addon-sdk/test/math.js
+++ /dev/null
@@ -1,7 +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.square = function square (x) { return x * x; }