Merge m-c to cedar
authorJames Graham <james@hoppipolla.co.uk>
Tue, 12 May 2015 15:42:20 +0100
changeset 326805 2ab7227887a121f675a03942d0422bc55939dae2
parent 326804 065f57c91e7fd00c581729fbab18fe10ac882f2a (current diff)
parent 264188 bedce1b405a38273d190853039000b78cc183bb6 (diff)
child 326806 df7a9f4648cfc133d9cbed40fc6af9ae4409968b
push id10169
push userdminor@mozilla.com
push dateThu, 28 Jan 2016 13:10:48 +0000
milestone41.0a1
Merge m-c to cedar
CLOBBER
addon-sdk/source/examples/annotator/README.md
addon-sdk/source/examples/annotator/data/annotation/annotation.html
addon-sdk/source/examples/annotator/data/annotation/annotation.js
addon-sdk/source/examples/annotator/data/editor/annotation-editor.html
addon-sdk/source/examples/annotator/data/editor/annotation-editor.js
addon-sdk/source/examples/annotator/data/jquery-1.4.2.min.js
addon-sdk/source/examples/annotator/data/list/annotation-list.css
addon-sdk/source/examples/annotator/data/list/annotation-list.html
addon-sdk/source/examples/annotator/data/list/annotation-list.js
addon-sdk/source/examples/annotator/data/matcher.js
addon-sdk/source/examples/annotator/data/selector.js
addon-sdk/source/examples/annotator/data/widget/pencil-off.png
addon-sdk/source/examples/annotator/data/widget/pencil-on.png
addon-sdk/source/examples/annotator/data/widget/widget.js
addon-sdk/source/examples/annotator/lib/main.js
addon-sdk/source/examples/annotator/package.json
addon-sdk/source/examples/annotator/tests/test-main.js
addon-sdk/source/examples/library-detector/README.md
addon-sdk/source/examples/library-detector/data/icons/closure.ico
addon-sdk/source/examples/library-detector/data/icons/jquery.ico
addon-sdk/source/examples/library-detector/data/icons/jquery_ui.ico
addon-sdk/source/examples/library-detector/data/icons/modernizr.ico
addon-sdk/source/examples/library-detector/data/icons/mootools.png
addon-sdk/source/examples/library-detector/data/icons/yui.ico
addon-sdk/source/examples/library-detector/data/library-detector.js
addon-sdk/source/examples/library-detector/data/panel.html
addon-sdk/source/examples/library-detector/data/widget.html
addon-sdk/source/examples/library-detector/lib/main.js
addon-sdk/source/examples/library-detector/package.json
addon-sdk/source/examples/library-detector/test/test-main.js
addon-sdk/source/lib/sdk/deprecated/cortex.js
addon-sdk/source/lib/sdk/deprecated/errors.js
addon-sdk/source/lib/sdk/deprecated/events.js
addon-sdk/source/lib/sdk/deprecated/light-traits.js
addon-sdk/source/lib/sdk/deprecated/list.js
addon-sdk/source/lib/sdk/deprecated/symbiont.js
addon-sdk/source/lib/sdk/deprecated/traits-worker.js
addon-sdk/source/lib/sdk/deprecated/traits.js
addon-sdk/source/lib/sdk/deprecated/traits/core.js
addon-sdk/source/lib/sdk/input/window.js
addon-sdk/source/lib/sdk/test/tmp-file.js
addon-sdk/source/lib/sdk/widget.js
addon-sdk/source/lib/sdk/windows/dom.js
addon-sdk/source/lib/sdk/windows/tabs-firefox.js
addon-sdk/source/test/addons/symbiont/data/test-trusted-document.html
addon-sdk/source/test/addons/symbiont/main.js
addon-sdk/source/test/addons/symbiont/package.json
addon-sdk/source/test/fixtures/test-content-symbiont.js
addon-sdk/source/test/test-content-loader.js
addon-sdk/source/test/test-content-symbiont.js
addon-sdk/source/test/test-cortex.js
addon-sdk/source/test/test-deprecated-list.js
addon-sdk/source/test/test-errors.js
addon-sdk/source/test/test-events.js
addon-sdk/source/test/test-light-traits.js
addon-sdk/source/test/test-tmp-file.js
addon-sdk/source/test/test-tmp-file.txt
addon-sdk/source/test/test-traits-core.js
addon-sdk/source/test/test-traits.js
addon-sdk/source/test/test-widget.js
addon-sdk/source/test/traits/descriptor-tests.js
addon-sdk/source/test/traits/inheritance-tests.js
addon-sdk/source/test/traits/object-tests.js
b2g/app/b2g.icns
b2g/app/b2g.ico
b2g/app/default.png
b2g/branding/official/android-resources.mn
b2g/branding/unofficial/android-resources.mn
browser/base/content/sync/progress.js
browser/base/content/sync/progress.xhtml
browser/base/content/test/general/browser_aboutSyncProgress.js
browser/base/content/test/general/browser_fxa_profile_channel.html
browser/base/content/test/general/browser_fxa_profile_channel.js
browser/components/loop/content/shared/libs/jquery-2.1.0.js
browser/devtools/commandline/commands-index.js
browser/devtools/shared/test/browser_layoutHelpers_iframe.html
browser/locales/en-US/chrome/browser/devtools/gcli.properties
browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
browser/locales/en-US/chrome/browser/syncProgress.dtd
browser/themes/linux/downloads/contentAreaDownloadsView.css
browser/themes/linux/syncProgress.css
browser/themes/osx/downloads/contentAreaDownloadsView.css
browser/themes/osx/syncProgress.css
browser/themes/windows/downloads/contentAreaDownloadsView.css
browser/themes/windows/syncProgress.css
dom/base/test/chrome.ini
dom/bluetooth/BluetoothInterface.cpp
dom/media/tests/mochitest/test_peerConnection_addCandidateInHaveLocalOffer.html
dom/plugins/ipc/interpose/Makefile.in
image/public/ImageLogging.h
image/public/imgICache.idl
image/public/imgIContainer.idl
image/public/imgIContainerDebug.idl
image/public/imgIEncoder.idl
image/public/imgILoader.idl
image/public/imgINotificationObserver.idl
image/public/imgIOnloadBlocker.idl
image/public/imgIRequest.idl
image/public/imgIScriptedNotificationObserver.idl
image/public/imgITools.idl
image/public/moz.build
image/public/nsIIconURI.idl
intl/unicharutil/util/Makefile.in
js/src/jsapi-tests/testGCNursery.cpp
layout/base/nsRefreshDriver.cpp
layout/base/tests/marionette/test_selectioncarets_multiplerange.py
media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl
media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h
memory/mozalloc/Makefile.in
mobile/android/base/animation/BounceAnimator.java
rdf/util/Makefile.in
security/manager/ssl/tests/mochitest/bugs/chrome.ini
security/manager/ssl/tests/mochitest/stricttransportsecurity/chrome.ini
services/fxaccounts/FxAccountsProfileChannel.jsm
services/fxaccounts/tests/xpcshell/test_profile_channel.js
testing/mozharness/mozharness.json
testing/web-platform/harness/wptrunner/browsers/firefox.py
testing/web-platform/meta/IndexedDB/idbcursor_advance_index.htm.ini
testing/web-platform/meta/IndexedDB/idbcursor_advance_objectstore.htm.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/sandboxed-iframes.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage.https.html.ini
toolkit/components/viewsource/test/browser/browser_viewsourceprefs_nonhtml.js
toolkit/content/tests/chrome/chrome.ini
toolkit/webapps/tests/chrome.ini
tools/profiler/JSStreamWriter.cpp
tools/profiler/JSStreamWriter.h
tools/profiler/tests/gtest/JSStreamWriterTest.cpp
xpcom/glue/Makefile.in
xpcom/glue/nsVoidArray.cpp
xpcom/glue/nsVoidArray.h
xpcom/glue/standalone/Makefile.in
xpcom/glue/standalone/staticruntime/Makefile.in
xpcom/glue/staticruntime/Makefile.in
xpcom/typelib/xpt/Makefile.in
--- a/.hgtags
+++ b/.hgtags
@@ -112,8 +112,9 @@ 0000000000000000000000000000000000000000
 6047f510fb73c7dbe9866066fb01ddda3c170c9c FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_36_BASE
 b297a6727acfd21e757ddd38cd61894812666265 FIREFOX_AURORA_36_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
 2c951493eef5b50b8085ef78ffe0d7902ff3d593 FIREFOX_AURORA_37_BASE
 98086da94ccdc88f6de86774ce3d1fa258dc7c44 FIREFOX_AURORA_38_BASE
 1b6bf6612c0f4d4fee81d18bf18016e692f874e1 FIREFOX_AURORA_39_BASE
+66a95a483d2c77dfc387019336d18093acd6aac2 FIREFOX_AURORA_40_BASE
--- a/.ycm_extra_conf.py
+++ b/.ycm_extra_conf.py
@@ -1,27 +1,40 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.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 imp
 import os
 from StringIO import StringIO
 import shlex
+import sys
+
+old_bytecode = sys.dont_write_bytecode
+sys.dont_write_bytecode = True
 
 path = os.path.join(os.path.dirname(__file__), 'mach')
 
 if not os.path.exists(path):
     path = os.path.join(os.path.dirname(__file__), 'config.status')
     config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
     path = os.path.join(config.topsrcdir, 'mach')
 mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE))
 
+sys.dont_write_bytecode = old_bytecode
+
 def FlagsForFile(filename):
     mach = mach_module.get_mach()
     out = StringIO()
     out.encoding = None
     mach.run(['compileflags', filename], stdout=out, stderr=out)
 
+    flag_list = shlex.split(out.getvalue())
+
+    # This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
+    # Removing this flag is a workaround until ycmd starts to handle this flag properly.
+    # https://github.com/Valloric/YouCompleteMe/issues/1490
+    final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
+
     return {
-        'flags': shlex.split(out.getvalue()),
+        'flags': final_flags,
         'do_cache': True
     }
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1155494 seems to need a clobber to pick up a change the ipdl parser.
+Merge day clobber
\ No newline at end of file
--- a/Makefile.in
+++ b/Makefile.in
@@ -250,18 +250,19 @@ ifdef MOZ_CRASHREPORTER
 	cd $(DIST)/crashreporter-symbols && \
           zip -r9D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
 ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+else
+	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
-	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
 
 # MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
 # exporting it makes make run its $(shell) command for each invoked submake,
 # so transform it to an immediate assignment.
 MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
 export MOZ_SOURCE_STAMP
 endif
--- a/README.txt
+++ b/README.txt
@@ -20,11 +20,8 @@ are accessible on Google Groups, or news
 
 You can download nightly development builds from the Mozilla FTP server.
 Keep in mind that nightly builds, which are used by Mozilla developers for
 testing, may be buggy. Firefox nightlies, for example, can be found at:
 
     ftp://ftp.mozilla.org/pub/firefox/nightly/latest-trunk/
             - or -
     http://nightly.mozilla.org/
-
-
->>
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -850,16 +850,23 @@ refChildCB(AtkObject *aAtkObj, gint aChi
   return childAtkObj;
 }
 
 gint
 getIndexInParentCB(AtkObject* aAtkObj)
 {
   // We don't use Accessible::IndexInParent() because we don't include text
   // leaf nodes as children in ATK.
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    if (ProxyAccessible* parent = proxy->Parent())
+      return parent->IndexOfEmbeddedChild(proxy);
+
+    return -1;
+  }
+
     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     if (!accWrap) {
         return -1;
     }
 
     Accessible* parent = accWrap->Parent();
     if (!parent)
         return -1; // No parent
@@ -1048,16 +1055,19 @@ GetInterfacesForProxy(ProxyAccessible* a
     interfaces |= MAI_INTERFACE_VALUE;
 
   if (aInterfaces & Interfaces::TABLE)
     interfaces |= MAI_INTERFACE_TABLE;
 
   if (aInterfaces & Interfaces::IMAGE)
     interfaces |= MAI_INTERFACE_IMAGE;
 
+  if (aInterfaces & Interfaces::DOCUMENT)
+    interfaces |= MAI_INTERFACE_DOCUMENT;
+
   return interfaces;
 }
 
 void
 a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
   GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy, aInterfaces));
   NS_ASSERTION(type, "why don't we have a type!");
--- a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
+++ b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
@@ -11,17 +11,17 @@
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkHyperlink*
 getHyperlinkCB(AtkHyperlinkImpl* aImpl)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImpl));
-  if (!accWrap || !GetProxy(ATK_OBJECT(aImpl)))
+  if (!accWrap && !GetProxy(ATK_OBJECT(aImpl)))
     return nullptr;
 
   if (accWrap)
     NS_ASSERTION(accWrap->IsLink(), "why isn't it a link!");
 
   return MAI_ATK_OBJECT(aImpl)->GetAtkHyperlink();
 }
 }
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1252,34 +1252,39 @@ nsAccessibilityService::Init()
 
   for (uint32_t i = 0; i < ArrayLength(sMarkupMapList); i++)
     mMarkupMaps.Put(*sMarkupMapList[i].tag, &sMarkupMapList[i]);
 
 #ifdef A11Y_LOG
   logging::CheckEnv();
 #endif
 
-  gApplicationAccessible = new ApplicationAccessibleWrap();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    gApplicationAccessible = new ApplicationAccessibleWrap();
+  else
+    gApplicationAccessible = new ApplicationAccessible();
+
   NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
 
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::
     AnnotateCrashReport(NS_LITERAL_CSTRING("Accessibility"),
                         NS_LITERAL_CSTRING("Active"));
 #endif
 
 #ifdef XP_WIN
   sPendingPlugins = new nsTArray<nsCOMPtr<nsIContent> >;
   sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
 #endif
 
   gIsShutdown = false;
 
   // Now its safe to start platform accessibility.
-  PlatformInit();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    PlatformInit();
 
   return true;
 }
 
 void
 nsAccessibilityService::Shutdown()
 {
   // Remove observers.
@@ -1311,17 +1316,19 @@ nsAccessibilityService::Shutdown()
   // accessibility service as shutdown to prevent calls of its methods.
   // Don't null accessibility service static member at this point to be safe
   // if someone will try to operate with it.
 
   NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
 
   gIsShutdown = true;
 
-  PlatformShutdown();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    PlatformShutdown();
+
   gApplicationAccessible->Shutdown();
   NS_RELEASE(gApplicationAccessible);
   gApplicationAccessible = nullptr;
 
   NS_IF_RELEASE(gXPCApplicationAccessible);
   gXPCApplicationAccessible = nullptr;
 }
 
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -34,16 +34,19 @@ InterfacesFor(Accessible* aAcc)
     interfaces |= Interfaces::VALUE;
 
   if (aAcc->IsImage())
     interfaces |= Interfaces::IMAGE;
 
   if (aAcc->IsTableCell())
     interfaces |= Interfaces::TABLECELL;
 
+  if (aAcc->IsDoc())
+    interfaces |= Interfaces::DOCUMENT;
+
   return interfaces;
 }
 
 static void
 SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree)
 {
   uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
   uint32_t role = aRoot->Role();
@@ -59,16 +62,19 @@ SerializeTree(Accessible* aRoot, nsTArra
   aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
   for (uint32_t i = 0; i < childCount; i++)
     SerializeTree(aRoot->GetChildAt(i), aTree);
 }
 
 Accessible*
 DocAccessibleChild::IdToAccessible(const uint64_t& aID) const
 {
+  if (!aID)
+    return mDoc;
+
   return mDoc->GetAccessibleByUniqueID(reinterpret_cast<void*>(aID));
 }
 
 Accessible*
 DocAccessibleChild::IdToAccessibleLink(const uint64_t& aID) const
 {
   Accessible* acc = IdToAccessible(aID);
   return acc && acc->IsLink() ? acc : nullptr;
@@ -216,17 +222,17 @@ DocAccessibleChild::PersistentProperties
 
 bool
 DocAccessibleChild::RecvRelationByType(const uint64_t& aID,
                                        const uint32_t& aType,
                                        nsTArray<uint64_t>* aTargets)
 {
   Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
   if (!acc)
-    return false;
+    return true;
 
   auto type = static_cast<RelationType>(aType);
   Relation rel = acc->RelationByType(type);
   while (Accessible* target = rel.Next())
     aTargets->AppendElement(reinterpret_cast<uintptr_t>(target));
 
   return true;
 }
@@ -248,18 +254,18 @@ AddRelation(Accessible* aAcc, RelationTy
   }
 }
 
 bool
 DocAccessibleChild::RecvRelations(const uint64_t& aID,
                                   nsTArray<RelationTargets>* aRelations)
 {
   Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
-  if (!aID)
-    return false;
+  if (!acc)
+    return true;
 
 #define RELATIONTYPE(gecko, s, a, m, i) AddRelation(acc, RelationType::gecko, aRelations);
 
 #include "RelationTypeMap.h"
 #undef RELATIONTYPE
 
   return true;
 }
@@ -1608,16 +1614,32 @@ DocAccessibleChild::RecvTakeFocus(const 
   if (acc) {
     acc->TakeFocus();
   }
 
   return true;
 }
 
 bool
+DocAccessibleChild::RecvIndexOfEmbeddedChild(const uint64_t& aID,
+                                             const uint64_t& aChildID,
+                                             uint32_t* aChildIdx)
+{
+  *aChildIdx = 0;
+
+  Accessible* parent = IdToAccessible(aID);
+  Accessible* child = IdToAccessible(aChildID);
+  if (!parent || !child)
+    return true;
+
+  *aChildIdx = parent->GetIndexOfEmbeddedChild(child);
+  return true;
+}
+
+bool
 DocAccessibleChild::RecvChildAtPoint(const uint64_t& aID,
                                      const int32_t& aX,
                                      const int32_t& aY,
                                      const uint32_t& aWhich,
                                      uint64_t* aChild,
                                      bool* aOk)
 {
   *aChild = 0;
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -388,16 +388,20 @@ public:
   virtual bool RecvMaxValue(const uint64_t& aID,
                             double* aValue) override;
 
   virtual bool RecvStep(const uint64_t& aID,
                         double* aStep) override;
 
   virtual bool RecvTakeFocus(const uint64_t& aID) override;
 
+  virtual bool RecvIndexOfEmbeddedChild(const uint64_t& aID,
+                                        const uint64_t& aChildID,
+                                        uint32_t* aChildIdx) override final;
+
   virtual bool RecvChildAtPoint(const uint64_t& aID,
                                 const int32_t& aX,
                                 const int32_t& aY,
                                 const uint32_t& aWhich,
                                 uint64_t* aChild,
                                 bool* aOk) override;
 
   virtual bool RecvBounds(const uint64_t& aID, nsIntRect* aRect) override;
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -206,16 +206,18 @@ child:
 
   prio(high) sync CurValue(uint64_t aID) returns(double aValue);
   prio(high) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal);
   prio(high) sync MinValue(uint64_t aID) returns(double aValue);
   prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
   prio(high) sync Step(uint64_t aID) returns(double aStep);
 
   prio(high) sync TakeFocus(uint64_t aID);
+  prio(high) sync IndexOfEmbeddedChild(uint64_t aID, uint64_t aChildID)
+    returns(uint32_t childIdx);
   prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
     returns(uint64_t aChild, bool aOk);
   prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);
 
   prio(high) sync Language(uint64_t aID) returns(nsString aLocale);
   prio(high) sync DocType(uint64_t aID) returns(nsString aType);
   prio(high) sync URL(uint64_t aID) returns(nsString aURL);
   prio(high) sync MimeType(uint64_t aID) returns(nsString aMime);
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -898,16 +898,25 @@ ProxyAccessible::Step()
 }
 
 void
 ProxyAccessible::TakeFocus()
 {
   unused << mDoc->SendTakeFocus(mID);
 }
 
+int32_t
+ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
+{
+  uint64_t childID = aChild->mID;
+  uint32_t childIdx;
+  unused << mDoc->SendIndexOfEmbeddedChild(mID, childID, &childIdx);
+  return childIdx;
+}
+
 ProxyAccessible*
 ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
                               Accessible::EWhichChildAtPoint aWhichChild)
 {
   uint64_t childID = 0;
   bool ok = false;
   unused << mDoc->SendChildAtPoint(mID, aX, aY,
                                    static_cast<uint32_t>(aWhichChild),
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -42,16 +42,17 @@ public:
   void AddChildAt(uint32_t aIdx, ProxyAccessible* aChild)
   { mChildren.InsertElementAt(aIdx, aChild); }
 
   uint32_t ChildrenCount() const { return mChildren.Length(); }
   ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
 
   // XXX evaluate if this is fast enough.
   size_t IndexInParent() const { return mParent->mChildren.IndexOf(this); }
+  int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
   bool MustPruneChildren() const;
 
   void Shutdown();
 
   void SetChildDoc(DocAccessibleParent*);
 
   /**
    * Remove The given child.
@@ -315,14 +316,15 @@ private:
 enum Interfaces
 {
   HYPERTEXT = 1,
   HYPERLINK = 2,
   IMAGE = 4,
   VALUE = 8,
   TABLE = 16,
   TABLECELL = 32,
+  DOCUMENT = 64,
 };
 
 }
 }
 
 #endif
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -490,17 +490,17 @@ STDMETHODIMP
 ia2Accessible::get_uniqueID(long* aUniqueID)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aUniqueID)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
-  *aUniqueID = - reinterpret_cast<intptr_t>(acc->UniqueID());
+  *aUniqueID = AccessibleWrap::GetChildIDFor(acc);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_windowHandle(HWND* aWindowHandle)
 {
--- a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -45,16 +45,26 @@ ia2AccessibleHyperlink::get_anchor(long 
   A11Y_TRYBLOCK_BEGIN
 
   if (!aAnchor)
     return E_INVALIDARG;
 
   VariantInit(aAnchor);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+  if (thisObj->IsProxy()) {
+    ProxyAccessible* anchor = thisObj->Proxy()->AnchorAt(aIndex);
+    if (!anchor)
+      return S_FALSE;
+
+    aAnchor->punkVal = static_cast<IAccessibleHyperlink*>(WrapperFor(anchor));
+    aAnchor->vt = VT_UNKNOWN;
+    return S_OK;
+  }
+
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
     return E_INVALIDARG;
 
   if (!thisObj->IsLink())
     return S_FALSE;
@@ -83,42 +93,44 @@ ia2AccessibleHyperlink::get_anchorTarget
   A11Y_TRYBLOCK_BEGIN
 
   if (!aAnchorTarget)
     return E_INVALIDARG;
 
   VariantInit(aAnchorTarget);
 
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
-  if (thisObj->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  nsAutoCString uriStr;
+  if (thisObj->IsProxy()) {
+    bool ok;
+    thisObj->Proxy()->AnchorURIAt(aIndex, uriStr, &ok);
+    if (!ok)
+      return S_FALSE;
 
-  if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
-    return E_INVALIDARG;
-
-  if (!thisObj->IsLink())
-    return S_FALSE;
+  } else {
+    if (thisObj->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
-  if (!uri)
-    return S_FALSE;
+    if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
+      return E_INVALIDARG;
+
+    if (!thisObj->IsLink())
+      return S_FALSE;
 
-  nsAutoCString prePath;
-  nsresult rv = uri->GetPrePath(prePath);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+    nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
+    if (!uri)
+      return S_FALSE;
 
-  nsAutoCString path;
-  rv = uri->GetPath(path);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+    nsresult rv = uri->GetSpec(uriStr);
+    if (NS_FAILED(rv))
+      return GetHRESULT(rv);
+  }
 
   nsAutoString stringURI;
-  AppendUTF8toUTF16(prePath, stringURI);
-  AppendUTF8toUTF16(path, stringURI);
+  AppendUTF8toUTF16(uriStr, stringURI);
 
   aAnchorTarget->vt = VT_BSTR;
   aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
                                                stringURI.Length());
   return aAnchorTarget->bstrVal ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -128,16 +140,22 @@ ia2AccessibleHyperlink::get_startIndex(l
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aIndex)
     return E_INVALIDARG;
 
   *aIndex = 0;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    bool valid;
+    *aIndex = proxy->StartOffset(&valid);
+    return valid ? S_OK : S_FALSE;
+  }
+
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
   *aIndex = thisObj->StartOffset();
@@ -151,16 +169,22 @@ ia2AccessibleHyperlink::get_endIndex(lon
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aIndex)
     return E_INVALIDARG;
 
   *aIndex = 0;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    bool valid;
+    *aIndex = proxy->EndOffset(&valid);
+    return valid ? S_OK : S_FALSE;
+  }
+
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
   *aIndex = thisObj->EndOffset();
@@ -174,16 +198,21 @@ ia2AccessibleHyperlink::get_valid(boolea
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aValid)
     return E_INVALIDARG;
 
   *aValid = false;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aValid = proxy->IsLinkValid();
+    return S_OK;
+  }
+
   Accessible* thisObj = static_cast<AccessibleWrap*>(this);
   if (thisObj->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!thisObj->IsLink())
     return S_FALSE;
 
   *aValid = thisObj->IsLinkValid();
--- a/accessible/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
@@ -21,16 +21,21 @@ ia2AccessibleHypertext::get_nHyperlinks(
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlinkCount)
     return E_INVALIDARG;
 
   *aHyperlinkCount = 0;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aHyperlinkCount = proxy->LinkCount();
+    return S_OK;
+  }
+
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkCount = hyperText->LinkCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -42,42 +47,57 @@ ia2AccessibleHypertext::get_hyperlink(lo
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlink)
     return E_INVALIDARG;
 
   *aHyperlink = nullptr;
 
-  HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
-  if (hyperText->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  AccessibleWrap* hyperLink;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    ProxyAccessible* link = proxy->LinkAt(aLinkIndex);
+    if (!link)
+      return E_FAIL;
 
-  Accessible* hyperLink = hyperText->LinkAt(aLinkIndex);
+    hyperLink = WrapperFor(link);
+  } else {
+    HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
+    if (hyperText->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
+
+    hyperLink = static_cast<AccessibleWrap*>(hyperText->LinkAt(aLinkIndex));
+  }
+
   if (!hyperLink)
     return E_FAIL;
 
   *aHyperlink =
-    static_cast<IAccessibleHyperlink*>(static_cast<AccessibleWrap*>(hyperLink));
+    static_cast<IAccessibleHyperlink*>(hyperLink);
   (*aHyperlink)->AddRef();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aHyperlinkIndex)
     return E_INVALIDARG;
 
   *aHyperlinkIndex = 0;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aHyperlinkIndex = proxy->LinkIndexAtOffset(aCharIndex);
+    return S_OK;
+  }
+
   HyperTextAccessibleWrap* hyperAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aHyperlinkIndex = hyperAcc->LinkIndexAtOffset(aCharIndex);
   return S_OK;
 
   A11Y_TRYBLOCK_END
--- a/accessible/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/windows/ia2/ia2AccessibleValue.cpp
@@ -49,62 +49,77 @@ ia2AccessibleValue::get_currentValue(VAR
   A11Y_TRYBLOCK_BEGIN
 
   if (!aCurrentValue)
     return E_INVALIDARG;
 
   VariantInit(aCurrentValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
-  if (valueAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  double currentValue;
+  if (valueAcc->IsProxy()) {
+    currentValue = valueAcc->Proxy()->CurValue();
+  } else {
+    if (valueAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  double currentValue = valueAcc->CurValue();
+    currentValue = valueAcc->CurValue();
+  }
+
   if (IsNaN(currentValue))
     return S_FALSE;
 
   aCurrentValue->vt = VT_R8;
   aCurrentValue->dblVal = currentValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::setCurrentValue(VARIANT aValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (aValue.vt != VT_R8)
+    return E_INVALIDARG;
+
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+  if (valueAcc->IsProxy())
+    return valueAcc->Proxy()->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
+
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  if (aValue.vt != VT_R8)
-    return E_INVALIDARG;
-
   return valueAcc->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aMaximumValue)
     return E_INVALIDARG;
 
   VariantInit(aMaximumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
-  if (valueAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  double maximumValue;
+  if (valueAcc->IsProxy()) {
+    maximumValue = valueAcc->Proxy()->MaxValue();
+  } else {
+    if (valueAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  double maximumValue = valueAcc->MaxValue();
+    maximumValue = valueAcc->MaxValue();
+  }
+
   if (IsNaN(maximumValue))
     return S_FALSE;
 
   aMaximumValue->vt = VT_R8;
   aMaximumValue->dblVal = maximumValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -116,20 +131,26 @@ ia2AccessibleValue::get_minimumValue(VAR
   A11Y_TRYBLOCK_BEGIN
 
   if (!aMinimumValue)
     return E_INVALIDARG;
 
   VariantInit(aMinimumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
-  if (valueAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  double minimumValue;
+  if (valueAcc->IsProxy()) {
+    minimumValue = valueAcc->Proxy()->MinValue();
+  } else {
+    if (valueAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  double minimumValue = valueAcc->MinValue();
+    minimumValue = valueAcc->MinValue();
+  }
+
   if (IsNaN(minimumValue))
     return S_FALSE;
 
   aMinimumValue->vt = VT_R8;
   aMinimumValue->dblVal = minimumValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -51,26 +51,58 @@ const uint32_t USE_ROLE_STRING = 0;
  */
 
 //#define DEBUG_LEAKS
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
 #endif
 
+#ifdef _WIN64
+IDSet AccessibleWrap::sIDGen;
+
+static const uint32_t kNoID = 0;
+#endif
+
 static const int32_t kIEnumVariantDisconnected = -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
+AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
+  Accessible(aContent, aDoc)
+#ifdef _WIN64
+  , mID(kNoID)
+#endif
+{
+}
+
+AccessibleWrap::~AccessibleWrap()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    sIDGen.ReleaseID(mID);
+#endif
+}
 
 ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
 
 NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
 
+void
+AccessibleWrap::Shutdown()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    static_cast<DocAccessibleWrap*>(mDoc)->RemoveID(mID);
+#endif
+
+  Accessible::Shutdown();
+}
+
 //-----------------------------------------------------
 // IUnknown interface methods - see iunknown.h for documentation
 //-----------------------------------------------------
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
@@ -1249,20 +1281,33 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 
 int32_t
 AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
 
-  // Yes, this means we're only compatibible with 32 bit
-  // MSAA is only available for 32 bit windows, so it's okay
-  // XXX: bug 606080
-  return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
+#ifdef _WIN64
+  if (!aAccessible || !aAccessible->Document())
+    return 0;
+
+  uint32_t* id = & static_cast<AccessibleWrap*>(aAccessible)->mID;
+  if (*id != kNoID)
+    return *id;
+
+  *id = sIDGen.GetID();
+  DocAccessibleWrap* doc =
+    static_cast<DocAccessibleWrap*>(aAccessible->Document());
+  doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
+
+  return *id;
+#else
+  return - reinterpret_cast<intptr_t>(aAccessible);
+#endif
 }
 
 HWND
 AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
 {
   if (aAccessible) {
     DocAccessible* document = aAccessible->Document();
     if(!document)
@@ -1302,16 +1347,35 @@ AccessibleWrap::NativeAccessible(Accessi
     return nullptr;
   }
 
   IAccessible* msaaAccessible = nullptr;
   aAccessible->GetNativeInterface(reinterpret_cast<void**>(&msaaAccessible));
   return static_cast<IDispatch*>(msaaAccessible);
 }
 
+#ifdef _WIN64
+static Accessible*
+GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
+{
+  Accessible* child = static_cast<DocAccessibleWrap*>(aDoc)->GetAccessibleByID(aID);
+  if (child)
+    return child;
+
+  uint32_t childDocCount = aDoc->ChildDocumentCount();
+  for (uint32_t i = 0; i < childDocCount; i++) {
+    child = GetAccessibleInSubtree(aDoc->GetChildDocumentAt(i), aID);
+    if (child)
+      return child;
+  }
+
+    return nullptr;
+  }
+#endif
+
 Accessible*
 AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
 {
   if (aVarChild.vt != VT_I4)
     return nullptr;
 
   // if its us real easy - this seems to always be the case
   if (aVarChild.lVal == CHILDID_SELF)
@@ -1337,17 +1401,21 @@ AccessibleWrap::GetXPAccessibleFor(const
   // Otherwise we treat lVal as index in parent.
 
   if (aVarChild.lVal < 0) {
     // Convert child ID to unique ID.
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
 
     DocAccessible* document = Document();
     Accessible* child =
+#ifdef _WIN64
+    GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
+#else
       document->GetAccessibleByUniqueIDInSubtree(uniqueID);
+#endif
 
     // If it is a document then just return an accessible.
     if (IsDoc())
       return child;
 
     // Otherwise check whether the accessible is a child (this path works for
     // ARIA documents and popups).
     Accessible* parent = child;
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -10,16 +10,17 @@
 #include "nsCOMPtr.h"
 #include "Accessible.h"
 #include "Accessible2.h"
 #include "ia2Accessible.h"
 #include "ia2AccessibleComponent.h"
 #include "ia2AccessibleHyperlink.h"
 #include "ia2AccessibleValue.h"
 #include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/a11y/IDSet.h"
 
 #ifdef __GNUC__
 // Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
 // about virtual functions being hidden by each other. This is done by
 // design, so silence the warning.
 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
 #endif
 
@@ -28,18 +29,17 @@ namespace a11y {
 
 class AccessibleWrap : public Accessible,
                        public ia2Accessible,
                        public ia2AccessibleComponent,
                        public ia2AccessibleHyperlink,
                        public ia2AccessibleValue
 {
 public: // construction, destruction
-  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
-    Accessible(aContent, aDoc) { }
+  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   public: // IUnknown methods - see iunknown.h for documentation
     STDMETHODIMP QueryInterface(REFIID, void**);
 
   // Return the registered OLE class ID of this object's CfDataObj.
@@ -147,16 +147,17 @@ public: // construction, destruction
                                            LCID lcid, WORD wFlags,
                                            DISPPARAMS *pDispParams,
                                            VARIANT *pVarResult,
                                            EXCEPINFO *pExcepInfo,
                                            UINT *puArgErr);
 
   // Accessible
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
+  virtual void Shutdown() override;
 
   // Helper methods
   static int32_t GetChildIDFor(Accessible* aAccessible);
   static HWND GetHWNDFor(Accessible* aAccessible);
 
   /**
    * System caret support: update the Windows caret position. 
    * The system caret works more universally than the MSAA caret
@@ -171,25 +172,32 @@ public: // construction, destruction
    */
   Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
 
   virtual void GetNativeInterface(void **aOutAccessible) override;
 
   static IDispatch* NativeAccessible(Accessible* aAccessible);
 
 protected:
-  virtual ~AccessibleWrap() { }
+  virtual ~AccessibleWrap();
+
+#ifdef _WIN64
+  uint32_t mID;
+#endif
 
   /**
    * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.
    */
   static ITypeInfo* GetTI(LCID lcid);
 
   static ITypeInfo* gTypeInfo;
 
+#ifdef _WIN64
+  static IDSet sIDGen;
+#endif
 
   enum navRelations {
     NAVRELATION_CONTROLLED_BY = 0x1000,
     NAVRELATION_CONTROLLER_FOR = 0x1001,
     NAVRELATION_LABEL_FOR = 0x1002,
     NAVRELATION_LABELLED_BY = 0x1003,
     NAVRELATION_MEMBER_OF = 0x1004,
     NAVRELATION_NODE_CHILD_OF = 0x1005,
--- a/accessible/windows/msaa/DocAccessibleWrap.h
+++ b/accessible/windows/msaa/DocAccessibleWrap.h
@@ -29,20 +29,38 @@ public:
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
   // Accessible
   virtual void Shutdown();
 
   // DocAccessible
   virtual void* GetNativeWindow() const;
 
+  /**
+   * Manage the mapping from id to Accessible.
+   */
+#ifdef _WIN64
+  void AddID(uint32_t aID, AccessibleWrap* aAcc)
+    { mIDToAccessibleMap.Put(aID, aAcc); }
+  void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
+  AccessibleWrap* GetAccessibleByID(uint32_t aID) const
+    { return mIDToAccessibleMap.Get(aID); }
+#endif
+
 protected:
   // DocAccessible
   virtual void DoInitialUpdate();
 
 protected:
   void* mHWND;
+
+  /*
+   * This provides a mapping from 32 bit id to accessible objects.
+   */
+#ifdef _WIN64
+  nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
+#endif
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/IDSet.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * A class to generate unique IDs in the range [ - 2^31, 0 )
+ */
+
+#ifndef MOZILLA_A11Y_IDSet_h_
+#define MOZILLA_A11Y_IDSet_h_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/SplayTree.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * On windows an accessible's id must be a negative 32 bit integer.  It is
+ * important to support recycling arbitrary IDs because accessibles can be
+ * created and destroyed at any time in the life of a page.  IDSet provides 2
+ * operations: generate an ID in the range [ - 2^31, 0 ), and release an ID so
+ * it can be allocated again.  Allocated ID are tracked by a sparse bitmap
+ * implemented with a splay tree.  Nodes in the tree are keyed by the upper N
+ * bits of the bitwise negation of the ID, and the node contains a bitmap
+ * tracking the allocation of 2^(32 - N) IDs.
+ */
+class IDSet
+{
+public:
+  MOZ_CONSTEXPR IDSet() : mBitSet(), mIdx(0) {}
+
+  /**
+   * Return a new unique id.
+   */
+  uint32_t GetID()
+  {
+    uint32_t idx = mIdx;
+    while (true) {
+      BitSetElt* elt = mBitSet.findOrInsert(BitSetElt(idx));
+      if (elt->mBitvec[0] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[0]);
+
+        elt->mBitvec[0] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + i);
+      }
+
+      if (elt->mBitvec[1] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[1]);
+
+        elt->mBitvec[1] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + bitsPerWord + i);
+      }
+
+      idx++;
+      if (idx > sMaxIdx) {
+        idx = 0;
+      }
+
+      if (idx == mIdx) {
+        MOZ_CRASH("used up all the available ids");
+      }
+    }
+  }
+
+  /**
+   * Free a no longer required id so it may be allocated again.
+   */
+  void ReleaseID(uint32_t aID)
+  {
+    aID = ~aID;
+    MOZ_ASSERT(aID < static_cast<uint32_t>(INT32_MAX));
+
+    uint32_t idx = aID / bitsPerElt;
+    mIdx = idx;
+    BitSetElt* elt = mBitSet.find(BitSetElt(idx));
+    MOZ_ASSERT(elt);
+
+    uint32_t vecIdx = (aID % bitsPerElt) / bitsPerWord;
+    elt->mBitvec[vecIdx] &= ~(1ull << (aID % bitsPerWord));
+    if (elt->mBitvec[0] == 0 && elt->mBitvec[1] == 0) {
+      delete mBitSet.remove(*elt);
+    }
+  }
+
+private:
+  static const unsigned int wordsPerElt = 2;
+  static const unsigned int bitsPerWord = 64;
+  static const unsigned int bitsPerElt = wordsPerElt * bitsPerWord;
+  static const uint32_t sMaxIdx = INT32_MAX / bitsPerElt;
+
+  struct BitSetElt : mozilla::SplayTreeNode<BitSetElt>
+  {
+    explicit BitSetElt(uint32_t aIdx) :
+      mIdx(aIdx)
+    { mBitvec[0] = mBitvec[1] = 0; }
+
+    uint64_t mBitvec[wordsPerElt];
+    uint32_t mIdx;
+
+    static int compare(const BitSetElt& a, const BitSetElt& b)
+    {
+      if (a.mIdx == b.mIdx) {
+        return 0;
+      }
+
+      if (a.mIdx < b.mIdx) {
+        return -1;
+      }
+      return 1;
+    }
+  };
+
+  SplayTree<BitSetElt, BitSetElt> mBitSet;
+  uint32_t mIdx;
+};
+
+}
+}
+
+#endif
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -7,16 +7,17 @@
 EXPORTS += [
     'IUnknownImpl.h',
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'Compatibility.h',
     'HyperTextAccessibleWrap.h',
+    'IDSet.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -24,26 +24,18 @@ EXTRA_JS_MODULES.sdk.system += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk":
     EXTRA_JS_MODULES.commonjs.method.test += [
         'source/lib/method/test/browser.js',
         'source/lib/method/test/common.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.deprecated += [
         'source/lib/sdk/deprecated/api-utils.js',
-        'source/lib/sdk/deprecated/cortex.js',
-        'source/lib/sdk/deprecated/errors.js',
-        'source/lib/sdk/deprecated/events.js',
-        'source/lib/sdk/deprecated/light-traits.js',
-        'source/lib/sdk/deprecated/list.js',
         'source/lib/sdk/deprecated/memory.js',
-        'source/lib/sdk/deprecated/symbiont.js',
         'source/lib/sdk/deprecated/sync-worker.js',
-        'source/lib/sdk/deprecated/traits-worker.js',
-        'source/lib/sdk/deprecated/traits.js',
         'source/lib/sdk/deprecated/unit-test-finder.js',
         'source/lib/sdk/deprecated/unit-test.js',
         'source/lib/sdk/deprecated/window-utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.frame += [
         'source/lib/sdk/frame/hidden-frame.js',
         'source/lib/sdk/frame/utils.js',
@@ -86,17 +78,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
     EXTRA_JS_MODULES.commonjs.sdk.test += [
         'source/lib/sdk/test/assert.js',
         'source/lib/sdk/test/harness.js',
         'source/lib/sdk/test/httpd.js',
         'source/lib/sdk/test/loader.js',
         'source/lib/sdk/test/memory.js',
         'source/lib/sdk/test/options.js',
         'source/lib/sdk/test/runner.js',
-        'source/lib/sdk/test/tmp-file.js',
         'source/lib/sdk/test/utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.ui += [
         'source/lib/sdk/ui/component.js',
         'source/lib/sdk/ui/frame.js',
         'source/lib/sdk/ui/id.js',
         'source/lib/sdk/ui/sidebar.js',
@@ -123,22 +114,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
         'source/lib/sdk/window/browser.js',
         'source/lib/sdk/window/events.js',
         'source/lib/sdk/window/helpers.js',
         'source/lib/sdk/window/namespace.js',
         'source/lib/sdk/window/utils.js',
     ]
 
     EXTRA_JS_MODULES.commonjs.sdk.windows += [
-        'source/lib/sdk/windows/dom.js',
         'source/lib/sdk/windows/fennec.js',
         'source/lib/sdk/windows/firefox.js',
         'source/lib/sdk/windows/observer.js',
         'source/lib/sdk/windows/tabs-fennec.js',
-        'source/lib/sdk/windows/tabs-firefox.js',
     ]
 
 EXTRA_JS_MODULES.commonjs += [
     'source/lib/index.js',
     'source/lib/test.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.dev += [
@@ -178,20 +167,32 @@ EXTRA_JS_MODULES.commonjs.diffpatcher.te
 EXTRA_JS_MODULES.commonjs.framescript += [
     'source/lib/framescript/content.jsm',
     'source/lib/framescript/context-menu.js',
     'source/lib/framescript/FrameScriptManager.jsm',
     'source/lib/framescript/manager.js',
     'source/lib/framescript/util.js',
 ]
 
+EXTRA_JS_MODULES.commonjs['jetpack-id'] += [
+    'source/lib/jetpack-id/index.js',
+]
+
 EXTRA_JS_MODULES.commonjs.method += [
     'source/lib/method/core.js',
 ]
 
+EXTRA_JS_MODULES.commonjs['mozilla-toolkit-versioning'] += [
+    'source/lib/mozilla-toolkit-versioning/index.js',
+]
+
+EXTRA_JS_MODULES.commonjs['mozilla-toolkit-versioning'].lib += [
+    'source/lib/mozilla-toolkit-versioning/lib/utils.js',
+]
+
 EXTRA_JS_MODULES.commonjs.node += [
     'source/lib/node/os.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk += [
     'source/lib/sdk/base64.js',
     'source/lib/sdk/clipboard.js',
     'source/lib/sdk/context-menu.js',
@@ -213,17 +214,16 @@ EXTRA_JS_MODULES.commonjs.sdk += [
     'source/lib/sdk/simple-prefs.js',
     'source/lib/sdk/simple-storage.js',
     'source/lib/sdk/system.js',
     'source/lib/sdk/tabs.js',
     'source/lib/sdk/test.js',
     'source/lib/sdk/timers.js',
     'source/lib/sdk/ui.js',
     'source/lib/sdk/url.js',
-    'source/lib/sdk/widget.js',
     'source/lib/sdk/windows.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.addon += [
     'source/lib/sdk/addon/bootstrap.js',
     'source/lib/sdk/addon/events.js',
     'source/lib/sdk/addon/host.js',
     'source/lib/sdk/addon/installer.js',
@@ -272,20 +272,16 @@ EXTRA_JS_MODULES.commonjs.sdk.core += [
     'source/lib/sdk/core/promise.js',
     'source/lib/sdk/core/reference.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.deprecated.events += [
     'source/lib/sdk/deprecated/events/assembler.js',
 ]
 
-EXTRA_JS_MODULES.commonjs.sdk.deprecated.traits += [
-    'source/lib/sdk/deprecated/traits/core.js',
-]
-
 EXTRA_JS_MODULES.commonjs.sdk.dom += [
     'source/lib/sdk/dom/events.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.dom.events += [
     'source/lib/sdk/dom/events/keys.js',
 ]
 
@@ -301,17 +297,16 @@ EXTRA_JS_MODULES.commonjs.sdk.fs += [
     'source/lib/sdk/fs/path.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.input += [
     'source/lib/sdk/input/browser.js',
     'source/lib/sdk/input/customizable-ui.js',
     'source/lib/sdk/input/frame.js',
     'source/lib/sdk/input/system.js',
-    'source/lib/sdk/input/window.js',
 ]
 
 EXTRA_JS_MODULES.commonjs.sdk.io += [
     'source/lib/sdk/io/buffer.js',
     'source/lib/sdk/io/byte-streams.js',
     'source/lib/sdk/io/data.js',
     'source/lib/sdk/io/file.js',
     'source/lib/sdk/io/fs.js',
--- a/addon-sdk/source/.gitignore
+++ b/addon-sdk/source/.gitignore
@@ -4,17 +4,33 @@ testdocs.tgz
 jetpack-sdk-docs.tgz
 .test_tmp/
 doc/dev-guide/
 doc/index.html
 doc/modules/
 doc/status.md5
 packages/*
 node_modules
+cache
 
 # Python
 *.pyc
 
 # OSX
 *.DS_Store
 
 # Windows
 *Thumbs.db
+
+# Ignore subtrees
+
+# git@github.com:jsantell/jetpack-id.git
+lib/jetpack-id/*
+!lib/jetpack-id/index.js
+!lib/jetpack-id/package.json
+
+# git@github.com:jsantell/mozilla-toolkit-versioning.git
+lib/mozilla-toolkit-versioning/*
+!lib/mozilla-toolkit-versioning/index.js
+!lib/mozilla-toolkit-versioning/lib
+lib/mozilla-toolkit-versioning/lib/*
+!lib/mozilla-toolkit-versioning/lib/*.js
+!lib/mozilla-toolkit-versioning/package.json
--- a/addon-sdk/source/.jpmignore
+++ b/addon-sdk/source/.jpmignore
@@ -3,15 +3,16 @@ mapping.json
 CONTRIBUTING.md
 @addon-sdk.xpi
 .*
 app-extension/
 bin/
 modules/
 node_modules/
 examples/
+cache/
 
 # Python
 python-lib/
 *.pyc
 
 # Windows
 *Thumbs.db
--- a/addon-sdk/source/.travis.yml
+++ b/addon-sdk/source/.travis.yml
@@ -1,24 +1,26 @@
 sudo: false
 language: node_js
 node_js:
-  - "iojs"
   - "0.10"
 
+env:
+  - JPM_FX_DEBUG=0
+  - JPM_FX_DEBUG=1
+
 notifications:
   irc: "irc.mozilla.org#jetpack"
 
+cache:
+  directories:
+  - cache
+
 before_install:
   - "export DISPLAY=:99.0"
-  - "sh -e /etc/init.d/xvfb start"
   - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR"
 
 before_script:
-  - npm install mozilla-download -g
-  - npm install jpm -g
-  - cd ..
-  - mozilla-download --branch nightly -c prerelease --host ftp.mozilla.org firefox
+  - npm install fx-download -g
+  - npm install gulp -g
+  - bash bin/fx-download.sh
   - export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox
   - cd $TRAVIS_BUILD_DIR
-
-script:
-  - npm test
--- a/addon-sdk/source/CONTRIBUTING.md
+++ b/addon-sdk/source/CONTRIBUTING.md
@@ -1,43 +1,43 @@
 ##  Overview
 
 - Changes should follow the [design guidelines], as well as the [coding style guide]
-- All changes must be accompanied by tests
-- In order to land, changes must have been reviewed by one of the Jetpack reviewers
-- Changes should have additional API review when needed
-- Changes should have additional review from a Mozilla platform domain-expert when needed
+- All changes need tests
+- In order to land, changes need a review by one of the Jetpack reviewers
+- Changes may need an API review
+- Changes may need a review from a Mozilla platform domain-expert
 
 If you have questions, ask in [#jetpack on IRC][jetpack irc channel] or on the [Jetpack mailing list].
 
 ## How to Make Code Contributions
 
-If you'd like to contribute the Jetpack project, follow these steps:
+To write code for the Jetpack project, follow these steps:
 
-1. Look for your issue in the list of [bugs already filed][open bugs]. If you want to contribute, but don't already know what you want to do, we keep a list of [good first bugs].
-2. If no bug exists, [submit one][submit bug].
+1. Look for your issue in the list of [bugs already filed][open bugs]. If you don't already know what you want to do, we keep a list of [good first bugs].
+2. If no bug exists, [make one][make bug].
 3. Get the code: get a [GitHub][GitHub] account, fork the [Add-on SDK repo][Add-on SDK repo], and clone it to your machine.
 4. Make your changes. Changes should follow the [design guidelines] as well as the [coding style guide].
 5. Write tests: [unit testing introduction][test intro], [unit testing API][test API].
 6. Submit a pull request with the changes and a title in the form of `Bug XXX - description`.
 7. Make sure that [Travis CI](https://travis-ci.org/mozilla/addon-sdk/branches) tests are passing for your branch.
 8. Copy the pull request link from GitHub and paste it in as an attachment to the bug.
 9. Each pull request should ideally contain only one commit, so squash the commits if necessary.
 10. Flag the attachment for code review from one of the Jetpack reviewers listed below. This step is optional, but could speed things up.
 11. Address any issues mentioned in the review.
 
-Finally, once review is approved, a team member will do the merging
+Finally, once the review is positive, a team member will do the merging
 
 ## Good First Bugs
 
 There is a list of [good first bugs here][good first bugs].
 
 ## Reviewers
 
-All changes must be reviewed by someone on the Jetpack review crew:
+All changes need a review by someone on the Jetpack review crew:
 
 - [@mossop]
 - [@gozala]
 - [@ZER0]
 - [@erikvold]
 - [@jsantell]
 - [@zombie]
 
@@ -45,17 +45,17 @@ For review of Mozilla platform usage and
 [@0c0w3], or [@mossop] to find the domain expert.
 
 For API and developer ergonomics review, ask [@gozala].
 
 [design guidelines]:https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines
 [jetpack irc channel]:irc://irc.mozilla.org/#jetpack
 [Jetpack mailing list]:http://groups.google.com/group/mozilla-labs-jetpack
 [open bugs]:https://bugzilla.mozilla.org/buglist.cgi?quicksearch=product%3ASDK
-[submit bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general
+[make bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general
 [test intro]:https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing
 [test API]:https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert
 [coding style guide]:https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
 [Add-on SDK repo]:https://github.com/mozilla/addon-sdk
 [GitHub]:https://github.com/
 [good first bugs]:https://bugzilla.mozilla.org/buglist.cgi?list_id=7345714&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&query_based_on=jetpack-good-1st-bugs&status_whiteboard_type=allwordssubstr&query_format=advanced&status_whiteboard=[good%20first%20bug]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&product=Add-on%20SDK&known_name=jetpack-good-1st-bugs
 
 [@mossop]:https://github.com/mossop/
--- a/addon-sdk/source/README.md
+++ b/addon-sdk/source/README.md
@@ -1,31 +1,32 @@
 # Mozilla Add-on SDK [![Build Status](https://travis-ci.org/mozilla/addon-sdk.png)](https://travis-ci.org/mozilla/addon-sdk)
 
 Using the Add-on SDK you can create Firefox add-ons using standard Web technologies: JavaScript, HTML, and CSS. The SDK includes JavaScript APIs which you can use to create add-ons, and tools for creating, running, testing, and packaging add-ons.
 
 If you find a problem, please [report the bug here](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK).
 
 ## Developing Add-ons
 
-These resources should provide some help:
+These resources offer some help:
 
 * [Add-on SDK Documentation](https://developer.mozilla.org/en-US/Add-ons/SDK)
 * [Community Developed Modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules)
 * [Jetpack FAQ](https://wiki.mozilla.org/Jetpack/FAQ)
 * [StackOverflow Questions](http://stackoverflow.com/questions/tagged/firefox-addon-sdk)
 * [Mailing List](https://wiki.mozilla.org/Jetpack#Mailing_list)
 * #jetpack on irc.mozilla.org
 
 ## Contributing Code
 
-Please read these two guides if you wish to contribute some patches to the addon-sdk:
+Please read these two guides if you wish to make some patches to the addon-sdk:
 
 * [Contribute Guide](https://github.com/mozilla/addon-sdk/blob/master/CONTRIBUTING.md)
 * [Style Guide](https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide)
 
 ## Issues
 
 We use [bugzilla](https://bugzilla.mozilla.org/) as our issue tracker, here are some useful links:
 
 * [File a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK)
 * [Open bugs](https://bugzilla.mozilla.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&product=Add-on%20SDK&query_format=advanced&order=priority)
 * [Good first bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+first+bug]&&resolution=---&product=Add-on+SDK)
+* [Good next bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+next+bug]&&resolution=---&product=Add-on+SDK)
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/fx-download.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ "$JPM_FX_DEBUG" = "1" ]; then
+  fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox --debug
+else
+  fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox
+fi
old mode 100644
new mode 100755
--- a/addon-sdk/source/bin/jpm-test.js
+++ b/addon-sdk/source/bin/jpm-test.js
@@ -6,23 +6,27 @@
 var Promise = require("promise");
 var Mocha = require("mocha");
 var mocha = new Mocha({
   ui: "bdd",
   reporter: "spec",
   timeout: 900000
 });
 
+var isDebug = require("./node-scripts/utils").isDebug;
+
 exports.run = function(type) {
   return new Promise(function(resolve) {
     type = type || "";
     [
-      (/^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
-      (/^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
+      (!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
+      (!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
       (/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
+      (!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"),
+      (!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"),
     ].sort().forEach(function(filepath) {
       filepath && mocha.addFile(filepath);
     })
 
     mocha.run(function(failures) {
       resolve(failures);
     });
   });
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/apply-patch.js
@@ -0,0 +1,64 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var path = require("path");
+var cp = require("child_process");
+var fs = require("fs");
+var Promise = require("promise");
+var patcher = require("patch-editor");
+var readParam = require("./utils").readParam;
+
+var isKeeper = /\/addon-sdk\/source/;
+
+function apply(options) {
+  return clean(options).then(function() {
+    return new Promise(function(resolve) {
+      var patch = path.resolve(readParam("patch"));
+      var proc = cp.spawn("git", ["apply", patch]);
+      proc.stdout.pipe(process.stdout);
+      proc.stderr.pipe(process.stderr);
+      proc.on("close", resolve);
+    });
+  });
+}
+exports.apply = apply;
+
+function clean(options) {
+  return new Promise(function(resolve) {
+    var patch = path.resolve(readParam("patch"));
+    if (!patch) {
+      throw new Error("no --patch was provided.");
+    }
+    console.log("Cleaning patch " + patch);
+
+    patcher.getChunks({ patch: patch }).then(function(chunks) {
+      var keepers = [];
+
+      for (var i = chunks.length - 1; i >= 0; i--) {
+        var chunk = chunks[i];
+        var files = chunk.getFilesChanged();
+
+        // check if the file changed is related to the addon-sdk/source directory
+        var keepIt = files.map(function(file) {
+          return (isKeeper.test(file));
+        }).reduce(function(prev, curr) {
+          return prev || curr;
+        }, false);
+
+        if (keepIt) {
+          keepers.push(chunk);
+        }
+      }
+
+      var contents = "\n" + keepers.join("\n") + "\n";
+      contents = contents.replace(/\/addon-sdk\/source/g, "");
+
+      fs.writeFileSync(patch, contents, { encoding: "utf8" });
+
+      console.log("Done cleaning patch.");
+    }).then(resolve).catch(console.error);
+  });
+}
+exports.clean = clean;
--- a/addon-sdk/source/bin/node-scripts/test.addons.js
+++ b/addon-sdk/source/bin/node-scripts/test.addons.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var utils = require("./utils");
 var path = require("path");
 var fs = require("fs");
 var jpm = utils.run;
 var readParam = utils.readParam;
+var isDebug = utils.isDebug;
 
 var addonsPath = path.join(__dirname, "..", "..", "test", "addons");
 
 var binary = process.env.JPM_FIREFOX_BINARY || "nightly";
 var filterPattern = readParam("filter");
 
 describe("jpm test sdk addons", function () {
   fs.readdirSync(addonsPath)
@@ -35,14 +36,22 @@ describe("jpm test sdk addons", function
   });
 });
 
 function fileFilter(root, file) {
   var matcher = filterPattern && new RegExp(filterPattern);
   if (/^(l10n-properties|simple-prefs|page-mod-debugger)/.test(file)) {
     return false;
   }
+
+  // filter additional add-ons when using debug builds
+  if (isDebug) {
+    if (/^(chrome|e10s)/.test(file)) {
+      return false;
+    }
+  }
+
   if (matcher && !matcher.test(file)) {
     return false;
   }
   var stat = fs.statSync(path.join(root, file))
   return (stat && stat.isDirectory());
 }
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/test.docs.js
@@ -0,0 +1,145 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var createHash = require('crypto').createHash;
+var fs = require("fs");
+var fsExtra = require("fs-extra")
+var path = require("path");
+var Promise = require("promise");
+var chai = require("chai");
+var expect = chai.expect;
+var teacher = require("teacher");
+
+var rootURI = path.join(__dirname, "..", "..");
+
+// get a list of words that fail spell check but are still acceptable
+var NEW_WORDS = fs.readFileSync(path.join(__dirname, "words.txt")).toString().trim().split("\n");
+
+var CACHE_PATH = path.join(__dirname, "..", "..", "cache", "spellchecks.json");
+
+var CACHE = {};
+
+try {
+  CACHE = JSON.parse(fs.readFileSync(CACHE_PATH).toString());
+}
+catch (e) {}
+
+function md5(str) {
+  return createHash("md5").update(str).digest("utf8");
+}
+
+function addCacheHash(hash) {
+  CACHE[hash] = true;
+  fsExtra.ensureFileSync(CACHE_PATH);
+  fsExtra.writeJSONSync(CACHE_PATH, CACHE);
+}
+
+describe("Spell Checking", function () {
+  it("Spellcheck CONTRIBUTING.md", function (done) {
+   var readme = path.join(rootURI, "CONTRIBUTING.md");
+
+    fs.readFile(readme, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var hash = md5(text);
+
+      // skip this test if we know we have done the
+      // exact same test with positive results before
+      if (CACHE[hash]) {
+        expect(CACHE[hash]).to.be.equal(true);
+        return done();
+      }
+
+      teacher.check(text, function(err, data) {
+        expect(err).to.be.equal(null);
+
+        var results = data || [];
+        results = results.filter(function(result) {
+          if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
+            return false;
+          }
+
+          // ignore anything that starts with a dash
+          if (result.string[0] == "-") {
+            return false;
+          }
+
+          if (!(new RegExp(result.string)).test(text)) {
+            return false;
+          }
+
+          return true;
+        })
+
+        if (results.length > 0) {
+          console.log(results);
+        }
+        else {
+          addCacheHash(hash);
+        }
+
+        expect(results.length).to.be.equal(0);
+
+        setTimeout(done, 500);
+      });
+    });
+  });
+
+  it("Spellcheck README.md", function (done) {
+   var readme = path.join(rootURI, "README.md");
+
+    fs.readFile(readme, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var hash = md5(text);
+
+      // skip this test if we know we have done the
+      // exact same test with positive results before
+      if (CACHE[hash]) {
+        expect(CACHE[hash]).to.be.equal(true);
+        return done();
+      }
+
+      teacher.check(text, function(err, data) {
+        expect(err).to.be.equal(null);
+
+        var results = data || [];
+        results = results.filter(function(result) {
+          if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) {
+            return false;
+          }
+
+          // ignore anything that starts with a dash
+          if (result.string[0] == "-") {
+            return false;
+          }
+
+          // ignore anything that we don't find in the original text,
+          // for some reason "bootstrap.js" becomes "bootstrapjs".
+          if (!(new RegExp(result.string)).test(text)) {
+            return false;
+          }
+
+          return true;
+        })
+
+        if (results.length > 0) {
+          console.log(results);
+        }
+        else {
+          addCacheHash(hash);
+        }
+
+        expect(results.length).to.be.equal(0);
+
+        done();
+      });
+    });
+  });
+});
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/test.ini.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var fs = require("fs");
+var path = require("path");
+var Promise = require("promise");
+var chai = require("chai");
+var expect = chai.expect;
+var ini = require("./update-ini");
+
+var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
+
+describe("Checking ini files", function () {
+
+  it("Check test/addons/jetpack-addon.ini", function (done) {
+
+    fs.readFile(addonINI, function (err, data) {
+      if (err) {
+        throw err;
+      }
+      var text = data.toString();
+      var expected = "";
+
+      ini.makeAddonIniContent()
+      .then(function(contents) {
+        expected = contents;
+
+        setTimeout(function end() {
+          expect(expected.trim()).to.be.equal(text.trim());
+          done();
+        });
+      });
+    });
+
+  });
+
+});
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/update-ini.js
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var path = require("path");
+var cp = require("child_process");
+var fs = require("fs");
+var Promise = require("promise");
+var parser = require("ini-parser");
+
+var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
+var addonsDir = path.resolve("./test/addons/");
+
+function updateAddonINI() {
+  return new Promise(function(resolve) {
+    console.log("Start updating " + addonINI);
+
+    makeAddonIniContent().
+    then(function(contents) {
+      fs.writeFileSync(addonINI, contents, { encoding: "utf8" });
+      console.log("Done updating " + addonINI);
+      resolve();
+    });
+  })
+}
+exports.updateAddonINI = updateAddonINI;
+
+function makeAddonIniContent() {
+  return new Promise(function(resolve) {
+    var data = parser.parse(fs.readFileSync(addonINI, { encoding: "utf8" }).toString());
+    var result = {};
+
+    fs.readdir(addonsDir, function(err, files) {
+      var folders = files.filter(function(file) {
+        return fs.statSync(path.resolve(addonsDir, file)).isDirectory();
+      }).sort();
+
+      folders.forEach(function(folder) {
+        var oldData = data[folder + ".xpi"];
+        result[folder] = oldData ? oldData : {};
+      });
+
+      // build ini file
+      var contents = [];
+      Object.keys(result).sort().forEach(function(key) {
+        contents.push("[" + key + ".xpi]");
+        Object.keys(result[key]).forEach(function(dataKey) {
+          contents.push(dataKey + " = " + result[key][dataKey]);
+        });
+      });
+      contents = contents.join("\n") + "\n";
+
+      return resolve(contents);
+    });
+  });
+}
+exports.makeAddonIniContent = makeAddonIniContent;
--- a/addon-sdk/source/bin/node-scripts/utils.js
+++ b/addon-sdk/source/bin/node-scripts/utils.js
@@ -12,53 +12,84 @@ var chai = require("chai");
 var expect = chai.expect;
 var assert = chai.assert;
 var DEFAULT_PROCESS = process;
 
 var sdk = path.join(__dirname, "..", "..");
 var prefsPath = path.join(sdk, "test", "preferences", "test-preferences.js");
 var e10sPrefsPath = path.join(sdk, "test", "preferences", "test-e10s-preferences.js");
 
+var OUTPUT_FILTERS = [
+  /[^\n\r]+WARNING\: NS_ENSURE_SUCCESS\(rv, rv\) failed[^\n]+\n\r?/
+];
+
+var isDebug = (process.env["JPM_FX_DEBUG"] == "1");
+exports.isDebug = isDebug;
+
 function spawn (cmd, options) {
   options = options || {};
   var env = _.extend({}, options.env, process.env);
+
+  if (isDebug) {
+    env["MOZ_QUIET"] = 1;
+  }
+
   var e10s = options.e10s || false;
 
   return child_process.spawn("node", [
-    jpm, cmd, "-v",
+    jpm, cmd, "-v", "--tbpl",
     "--prefs", e10s ? e10sPrefsPath : prefsPath,
     "-o", sdk,
     "-f", options.filter || ""
   ], {
     cwd: options.cwd || tmpOutputDir,
     env: env
   });
 }
 exports.spawn = spawn;
 
 function run (cmd, options, p) {
   return new Promise(function(resolve) {
     var output = [];
+
     var proc = spawn(cmd, options);
     proc.stderr.pipe(process.stderr);
     proc.stdout.on("data", function (data) {
+      for (var i = OUTPUT_FILTERS.length - 1; i >= 0; i--) {
+        if (OUTPUT_FILTERS[i].test(data)) {
+          return null;
+        }
+      }
       output.push(data);
+      return null;
     });
+
     if (p) {
       proc.stdout.pipe(p.stdout);
     }
+    else {
+      proc.stdout.on("data", function (data) {
+        data = (data || "") + "";
+        if (/TEST-/.test(data)) {
+          DEFAULT_PROCESS.stdout.write(data.replace(/[\s\n]+$/, "") + "\n");
+        }
+      });
+    }
+
     proc.on("close", function(code) {
       var out = output.join("");
+      var buildDisplayed = /Build \d+/.test(out);
       var noTests = /No tests were run/.test(out);
       var hasSuccess = /All tests passed!/.test(out);
       var hasFailure = /There were test failures\.\.\./.test(out);
       if (noTests || hasFailure || !hasSuccess || code != 0) {
         DEFAULT_PROCESS.stdout.write(out);
       }
       expect(code).to.equal(hasFailure ? 1 : 0);
+      expect(buildDisplayed).to.equal(true);
       expect(hasFailure).to.equal(false);
       expect(hasSuccess).to.equal(true);
       expect(noTests).to.equal(false);
       resolve();
     });
   });
 }
 exports.run = run;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/bin/node-scripts/words.txt
@@ -0,0 +1,12 @@
+addon-sdk
+github
+stackoverflow
+bugzilla
+irc
+erikvold
+jsantell
+mossop
+gozala
+zer0
+autonome
+0c0w3
--- a/addon-sdk/source/examples/actor-repl/package.json
+++ b/addon-sdk/source/examples/actor-repl/package.json
@@ -1,10 +1,10 @@
 {
   "name": "actor-repl",
   "id": "@actor-repl",
   "title": "Actor REPL",
   "description": "Actor REPL",
   "version": "0.0.1",
   "author": "Irakli Gozalishvili",
   "main": "./index.js",
-  "license": "MPL 2.0"
+  "license": "MPL-2.0"
 }
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-This add-on enables users to add notes, or annotations, to Web pages.
-
-Usage
------
-
-To switch the annotator on, left-click the pencil icon in the Add-on Bar. The
-icon should turn yellow: this indicates that the annotator is active. To switch
-it off, click it again. Switching it on/off only stops you from entering
-annotations: existing annotations are still displayed.
-
-When the annotator is active and the user moves the mouse over a page element
-that can be annotated, the annotator highlights that elements by giving it a
-yellow background.
-
-If the user clicks on a highlighted element the add-on opens a dialog for the
-user to enter the annotation. When the user hits <return> the annotation is
-saved.
-
-Elements which have been annotated are displayed with a yellow border: when the
-user moves the mouse over one of these elements, the add-on displays the
-annotation associated with that element.
-
-To view all annotations in a list, right-click the pencil icon.
-
-The add-on is deactivated in private browsing mode, meaning that new annotations
-can't be created although existing ones are still shown. On exiting private
-browsing the add-on returns to its previous activation state.
-
-Known Issues/Limitations
-------------------------
-
-It is not possible to delete annotations, or to edit them after creating them,
-but it would be simple to add this.
-
-When right-clicking the annotator icon the add-on bar's context-menu is shown:
-this is tracked by
-[bug 626326](https://bugzilla.mozilla.org/show_bug.cgi?id=626326).
-
-The list of annotations should be anchored to the widget. The annotation
-editor, and the annotation itself, should be anchored to the element which is
-annotated. The will be done when the implementation of panel-anchoring is
-extended.
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/annotation/annotation.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-    <title>Annotation</title>
-    <style type="text/css" media="all">
-
-body {
-        font: 100% arial, helvetica, sans-serif;
-    }
-
-div {
-        text-align:left;
-    }
-
-</style>
-
-</head>
-
-<body>
-
-<div id = "annotation">
-</div>
-
-</body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/annotation/annotation.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-Initialize annotation content.
-*/
-
-self.on('message', function(message) {
-  $('#annotation').text(message);
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/editor/annotation-editor.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-  <title>Annotation</title>
-  <style type="text/css" media="all">
-  body, html {
-    font: 100% arial, helvetica, sans-serif;
-    padding: 0;
-    margin: 0;
-    position: fixed;
-  }
-  textarea {
-    width: 100%;
-    height: 100%;
-    margin: 10px;
-    padding: 0;
-    color: inherit !important;
-    font: inherit !important;
-    background: transparent;
-    border: none;
-  }
-  </style>
-
-</head>
-
-<body>
-
-<textarea rows='10' cols='20' id='annotation-box'>
-</textarea>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/editor/annotation-editor.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-On a return key, send the content of the textArea back to the add-on,
-and zero the textArea for the next time.
-*/
-
-var textArea = document.getElementById('annotation-box');
-
-textArea.onkeyup = function(event) {
-  if (event.keyCode == 13) {
-    self.postMessage(textArea.value);
-    textArea.value = '';
-  }
-};
-
-self.on('message', function() {
-  var textArea = document.getElementById('annotation-box');
-  textArea.value = '';
-  textArea.focus();
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/jquery-1.4.2.min.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.4.2
- * http://jquery.com/
- *
- * Copyright 2010, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2010, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Sat Feb 13 22:33:48 2010 -0500
- */
-(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
-e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
-j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
-"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
-true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
-Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
-(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
-a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
-"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
-function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
-c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
-L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
-"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
-a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
-d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
-a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
-!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
-true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
-var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
-parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
-false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
-s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
-applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
-else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
-a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
-w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
-cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
-i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
-" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
-this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
-e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
-c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
-a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
-function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
-k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
-C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
-null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
-e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
-f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
-if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
-fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
-d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
-"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
-a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
-isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
-{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
-if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
-e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
-"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
-d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
-!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
-toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
-u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
-function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
-if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
-e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
-t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
-g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
-for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
-1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
-CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
-relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
-l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
-h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
-CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
-g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
-text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
-setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
-h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
-m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
-"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
-h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
-!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
-h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
-q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
-if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
-(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
-function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
-gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
-c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
-{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
-"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
-d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
-a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
-1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
-a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
-c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
-wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
-prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
-this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
-return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
-""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
-this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
-u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
-1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
-return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
-""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
-c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
-c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
-function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
-Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
-"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
-a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
-a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
-"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
-serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
-function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
-global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
-e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
-"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
-false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
-false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
-c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
-d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
-g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
-1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
-"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
-if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
-this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
-"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
-animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
-j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
-this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
-"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
-c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
-this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
-this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
-e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
-c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
-function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
-this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
-k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
-f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
-a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
-c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
-d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
-"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
-e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.css
+++ /dev/null
@@ -1,40 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#annotation-list .annotation-details
-  {
-  padding: 10px;
-  margin: 10px;
-  border: solid 3px #EEE;
-  background-color: white;
-  }
-
-#annotation-list .url, .selection-text, .annotation-text
-  {
-  padding: 5px;
-  margin: 5px;
-  }
-
-#annotation-list .selection-text,#annotation-list .annotation-text
-  {
-  border: solid 1px #EEE;
-  }
-
-#annotation-list .annotation-text
-  {
-  font-style: italic;
-  }
-
-body
-  {
-  background-color: #F5F5F5;
-  font: 100% arial, helvetica, sans-serif;
-  }
-
-h1
-  {
-  font-family: georgia,serif;
-  font-size: 1.5em;
-  text-align:center;
-  }
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Saved annotations</title>
-  <link rel="stylesheet" type="text/css" href="annotation-list.css" />
-</head>
-<body>
-
-<div id="annotation-list">
-</div>
-
-<div id="template">
-  <div class="annotation-details">
-    <a class="url"></a>
-    <div class="selection-text"></div>
-    <div class="annotation-text"></div>
-  </div>
-</div>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/list/annotation-list.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-Construct the HTML for the annotation list.
-
-Bind a function to click events on the link that send a message back to
-the add-on code, so it can open the link in the main browser.
-*/
-
-self.on("message", function onMessage(storedAnnotations) {
-  var annotationList = $('#annotation-list');
-  annotationList.empty();
-  storedAnnotations.forEach(
-    function(storedAnnotation) {
-      var annotationHtml = $('#template .annotation-details').clone();
-      annotationHtml.find('.url').text(storedAnnotation.url)
-                                 .attr('href', storedAnnotation.url);
-      annotationHtml.find('.url').bind('click', function(event) {
-        event.stopPropagation();
-        event.preventDefault();
-        self.postMessage(storedAnnotation.url);
-      });
-      annotationHtml.find('.selection-text')
-                    .text(storedAnnotation.anchorText);
-      annotationHtml.find('.annotation-text')
-                    .text(storedAnnotation.annotationText);
-      annotationList.append(annotationHtml);
-    });
-});
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/matcher.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-Locate anchors for annotations and prepare to display the annotations.
-
-For each annotation, if its URL matches this page,
-- get the ancestor whose ID matches the ID in the anchor
-- look for a <p> element whose content contains the anchor text
-
-That's considered a match. Then we:
-- highlight the anchor element
-- add an 'annotated' class to tell the selector to skip this element
-- embed the annottion text as a new attribute
-
-For all annotated elements:
-- bind 'mouseenter' and 'mouseleave' events to the element, to send 'show'
-  and 'hide' messages back to the add-on.
-*/
-
-self.on('message', function onMessage(annotations) {
-  annotations.forEach(
-    function(annotation) {
-      if(annotation.url == document.location.toString()) {
-        createAnchor(annotation);
-      }
-  });
-
-  $('.annotated').css('border', 'solid 3px yellow');
-
-  $('.annotated').bind('mouseenter', function(event) {
-    self.port.emit('show', $(this).attr('annotation'));
-    event.stopPropagation();
-    event.preventDefault();
-  });
-
-  $('.annotated').bind('mouseleave', function() {
-    self.port.emit('hide');
-  });
-});
-
-
-function createAnchor(annotation) {
-  annotationAnchorAncestor = $('#' + annotation.ancestorId)[0] || document.body;
-  annotationAnchor = $(annotationAnchorAncestor).parent().find(
-                     ':contains("' + annotation.anchorText + '")').last();
-  annotationAnchor.addClass('annotated');
-  annotationAnchor.attr('annotation', annotation.annotationText);
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/selector.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-The selector locates elements that are suitable for annotation and enables
-the user to select them.
-
-On 'mouseenter' events associated with <p> elements:
-- if the selector is active and the element is not already annotated
-- find the nearest ancestor which has an id attribute: this is supposed to
-make identification of this element more accurate
-- highlight the element
-- bind 'click' for the element to send a message back to the add-on, including
-all the information associated with the anchor.
-*/
-
-var matchedElement = null;
-var originalBgColor = null;
-var active = false;
-
-function resetMatchedElement() {
-  if (matchedElement) {
-    matchedElement.css('background-color', originalBgColor);
-    matchedElement.unbind('click.annotator');
-  }
-}
-
-self.on('message', function onMessage(activation) {
-  active = activation;
-  if (!active) {
-    resetMatchedElement();
-  }
-});
-
-function getInnerText(element) {
-  // jQuery.text() returns content of <script> tags, we need to ignore those
-  var list = [];
-  element.find("*").andSelf().contents()
-    .filter(function () {
-      return this.nodeType == 3 && this.parentNode.tagName != "SCRIPT";
-    })
-    .each(function () {
-      list.push(this.nodeValue);
-    });
-  return list.join("");
-}
-
-$('*').mouseenter(function() {
-  if (!active || $(this).hasClass('annotated')) {
-    return;
-  }
-  resetMatchedElement();
-  ancestor = $(this).closest("[id]");
-  matchedElement = $(this).first();
-  originalBgColor = matchedElement.css('background-color');
-  matchedElement.css('background-color', 'yellow');
-  matchedElement.bind('click.annotator', function(event) {
-    event.stopPropagation();
-    event.preventDefault();
-    self.port.emit('show',
-      [
-        document.location.toString(),
-        ancestor.attr("id"),
-        getInnerText(matchedElement)
-      ]
-   );
-  });
-});
-
-$('*').mouseout(function() {
-  resetMatchedElement();
-});
deleted file mode 100644
index b14d9619635af8d6bb04bae79ca74e67579c3fb0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 71a609f83ff1805acecc08fc5be4e4947ad407b9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/data/widget/widget.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-Listen for left and right click events and send the corresponding message
-to the content script.
-*/
-
-this.addEventListener('click', function(event) {
-  if(event.button == 0 && event.shiftKey == false)
-    self.port.emit('left-click');
-
-  if(event.button == 2 || (event.button == 0 && event.shiftKey == true))
-    self.port.emit('right-click');
-    event.preventDefault();
-}, true);
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/lib/main.js
+++ /dev/null
@@ -1,266 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var widgets = require('sdk/widget');
-var pageMod = require('sdk/page-mod');
-var data = require('sdk/self').data;
-var panels = require('sdk/panel');
-var simpleStorage = require('sdk/simple-storage');
-var notifications = require("sdk/notifications");
-
-/*
-Global variables
-* Boolean to indicate whether the add-on is switched on or not
-* Array for all workers associated with the 'selector' page mod
-* Array for all workers associated with the 'matcher' page mod
-*/
-var annotatorIsOn = false;
-var selectors = [];
-var matchers = [];
-
-if (!simpleStorage.storage.annotations)
-  simpleStorage.storage.annotations = [];
-
-/*
-Update the matchers: call this whenever the set of annotations changes
-*/
-function updateMatchers() {
-  matchers.forEach(function (matcher) {
-    matcher.postMessage(simpleStorage.storage.annotations);
-  });
-}
-
-/*
-Constructor for an Annotation object
-*/
-function Annotation(annotationText, anchor) {
-  this.annotationText = annotationText;
-  this.url = anchor[0];
-  this.ancestorId = anchor[1];
-  this.anchorText = anchor[2];
-}
-
-/*
-Function to deal with a new annotation.
-Create a new annotation object, store it, and
-notify all the annotators of the change.
-*/
-function handleNewAnnotation(annotationText, anchor) {
-  var newAnnotation = new Annotation(annotationText, anchor);
-  simpleStorage.storage.annotations.push(newAnnotation);
-  updateMatchers();
-}
-
-/*
-Function to tell the selector page mod that the add-on has become (in)active
-*/
-function activateSelectors() {
-  selectors.forEach(
-    function (selector) {
-      selector.postMessage(annotatorIsOn);
-  });
-}
-
-/*
-Toggle activation: update the on/off state and notify the selectors.
-*/
-function toggleActivation() {
-  annotatorIsOn = !annotatorIsOn;
-  activateSelectors();
-  return annotatorIsOn;
-}
-
-function detachWorker(worker, workerArray) {
-  var index = workerArray.indexOf(worker);
-  if(index != -1) {
-    workerArray.splice(index, 1);
-  }
-}
-
-exports.main = function() {
-
-/*
-The widget provides a mechanism to switch the selector on or off, and to
-view the list of annotations.
-
-The selector is switched on/off with a left-click, and the list of annotations
-is displayed on a right-click.
-*/
-  var widget = widgets.Widget({
-    id: 'toggle-switch',
-    label: 'Annotator',
-    contentURL: data.url('widget/pencil-off.png'),
-    contentScriptWhen: 'ready',
-    contentScriptFile: data.url('widget/widget.js')
-  });
-
-  widget.port.on('left-click', function() {
-    console.log('activate/deactivate');
-    widget.contentURL = toggleActivation() ?
-              data.url('widget/pencil-on.png') :
-              data.url('widget/pencil-off.png');
-  });
-
-  widget.port.on('right-click', function() {
-      console.log('show annotation list');
-      annotationList.show();
-  });
-
-/*
-The selector page-mod enables the user to select page elements to annotate.
-
-It is attached to all pages but only operates if the add-on is active.
-
-The content script highlights any page elements which can be annotated. If the
-user clicks a highlighted element it sends a message to the add-on containing
-information about the element clicked, which is called the anchor of the
-annotation.
-
-When we receive this message we assign the anchor to the annotationEditor and
-display it.
-*/
-  var selector = pageMod.PageMod({
-    include: ['*'],
-    contentScriptWhen: 'ready',
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('selector.js')],
-    onAttach: function(worker) {
-      worker.postMessage(annotatorIsOn);
-      selectors.push(worker);
-      worker.port.on('show', function(data) {
-        annotationEditor.annotationAnchor = data;
-        annotationEditor.show();
-      });
-      worker.on('detach', function () {
-        detachWorker(this, selectors);
-      });
-    }
-  });
-
-/*
-The annotationEditor panel is the UI component used for creating
-new annotations. It contains a text area for the user to
-enter the annotation.
-
-When we are ready to display the editor we assign its 'anchor' property
-and call its show() method.
-
-Its content script sends the content of the text area to the add-on
-when the user presses the return key.
-
-When we receives this message we create a new annotation using the anchor
-and the text the user entered, store it, and hide the panel.
-*/
-  var annotationEditor = panels.Panel({
-    width: 220,
-    height: 220,
-    contentURL: data.url('editor/annotation-editor.html'),
-    contentScriptFile: data.url('editor/annotation-editor.js'),
-    onMessage: function(annotationText) {
-      if (annotationText)
-        handleNewAnnotation(annotationText, this.annotationAnchor);
-      annotationEditor.hide();
-    },
-    onShow: function() {
-      this.postMessage('focus');
-    }
-  });
-
-/*
-The annotationList panel is the UI component that lists all the annotations
-the user has entered.
-
-On its 'show' event we pass it the array of annotations.
-
-The content script creates the HTML elements for the annotations, and
-intercepts clicks on the links, passing them back to the add-on to open them
-in the browser.
-*/
-  var annotationList = panels.Panel({
-    width: 420,
-    height: 200,
-    contentURL: data.url('list/annotation-list.html'),
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('list/annotation-list.js')],
-    contentScriptWhen: 'ready',
-    onShow: function() {
-      this.postMessage(simpleStorage.storage.annotations);
-    },
-    onMessage: function(message) {
-      require('sdk/tabs').open(message);
-    }
-  });
-
-/*
-We listen for the OverQuota event from simple-storage.
-If it fires we just notify the user and delete the most
-recent annotations until we are back in quota.
-*/
-  simpleStorage.on("OverQuota", function () {
-    notifications.notify({
-      title: 'Storage space exceeded',
-      text: 'Removing recent annotations'});
-    while (simpleStorage.quotaUsage > 1)
-      simpleStorage.storage.annotations.pop();
-  });
-
-/*
-The matcher page-mod locates anchors on web pages and prepares for the
-annotation to be displayed.
-
-It is attached to all pages, and when it is attached we pass it the complete
-list of annotations. It looks for anchors in its page. If it finds one it
-highlights the anchor and binds mouseenter/mouseout events to 'show' and 'hide'
-messages to the add-on.
-
-When the add-on receives the 'show' message it assigns the annotation text to
-the annotation panel and shows it.
-
-Note that the matcher is active whether or not the add-on is active:
-'inactive' only means that the user can't create new add-ons, they can still
-see old ones.
-*/
-  var matcher = pageMod.PageMod({
-    include: ['*'],
-    contentScriptWhen: 'ready',
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('matcher.js')],
-    onAttach: function(worker) {
-      if(simpleStorage.storage.annotations) {
-        worker.postMessage(simpleStorage.storage.annotations);
-      }
-      worker.port.on('show', function(data) {
-        annotation.content = data;
-        annotation.show();
-      });
-      worker.port.on('hide', function() {
-        annotation.content = null;
-        annotation.hide();
-      });
-      worker.on('detach', function () {
-        detachWorker(this, matchers);
-      });
-      matchers.push(worker);
-    }
-  });
-
-/*
-The annotation panel is the UI component that displays an annotation.
-
-When we are ready to show it we assign its 'content' attribute to contain
-the annotation text, and that gets sent to the content process in onShow().
-*/
-  var annotation = panels.Panel({
-    width: 200,
-    height: 180,
-    contentURL: data.url('annotation/annotation.html'),
-    contentScriptFile: [data.url('jquery-1.4.2.min.js'),
-                        data.url('annotation/annotation.js')],
-    contentScriptWhen: 'ready',
-    onShow: function() {
-      this.postMessage(this.content);
-    }
-  });
-
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "license": "MPL 2.0",
-  "name": "annotator",
-  "contributors": [],
-  "author": "Will Bamberg",
-  "keywords": [],
-  "version": "0.1.1",
-  "id": "anonid0-annotator@jetpack",
-  "description": "Add notes to Web pages",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/annotator/tests/test-main.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-exports.testMain = function(assert) {
-  assert.pass("TODO: Write some tests.");
-};
-
-require("sdk/test").run(exports);
--- a/addon-sdk/source/examples/debug-client/package.json
+++ b/addon-sdk/source/examples/debug-client/package.json
@@ -1,10 +1,10 @@
 {
   "name": "debug-client",
   "id": "@debug-client",
   "title": "Debug client",
   "description": "Example debug client",
   "version": "0.0.1",
   "author": "Irakli Gozalishvili",
   "main": "./index.js",
-  "license": "MPL 2.0"
+  "license": "MPL-2.0"
 }
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-This is a port to the SDK of the
-[Library Detector add-on](https://addons.mozilla.org/en-US/firefox/addon/library-detector/).
-The original Library Detector is written by
-[Paul Bakaus](http://paulbakaus.com/) and made available under the
-[MIT License](http://www.opensource.org/licenses/mit-license.php).
-
-It only recognizes a subset of the libraries recognized by the original,
-just to keep the SDK download package size and on-disk footprint as small
-as possible.
deleted file mode 100644
index a8c91a039c867919580e945391d8dbf0583624da..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 8df8f3893cbe881e0067cec73870c1388c70843a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 77e3bd2dd354989533e0d4be353a17461f823648..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c37d43883133d3e6e10e5893d16b2206e53fe305..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 2a5df7db5890c738f675e12720e419392594e9bf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 06acd8a79b6eb13f0b9cdcac4d5b6cd78e6ca1e1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/library-detector.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-The code in this file is adapted from the original
-Library Detector add-on
-(https://addons.mozilla.org/en-US/firefox/addon/library-detector/) written by
-Paul Bakaus (http://paulbakaus.com/) and made available under the
-MIT License (http://www.opensource.org/licenses/mit-license.php).
-*/
-
-var LD_tests = {
-
-    'jQuery': {
-        test: function(win) {
-            var jq = win.jQuery || win.$ || win.$jq || win.$j;
-            if(jq && jq.fn && jq.fn.jquery) {
-                return { version: jq.fn.jquery };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'jQuery UI': {
-        //phonehome: 'http://jqueryui.com/phone_home',
-        test: function(win) {
-
-            var jq = win.jQuery || win.$ || win.$jq || win.$j;
-            if(jq && jq.fn && jq.fn.jquery && jq.ui) {
-
-                var plugins = 'accordion,datepicker,dialog,draggable,droppable,progressbar,resizable,selectable,slider,menu,grid,tabs'.split(','), concat = [];
-                for (var i=0; i < plugins.length; i++) { if(jq.ui[plugins[i]]) concat.push(plugins[i].substr(0,1).toUpperCase() + plugins[i].substr(1)); };
-
-                return { version: jq.ui.version, details: concat.length ? 'Plugins used: '+concat.join(',') : '' };
-            } else {
-                return false;
-            }
-
-        }
-    },
-
-    'MooTools': {
-        test: function(win) {
-            if(win.MooTools && win.MooTools.version) {
-                return { version: win.MooTools.version };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'YUI': {
-        test: function(win) {
-            if(win.YAHOO && win.YAHOO.VERSION) {
-                return { version: win.YAHOO.VERSION };
-            } else {
-                return false;
-            }
-        }
-    },
-
-    'Closure': {
-        test: function(win) {
-            if(win.goog) {
-                return { version: '2.0' };
-            }
-            return false;
-        }
-    },
-
-    'Modernizr': {
-        test: function(win) {
-            if(win.Modernizr) {
-                return { version: win.Modernizr._version };
-            }
-            return false;
-        }
-    },
-
-
-};
-
-function testLibraries() {
-  var win = unsafeWindow;
-  var libraryList = [];
-  for(var i in LD_tests) {
-    var passed = LD_tests[i].test(win);
-    if (passed) {
-      let libraryInfo = {
-        name: i,
-        version: passed.version
-      };
-      libraryList.push(libraryInfo);
-    }
-  }
-  self.postMessage(libraryList);
-}
-
-testLibraries();
\ No newline at end of file
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/panel.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Library detector</title>
-  <script type="text/javascript">
-    addon.on('message', function (libraryInfo) {
-      document.body.innerHTML = libraryInfo;
-    });
-  </script>
-</head>
-<body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/data/widget.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-  <title>Library detector</title>
-  <style type="text/css" media="all">
-    img {
-      display: inline;
-      width: 16px;
-      height: 16px;
-    }
-  </style>
-  <script type="text/javascript">
-    var icons = {
-      'jQuery' : 'jquery.ico',
-      'jQuery UI' : 'jquery_ui.ico',
-      'MooTools' : 'mootools.png',
-      'YUI' : 'yui.ico',
-      'Closure' : 'closure.ico',
-      'Modernizr': 'modernizr.ico',
-    };
-
-    // Listen for mouse events over icons, in order to send a message up to
-    // the panel and update its content with library name and version
-    window.addEventListener('mouseover', function (event) {
-      if (event.target.tagName == 'IMG') {
-        addon.port.emit('setLibraryInfo', event.target.title);
-      }
-    }, false);
-
-    addon.port.on('update', function (libraries) {
-      // Cleanup previous content
-      document.body.innerHTML = '';
-
-      // Create new updated list of icons
-      libraries.forEach(function(library) {
-        var img = document.createElement('img');
-        img.setAttribute('src', 'icons/' + icons[library.name]);
-        img.setAttribute('title', library.name + "<br>Version: " +
-                                  library.version);
-        document.body.appendChild(img);
-      });
-    });
-  </script>
-</head>
-<body></body>
-</html>
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/lib/main.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const tabs = require('sdk/tabs');
-const widgets = require('sdk/widget');
-const data = require('sdk/self').data;
-const pageMod = require('sdk/page-mod');
-const panel = require('sdk/panel');
-
-const ICON_WIDTH = 16;
-
-function updateWidgetView(tab) {
-  let widgetView = widget.getView(tab.window);
-  if (!tab.libraries) {
-    tab.libraries = [];
-  }
-  widgetView.port.emit("update", tab.libraries);
-  widgetView.width = tab.libraries.length * ICON_WIDTH;
-}
-
-var widget = widgets.Widget({
-  id: "library-detector",
-  label: "Library Detector",
-  contentURL: data.url("widget.html"),
-  panel: panel.Panel({
-    width: 240,
-    height: 60,
-    contentURL: data.url("panel.html")
-  })
-});
-
-widget.port.on('setLibraryInfo', function(libraryInfo) {
-  widget.panel.postMessage(libraryInfo);
-});
-
-pageMod.PageMod({
-  include: "*",
-  contentScriptWhen: 'end',
-  contentScriptFile: (data.url('library-detector.js')),
-  onAttach: function(worker) {
-    worker.on('message', function(libraryList) {
-      if (!worker.tab.libraries) {
-        worker.tab.libraries = [];
-      }
-      libraryList.forEach(function(library) {
-        if (worker.tab.libraries.indexOf(library) == -1) {
-          worker.tab.libraries.push(library);
-        }
-      });
-      if (worker.tab == tabs.activeTab) {
-        updateWidgetView(worker.tab);
-      }
-    });
-  }
-});
-
-tabs.on('activate', function(tab) {
-  updateWidgetView(tab);
-});
-
-/*
-For change of location
-*/
-tabs.on('ready', function(tab) {
-  tab.libraries = [];
-});
\ No newline at end of file
deleted file mode 100755
--- a/addon-sdk/source/examples/library-detector/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "name": "library-detector-sdk",
-  "license": "MPL 2.0",
-  "author": "",
-  "version": "0.1.1",
-  "title": "library-detector-sdk",
-  "id": "jid1-R4rSVNkBANnvGQ@jetpack",
-  "description": "a basic add-on",
-  "main": "./lib/main.js"
-}
deleted file mode 100644
--- a/addon-sdk/source/examples/library-detector/test/test-main.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
-
-exports.testMain = function(assert) {
-  assert.pass("TODO: Write some tests.");
-};
-
-require("sdk/test").run(exports);
--- a/addon-sdk/source/examples/reading-data/package.json
+++ b/addon-sdk/source/examples/reading-data/package.json
@@ -1,9 +1,9 @@
 {
     "name": "reading-data",
     "description": "A demonstration of reading bundled data.",
     "keywords": [],
     "author": "Brian Warner",
     "contributors": [],
-    "license": "MPL 2.0",
+    "license": "MPL-2.0",
     "id": "reading-data-example@jetpack.mozillalabs.com"
 }
--- a/addon-sdk/source/examples/theme/package.json
+++ b/addon-sdk/source/examples/theme/package.json
@@ -1,10 +1,10 @@
 {
   "name": "theme",
   "title": "theme",
   "id": "theme@jetpack",
   "description": "How to create new theme for devtools",
   "author": "Jan Odvarko",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.0",
   "main": "lib/main"
 }
--- a/addon-sdk/source/examples/toolbar-api/package.json
+++ b/addon-sdk/source/examples/toolbar-api/package.json
@@ -1,12 +1,12 @@
 {
   "name": "toolbar-api",
   "title": "Toolbar API",
   "main": "./lib/main.js",
   "description": "a toolbar api example",
   "author": "",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.1",
   "engines": {
     "firefox": ">=27.0 <=30.0"
   }
 }
--- a/addon-sdk/source/examples/ui-button-apis/package.json
+++ b/addon-sdk/source/examples/ui-button-apis/package.json
@@ -1,10 +1,10 @@
 {
   "name": "ui-button-apis",
   "title": "Australis Button API Examples",
   "id": "ui-button-apis@mozilla.org",
   "description": "A Button API example",
   "author": "jeff@canuckistani.ca (Jeff Griffiths | @canuckistani)",
-  "license": "MPL 2.0",
+  "license": "MPL-2.0",
   "version": "0.1.1",
   "main": "./lib/main.js"
 }
--- a/addon-sdk/source/gulpfile.js
+++ b/addon-sdk/source/gulpfile.js
@@ -1,23 +1,44 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var gulp = require('gulp');
+var patch = require("./bin/node-scripts/apply-patch");
+var ini = require("./bin/node-scripts/update-ini");
 
 gulp.task('test', function(done) {
   require("./bin/jpm-test").run().then(done);
 });
 
 gulp.task('test:addons', function(done) {
-  require("./bin/jpm-test").run("addons").then(done);
+  require("./bin/jpm-test").run("addons").catch(console.error).then(done);
+});
+
+gulp.task('test:docs', function(done) {
+  require("./bin/jpm-test").run("docs").catch(console.error).then(done);
 });
 
 gulp.task('test:examples', function(done) {
-  require("./bin/jpm-test").run("examples").then(done);
+  require("./bin/jpm-test").run("examples").catch(console.error).then(done);
 });
 
 gulp.task('test:modules', function(done) {
-  require("./bin/jpm-test").run("modules").then(done);
+  require("./bin/jpm-test").run("modules").catch(console.error).then(done);
+});
+
+gulp.task('test:ini', function(done) {
+  test("ini").catch(console.error).then(done);
 });
 
+gulp.task('patch:clean', function(done) {
+  patch.clean().catch(console.error).then(done);
+});
+
+gulp.task('patch:apply', function(done) {
+  patch.apply().catch(console.error).then(done);
+});
+
+gulp.task('update:ini', function(done) {
+  ini.updateAddonINI().catch(console.error).then(done);
+});
--- a/addon-sdk/source/lib/dev/frame-script.js
+++ b/addon-sdk/source/lib/dev/frame-script.js
@@ -67,49 +67,54 @@ const onInMessage = (message) => {
 const onReady = event => {
   channels.clear();
 };
 
 addMessageListener("sdk/event/message", onInMessage);
 addMessageListener("sdk/port/message", onInPort);
 
 const observer = {
+  handleEvent: ({target, type}) => {
+    observer.observe(target, type);
+  },
   observe: (document, topic, data) => {
     // When frame associated with message manager is removed from document `docShell`
     // is set to `null` but observer is still kept alive. At this point accesing
     // `content.document` throws "can't access dead object" exceptions. In order to
     // avoid leaking observer and logged errors observer is going to be removed when
     // `docShell` is set to `null`.
     if (!docShell) {
       observerService.removeObserver(observer, topic);
     }
     else if (document === content.document) {
-      if (topic === "content-document-interactive") {
+      if (topic.endsWith("-document-interactive")) {
         sendAsyncMessage("sdk/event/ready", {
           type: "ready",
           readyState: document.readyState,
           uri: document.documentURI
         });
       }
-      if (topic === "content-document-loaded") {
+      if (topic.endsWith("-document-loaded")) {
         sendAsyncMessage("sdk/event/load", {
           type: "load",
           readyState: document.readyState,
           uri: document.documentURI
         });
       }
-      if (topic === "content-page-hidden") {
+      if (topic === "unload") {
         channels.clear();
         sendAsyncMessage("sdk/event/unload", {
           type: "unload",
           readyState: "uninitialized",
           uri: document.documentURI
         });
       }
     }
   }
 };
 
 observerService.addObserver(observer, "content-document-interactive", false);
 observerService.addObserver(observer, "content-document-loaded", false);
-observerService.addObserver(observer, "content-page-hidden", false);
+observerService.addObserver(observer, "chrome-document-interactive", false);
+observerService.addObserver(observer, "chrome-document-loaded", false);
+addEventListener("unload", observer, false);
 
 })(this);
--- a/addon-sdk/source/lib/dev/panel.js
+++ b/addon-sdk/source/lib/dev/panel.js
@@ -121,17 +121,17 @@ const Panel = Class({
            when(this, "load").then(getTarget);
   },
   unloaded: function() {
     const { readyState } = this;
     const isUninitialized = readyState === "uninitialized";
     return isUninitialized ? Promise.resolve(this) :
            when(this, "unload").then(getTarget);
   },
-  postMessage: function(data, ports) {
+  postMessage: function(data, ports=[]) {
     const manager = managerFor(this);
     manager.sendAsyncMessage("sdk/event/message", {
       type: "message",
       bubbles: false,
       cancelable: false,
       data: data,
       origin: this.url,
       ports: ports.map(marshal(manager))
@@ -222,21 +222,21 @@ setup.define(Panel, (panel, {window, too
 
   panel.setup({ debuggee: debuggee });
 });
 
 createView.define(Panel, (panel, document) => {
   const frame = document.createElement("iframe");
   setAttributes(frame, {
     "sandbox": "allow-scripts",
-    // It would be great if we could allow remote iframes for sandboxing
-    // panel documents in a content process, but for now platform implementation
-    // is buggy on linux so this is disabled.
-    // "remote": true,
-    "type": "content",
+    // We end up using chrome iframe with forced message manager
+    // as fixing a swapFrameLoader seemed like a giant task (see
+    // Bug 1075490).
+    "type": "chrome",
+    "forcemessagemanager": true,
     "transparent": true,
     "seamless": "seamless",
   });
   return frame;
 });
 
 dispose.define(Panel, function(panel) {
   debuggeeFor(panel).close();
--- a/addon-sdk/source/lib/dev/volcan.js
+++ b/addon-sdk/source/lib/dev/volcan.js
@@ -1,11 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.volcan=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
 "use strict";
 
 var Client = _dereq_("../client").Client;
 
 function connect(port) {
   var client = new Client();
   return client.connect(port);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/jetpack-id/index.js
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Takes parsed `package.json` manifest and returns
+ * valid add-on id for it.
+ */
+function getID(manifest) {
+  manifest = manifest || {};
+
+  if (manifest.id) {
+
+    if (typeof manifest.id !== "string") {
+      return null;
+    }
+
+    // If manifest.id is already valid (as domain or GUID), use it
+    if (isValidAOMName(manifest.id)) {
+      return manifest.id;
+    }
+    // Otherwise, this ID is invalid so return `null`
+    return null;
+  }
+
+  // If no `id` defined, turn `name` into a domain ID,
+  // as we transition to `name` being an id, similar to node/npm, but
+  // append a '@' to make it compatible with Firefox requirements
+  if (manifest.name) {
+
+    if (typeof manifest.name !== "string") {
+      return null;
+    }
+
+    var modifiedName = "@" + manifest.name;
+    return isValidAOMName(modifiedName) ? modifiedName : null;
+  }
+
+  // If no `id` or `name` property, return null as this manifest
+  // is invalid
+  return null;
+}
+
+module.exports = getID;
+
+/**
+ * Regex taken from XPIProvider.jsm in the Addon Manager to validate proper
+ * IDs that are able to be used.
+ * http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#209
+ */
+function isValidAOMName (s) {
+  return /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i.test(s || "");
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/jetpack-id/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "jetpack-id",
+  "version": "1.0.0",
+  "description": "Creates an ID from a Firefox Jetpack manifest",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/jsantell/jetpack-id"
+  },
+  "author": {
+    "name": "Jordan Santell",
+    "url": "http://github.com/jsantell"
+  },
+  "license": "MPL-2.0",
+  "scripts": {
+    "test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
+  },
+  "keywords": [
+    "jetpack",
+    "addon",
+    "mozilla",
+    "firefox"
+  ],
+  "devDependencies": {
+    "mocha": "*",
+    "chai": "*"
+  }
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/index.js
@@ -0,0 +1,112 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var versionParse = require('./lib/utils').versionParse;
+
+var COMPARATORS = ['>=', '<=', '>', '<', '=', '~', '^'];
+
+exports.parse = function (input) {
+  input = input || '';
+  input = input.trim();
+  if (!input)
+    throw new Error('`parse` argument must be a populated string.');
+
+  // Handle the "*" case
+  if (input === "*") {
+    return { min: undefined, max: undefined };
+  }
+
+  var inputs = input.split(' ');
+  var min;
+  var max;
+
+  // 1.2.3 - 2.3.4
+  if (inputs.length === 3 && inputs[1] === '-') {
+    return { min: inputs[0], max: inputs[2] };
+  }
+
+  inputs.forEach(function (input) {
+    var parsed = parseExpression(input);
+    var version = parsed.version;
+    var comparator = parsed.comparator;
+
+    // 1.2.3
+    if (inputs.length === 1 && !comparator)
+      min = max = version;
+
+    // Parse min
+    if (~comparator.indexOf('>')) {
+      if (~comparator.indexOf('='))
+        min = version; // >=1.2.3
+      else
+        min = increment(version); // >1.2.3
+    }
+    else if (~comparator.indexOf('<')) {
+      if (~comparator.indexOf('='))
+        max = version; // <=1.2.3
+      else
+        max = decrement(version); // <1.2.3
+    }
+  });
+
+  return {
+    min: min,
+    max : max
+  };
+};
+
+function parseExpression (input) {
+  for (var i = 0; i < COMPARATORS.length; i++)
+    if (~input.indexOf(COMPARATORS[i]))
+      return {
+        comparator: COMPARATORS[i],
+        version: input.substr(COMPARATORS[i].length)
+      };
+  return { version: input, comparator: '' };
+}
+
+/**
+ * Takes a version string ('1.2.3') and returns a version string
+ * that'll parse as one less than the input string ('1.2.3.-1').
+ *
+ * @param {String} vString
+ * @return {String}
+ */
+function decrement (vString) {
+  return vString + (vString.charAt(vString.length - 1) === '.' ? '' : '.') + '-1';
+}
+exports.decrement = decrement;
+
+/**
+ * Takes a version string ('1.2.3') and returns a version string
+ * that'll parse as greater than the input string by the smallest margin
+ * possible ('1.2.3.1').
+ * listed as number-A, string-B, number-C, string-D in
+ * Mozilla's Toolkit Format.
+ * https://developer.mozilla.org/en-US/docs/Toolkit_version_format
+ *
+ * @param {String} vString
+ * @return {String}
+ */
+function increment (vString) {
+  var match = versionParse(vString);
+  var a = match[1];
+  var b = match[2];
+  var c = match[3];
+  var d = match[4];
+  var lastPos = vString.length - 1;
+  var lastChar = vString.charAt(lastPos);
+
+  if (!b) {
+    return vString + (lastChar === '.' ? '' : '.') + '1';
+  }
+  if (!c) {
+    return vString + '1';
+  }
+  if (!d) {
+    return vString.substr(0, lastPos) + (++lastChar);
+  }
+  return vString.substr(0, lastPos) + String.fromCharCode(lastChar.charCodeAt(0) + 1);
+}
+exports.increment = increment;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/lib/utils.js
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Breaks up a version string into the 4 components
+ * defined in:
+ * https://developer.mozilla.org/en-US/docs/Toolkit_version_format
+ * @params {String} val
+ * @return {String}
+ */
+function versionParse (val) {
+  return val.match(/^([0-9\.]*)([a-zA-Z]*)([0-9\.]*)([a-zA-Z]*)$/);
+}
+exports.versionParse = versionParse;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/mozilla-toolkit-versioning/package.json
@@ -0,0 +1,21 @@
+{
+  "name": "mozilla-toolkit-versioning",
+  "version": "0.0.2",
+  "description": "Parser for Mozilla's toolkit version format",
+  "main": "index.js",
+  "scripts": {
+    "test": "./node_modules/.bin/mocha --reporter spec --ui bdd"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jsantell/mozilla-toolkit-versioning.git"
+  },
+  "author": "Jordan Santell",
+  "license": "MIT",
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "^1.21.4",
+    "chai": "^1.9.1",
+    "mozilla-version-comparator": "^1.0.2"
+  }
+}
--- a/addon-sdk/source/lib/sdk/clipboard.js
+++ b/addon-sdk/source/lib/sdk/clipboard.js
@@ -11,17 +11,16 @@ module.metadata = {
     "Firefox": "*",
     "SeaMonkey": "*",
     "Thunderbird": "*"
   }
 };
 
 const { Cc, Ci } = require("chrome");
 const { DataURL } = require("./url");
-const errors = require("./deprecated/errors");
 const apiUtils = require("./deprecated/api-utils");
 /*
 While these data flavors resemble Internet media types, they do
 no directly map to them.
 */
 const kAllowableFlavors = [
   "text/unicode",
   "text/html",
--- a/addon-sdk/source/lib/sdk/content/content-worker.js
+++ b/addon-sdk/source/lib/sdk/content/content-worker.js
@@ -105,17 +105,17 @@ Object.freeze({
       time: pipe.emit.bind(null, "console", "time"),
       timeEnd: pipe.emit.bind(null, "console", "timeEnd")
     });
   },
 
   injectTimers: function injectTimers(exports, chromeAPI, pipe, console) {
     // wrapped functions from `'timer'` module.
     // Wrapper adds `try catch` blocks to the callbacks in order to
-    // emit `error` event on a symbiont if exception is thrown in
+    // emit `error` event if exception is thrown in
     // the Worker global scope.
     // @see http://www.w3.org/TR/workers/#workerutils
 
     // List of all living timeouts/intervals
     let _timers = Object.create(null);
 
     // Keep a reference to original timeout functions
     let {
--- a/addon-sdk/source/lib/sdk/content/content.js
+++ b/addon-sdk/source/lib/sdk/content/content.js
@@ -4,29 +4,14 @@
 "use strict";
 
 module.metadata = {
   "stability": "deprecated"
 };
 
 const { deprecateUsage } = require('../util/deprecate');
 
-Object.defineProperty(exports, "Loader", { 
-  get: function() {
-    deprecateUsage('`sdk/content/content` is deprecated. Please use `sdk/content/loader` directly.');
-    return require('./loader').Loader;
-  }
-});
-
-Object.defineProperty(exports, "Symbiont", { 
-  get: function() {
-    deprecateUsage('Both `sdk/content/content` and `sdk/deprecated/symbiont` are deprecated. ' +
-                   '`sdk/core/heritage` supersedes Symbiont for inheritance.');
-    return require('../deprecated/symbiont').Symbiont;
-  }
-});
-
-Object.defineProperty(exports, "Worker", { 
+Object.defineProperty(exports, "Worker", {
   get: function() {
     deprecateUsage('`sdk/content/content` is deprecated. Please use `sdk/content/worker` directly.');
     return require('./worker').Worker;
   }
 });
--- a/addon-sdk/source/lib/sdk/content/loader.js
+++ b/addon-sdk/source/lib/sdk/content/loader.js
@@ -1,30 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-const { EventEmitter } = require('../deprecated/events');
 const { isValidURI, isLocalURL, URL } = require('../url');
-const file = require('../io/file');
 const { contract } = require('../util/contract');
 const { isString, isNil, instanceOf } = require('../lang/type');
 const { validateOptions,
   string, array, object, either, required } = require('../deprecated/api-utils');
 
 const isJSONable = (value) => {
   try {
     JSON.parse(JSON.stringify(value));
-  } catch (e) {
+  }
+  catch (e) {
     return false;
   }
   return true;
 };
 
 const isValidScriptFile = (value) =>
   (isString(value) || instanceOf(value, URL)) && isLocalURL(value);
 
@@ -70,107 +68,9 @@ function validate(suspect, validation) v
   { $: validation }
 ).$
 
 function Allow(script) ({
   get script() script,
   set script(value) script = !!value
 })
 
-/**
- * Trait is intended to be used in some composition. It provides set of core
- * properties and bounded validations to them. Trait is useful for all the
- * compositions providing high level APIs for interaction with content.
- * Property changes emit `"propertyChange"` events on instances.
- */
-const Loader = EventEmitter.compose({
-  /**
-   * Permissions for the content, with the following keys:
-   * @property {Object} [allow = { script: true }]
-   * @property {Boolean} [allow.script = true]
-   *    Whether or not to execute script in the content.  Defaults to true.
-   */
-  get allow() this._allow || (this._allow = Allow(true)),
-  set allow(value) this.allow.script = value && value.script,
-  _allow: null,
-  /**
-   * The content to load. Either a string of HTML or a URL.
-   * @type {String}
-   */
-  get contentURL() this._contentURL,
-  set contentURL(value) {
-    value = validate(value, valid.contentURL);
-    if (this._contentURL != value) {
-      this._emit('propertyChange', {
-        contentURL: this._contentURL = value
-      });
-    }
-  },
-  _contentURL: null,
-  /**
-   * When to load the content scripts.
-   * Possible values are "end" (default), which loads them once all page
-   * contents have been loaded, "ready", which loads them once DOM nodes are
-   * ready (ie like DOMContentLoaded event), and "start", which loads them once
-   * the `window` object for the page has been created, but before any scripts
-   * specified by the page have been loaded.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {'start'|'ready'|'end'}
-   */
-  get contentScriptWhen() this._contentScriptWhen,
-  set contentScriptWhen(value) {
-    value = validate(value, valid.contentScriptWhen);
-    if (value !== this._contentScriptWhen) {
-      this._emit('propertyChange', {
-        contentScriptWhen: this._contentScriptWhen = value
-      });
-    }
-  },
-  _contentScriptWhen: 'end',
-  /**
-   * Options avalaible from the content script as `self.options`.
-   * The value of options can be of any type (object, array, string, etc.)
-   * but only jsonable values will be available as frozen objects from the
-   * content script.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {Object}
-   */
-  get contentScriptOptions() this._contentScriptOptions,
-  set contentScriptOptions(value) this._contentScriptOptions = value,
-  _contentScriptOptions: null,
-  /**
-   * The URLs of content scripts.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {String[]}
-   */
-  get contentScriptFile() this._contentScriptFile,
-  set contentScriptFile(value) {
-    value = validate(value, valid.contentScriptFile);
-    if (value != this._contentScriptFile) {
-      this._emit('propertyChange', {
-        contentScriptFile: this._contentScriptFile = value
-      });
-    }
-  },
-  _contentScriptFile: null,
-  /**
-   * The texts of content script.
-   * Property change emits `propertyChange` event on instance with this key
-   * and new value.
-   * @type {String|undefined}
-   */
-  get contentScript() this._contentScript,
-  set contentScript(value) {
-    value = validate(value, valid.contentScript);
-    if (value != this._contentScript) {
-      this._emit('propertyChange', {
-        contentScript: this._contentScript = value
-      });
-    }
-  },
-  _contentScript: null
-});
-exports.Loader = Loader;
-
 exports.contract = contract(valid);
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ b/addon-sdk/source/lib/sdk/content/sandbox.js
@@ -111,17 +111,17 @@ const WorkerSandbox = Class({
     this.emit = this.emit.bind(this);
     this.emitSync = this.emitSync.bind(this);
 
     // Use expanded principal for content-script if the content is a
     // regular web content for better isolation.
     // (This behavior can be turned off for now with the unsafe-content-script
     // flag to give addon developers time for making the necessary changes)
     // But prevent it when the Worker isn't used for a content script but for
-    // injecting `addon` object into a Panel, Widget, ... scope.
+    // injecting `addon` object into a Panel scope, for example.
     // That's because:
     // 1/ It is useless to use multiple domains as the worker is only used
     // to communicate with the addon,
     // 2/ By using it it would prevent the document to have access to any JS
     // value of the worker. As JS values coming from multiple domain principals
     // can't be accessed by 'mono-principals' (principal with only one domain).
     // Even if this principal is for a domain that is specified in the multiple
     // domain principal.
@@ -209,17 +209,17 @@ const WorkerSandbox = Class({
       Object.defineProperty(getUnsafeWindow(window), 'addon', {
           value: content.self,
           configurable: true
         }
       );
     }
 
     // Inject our `console` into target document if worker doesn't have a tab
-    // (e.g Panel, PageWorker, Widget).
+    // (e.g Panel, PageWorker).
     // `worker.tab` can't be used because bug 804935.
     if (!isWindowInTab(window)) {
       let win = getUnsafeWindow(window);
 
       // export our chrome console to content window, as described here:
       // https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
       let con = Cu.createObjectIn(win);
 
--- a/addon-sdk/source/lib/sdk/content/worker-child.js
+++ b/addon-sdk/source/lib/sdk/content/worker-child.js
@@ -29,16 +29,18 @@ const EVENTS = {
 const WorkerChild = Class({
   implements: [EventTarget],
 
   initialize(options) {
     merge(this, options);
     keepAlive.set(this.id, this);
 
     this.windowId = getInnerId(this.window);
+    if (this.contentScriptOptions)
+      this.contentScriptOptions = JSON.parse(this.contentScriptOptions);
 
     this.port = EventTarget();
     this.port.on('*', this.send.bind(this, 'event'));
     this.on('*', this.send.bind(this));
 
     this.observe = this.observe.bind(this);
 
     for (let topic in EVENTS)
@@ -48,41 +50,41 @@ const WorkerChild = Class({
     process.port.on('sdk/worker/message', this.receive);
 
     this.sandbox = WorkerSandbox(this, this.window);
 
     this.frozen = false;
     this.frozenMessages = [];
     this.on('pageshow', () => {
       this.frozen = false;
-      this.frozenMessages.forEach(args => this.receive(null, this.id, args));
+      this.frozenMessages.forEach(args => this.sandbox.emit(...args));
       this.frozenMessages = [];
     });
     this.on('pagehide', () => {
       this.frozen = true;
     });
   },
 
   // messages
   receive(process, id, args) {
     if (id !== this.id)
       return;
+    args = JSON.parse(args);
 
     if (this.frozen)
       this.frozenMessages.push(args);
     else
       this.sandbox.emit(...args);
 
     if (args[0] === 'detach')
       this.destroy(args[1]);
   },
 
   send(...args) {
-    args = JSON.parse(JSON.stringify(args, exceptions));
-    process.port.emit('sdk/worker/event', this.id, args);
+    process.port.emit('sdk/worker/event', this.id, JSON.stringify(args, exceptions));
   },
 
   // notifications
   observe({ type, subject }) {
     if (!this.sandbox)
       return;
 
     if (subject.defaultView && getInnerId(subject.defaultView) === this.windowId) {
@@ -126,17 +128,17 @@ function exceptions(key, value) {
   let { message, fileName, lineNumber, stack, name } = value;
   return { _errorType, message, fileName, lineNumber, stack, name };
 }
 
 // workers for windows in this tab
 let keepAlive = new Map();
 
 process.port.on('sdk/worker/create', (process, options) => {
-  options.window = getByInnerId(options.window);
+  options.window = getByInnerId(options.windowId);
   if (!options.window)
     return;
 
   let worker = new WorkerChild(options);
 });
 
 when(reason => {
   for (let worker of keepAlive.values())
--- a/addon-sdk/source/lib/sdk/content/worker.js
+++ b/addon-sdk/source/lib/sdk/content/worker.js
@@ -62,16 +62,17 @@ const Worker = Class({
     }
   },
 
   // messages
   receive(process, id, args) {
     let model = modelFor(this);
     if (id !== model.id || !model.attached)
       return;
+    args = JSON.parse(args);
     if (model.destroyed && args[0] != 'detach')
       return;
 
     if (args[0] === 'event')
       emit(this.port, ...args.slice(1))
     else
       emit(this, ...args);
   },
@@ -81,17 +82,17 @@ const Worker = Class({
     if (model.destroyed && args[0] !== 'detach')
       throw new Error(ERR_DESTROYED);
 
     if (!model.attached) {
       model.earlyEvents.push(args);
       return;
     }
 
-    processes.port.emit('sdk/worker/message', model.id, args);
+    processes.port.emit('sdk/worker/message', model.id, JSON.stringify(args));
   },
 
   // properties
   get url() {
     let { url } = modelFor(this);
     return url;
   },
 
@@ -122,25 +123,36 @@ attach.define(Worker, function(worker, w
     detach(worker);
 
   model.window = window;
   let frame = null;
   let tab = getTabForContentWindow(window.top);
   if (tab)
     frame = frames.getFrameForBrowser(getBrowserForTab(tab));
 
-  merge(model.options, {
-    id: String(uuid()),
-    window: getInnerId(window),
-    url: String(window.location)
-  });
+  function makeStringArray(arrayOrValue) {
+    if (!arrayOrValue)
+      return [];
+    return [String(v) for (v of [].concat(arrayOrValue))];
+  }
 
-  processes.port.emit('sdk/worker/create', model.options);
+  let id = String(uuid());
+  let childOptions = {
+    id,
+    windowId: getInnerId(window),
+    contentScript: makeStringArray(model.options.contentScript),
+    contentScriptFile: makeStringArray(model.options.contentScriptFile),
+    contentScriptOptions: model.options.contentScriptOptions ?
+                          JSON.stringify(model.options.contentScriptOptions) :
+                          null,
+  }
 
-  connect(worker, frame, model.options);
+  processes.port.emit('sdk/worker/create', childOptions);
+
+  connect(worker, frame, { id, url: String(window.location) });
 })
 
 connect.define(Worker, function(worker, frame, { id, url }) {
   let model = modelFor(worker);
   if (model.attached)
     detach(worker);
 
   model.id = id;
--- a/addon-sdk/source/lib/sdk/context-menu.js
+++ b/addon-sdk/source/lib/sdk/context-menu.js
@@ -444,17 +444,17 @@ let BaseItem = Class({
     return internal(this).parentMenu;
   },
 });
 
 function workerMessageReceived(process, id, args) {
   if (internal(this).id != id)
     return;
 
-  emit(this, ...args);
+  emit(this, ...JSON.parse(args));
 }
 
 // All things that have a label on the context menu extend this
 let LabelledItem = Class({
   extends: BaseItem,
   implements: [ EventTarget ],
 
   initialize: function initialize(options) {
--- a/addon-sdk/source/lib/sdk/core/promise.js
+++ b/addon-sdk/source/lib/sdk/core/promise.js
@@ -1,13 +1,11 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 /*
  * Uses `Promise.jsm` as a core implementation, with additional sugar
  * from previous implementation, with inspiration from `Q` and `when`
  *
  * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm
  * https://github.com/cujojs/when
--- a/addon-sdk/source/lib/sdk/deprecated/api-utils.js
+++ b/addon-sdk/source/lib/sdk/deprecated/api-utils.js
@@ -1,19 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
 
-"use strict";
 module.metadata = {
   "stability": "deprecated"
 };
 
-const memory = require("./memory");
-
 const { merge } = require("../util/object");
 const { union } = require("../util/array");
 const { isNil, isRegExp } = require("../lang/type");
 
 // The possible return values of getTypeOf.
 const VALID_TYPES = [
   "array",
   "boolean",
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/cortex.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const getOwnIdentifiers = x => [...Object.getOwnPropertyNames(x),
-                                ...Object.getOwnPropertySymbols(x)];
-
-
-// `var` is being used in the module in order to make it reusable in
-// environments in which `let` and `const` is not yet supported.
-
-// Returns `object`'s property value, where `name` is a name of the property.
-function get(object, name) {
-  return object[name];
-}
-
-// Assigns `value` to the `object`'s property, where `name` is the name of the
-// property.
-function set(object, name, value) {
-  return object[name] = value;
-}
-
-/**
- * Given an `object` containing a property with the given `name`, create
- * a property descriptor that can be used to define alias/proxy properties
- * on other objects.  A change in the value of an alias will propagate
- * to the aliased property and vice versa.
- */
-function createAliasProperty(object, name) {
-  // Getting own property descriptor of an `object` for the given `name` as
-  // we are going to create proxy analog.
-  var property = Object.getOwnPropertyDescriptor(object, name);
-  var descriptor = {
-    configurable: property.configurable,
-    enumerable: property.enumerable,
-    alias: true
-  };
-
-  // If the original property has a getter and/or setter, bind a
-  // corresponding getter/setter in the alias descriptor to the original
-  // object, so the `this` object in the getter/setter is the original object
-  // rather than the alias.
-  if ("get" in property && property.get)
-    descriptor.get = property.get.bind(object);
-  if ("set" in property && property.set)
-    descriptor.set = property.set.bind(object);
-
-  // If original property was a value property.
-  if ("value" in property) {
-    // If original property is a method using it's `object` bounded copy.
-    if (typeof property.value === "function") {
-      descriptor.value = property.value.bind(object);
-      // Also preserving writability of the original property.
-      descriptor.writable = property.writable;
-    }
-
-    // If the original property was just a data property, we create proxy
-    // accessors using our custom get/set functions to propagate changes to the
-    // original `object` and vice versa.
-    else {
-      descriptor.get = get.bind(null, object, name);
-      descriptor.set = set.bind(null, object, name);
-    }
-  }
-  return descriptor;
-}
-
-// Defines property on `object` object with a name `alias` if given if not
-// defaults to `name` that represents an alias of `source[name]`. If aliased
-// property was an assessor or a method `this` pseudo-variable will be `source`
-// when invoked. If aliased property was a data property changes on any of the
-// aliases will propagate to the `source[name]` and also other way round.
-function defineAlias(source, target, name, alias) {
-  return Object.defineProperty(target, alias || name,
-                               createAliasProperty(source, name));
-}
-
-/**
- * Function takes any `object` and returns a proxy for its own public
- * properties. By default properties are considered to be public if they don't
- * start with `"_"`, but default behavior can be overridden if needed, by
- * passing array of public property `names` as a second argument. By default
- * returned object will be direct decedent of the given `object`'s prototype,
- * but this can be overridden by passing third optional argument, that will be
- * used as `prototype` instead.
- * @param {Object} object
- *    Object to create cortex for.
- * @param {String[]} [names]
- *    Optional array of public property names.
- * @param {Object} [prototype]
- *    Optional argument that will be used as `prototype` of the returned object,
- *    if not provided `Object.getPrototypeOf(object)` is used instead.
- */
-exports.Cortex = function Cortex(object, names, prototype) {
-  // Creating a cortex object from the given `prototype`, if one was not
-  // provided then `prototype` of a given `object` is used. This allows
-  // consumer to define expected behavior `instanceof`. In common case
-  // `prototype` argument can be omitted to preserve same behavior of
-  // `instanceof` as on original `object`.
-  var cortex = Object.create(prototype || Object.getPrototypeOf(object));
-  // Creating alias properties on the `cortex` object for all the own
-  // properties of the original `object` that are contained in `names` array.
-  // If `names` array is not provided then all the properties that don't
-  // start with `"_"` are aliased.
-  getOwnIdentifiers(object).forEach(function (name) {
-    if ((!names && "_" !== name.toString().charAt(0)) || (names && ~names.indexOf(name)))
-      defineAlias(object, cortex, name);
-  });
-  return cortex;
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/errors.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-function logToConsole(e) {
-  console.exception(e);
-}
-
-var catchAndLog = exports.catchAndLog = function(callback,
-                                                 defaultResponse,
-                                                 logException) {
-  if (!logException)
-    logException = logToConsole;
-
-  return function() {
-    try {
-      return callback.apply(this, arguments);
-    } catch (e) {
-      logException(e);
-      return defaultResponse;
-    }
-  };
-};
-
-exports.catchAndLogProps = function catchAndLogProps(object,
-                                                     props,
-                                                     defaultResponse,
-                                                     logException) {
-  if (typeof(props) == "string")
-    props = [props];
-  props.forEach(
-    function(property) {
-      object[property] = catchAndLog(object[property],
-                                     defaultResponse,
-                                     logException);
-    });
-};
-
-/**
- * Catch and return an exception while calling the callback.  If the callback
- * doesn't throw, return the return value of the callback in a way that makes it
- * possible to distinguish between a return value and an exception.
- *
- * This function is useful when you need to pass the result of a call across
- * a process boundary (across which exceptions don't propagate).  It probably
- * doesn't need to be factored out into this module, since it is only used by
- * a single caller, but putting it here works around bug 625560.
- */
-exports.catchAndReturn = function(callback) {
-  return function() {
-    try {
-      return { returnValue: callback.apply(this, arguments) };
-    }
-    catch (exception) {
-      return { exception: exception };
-    }
-  };
-};
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/events.js
+++ /dev/null
@@ -1,181 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const ERROR_TYPE = 'error',
-      UNCAUGHT_ERROR = 'An error event was dispatched for which there was'
-        + ' no listener.',
-      BAD_LISTENER = 'The event listener must be a function.';
-/**
- * This object is used to create an `EventEmitter` that, useful for composing
- * objects that emit events. It implements an interface like `EventTarget` from
- * DOM Level 2, which is implemented by Node objects in implementations that
- * support the DOM Event Model.
- * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
- * @see http://nodejs.org/api.html#EventEmitter
- * @see http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/EventDispatcher.html
- */
-const eventEmitter =  {
-  /**
-   * Registers an event `listener` that is called every time events of
-   * specified `type` are emitted.
-   * @param {String} type
-   *    The type of event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   * @example
-   *      worker.on('message', function (data) {
-   *          console.log('data received: ' + data)
-   *      })
-   */
-  on: function on(type, listener) {
-    if ('function' !== typeof listener)
-      throw new Error(BAD_LISTENER);
-    let listeners = this._listeners(type);
-    if (0 > listeners.indexOf(listener))
-      listeners.push(listener);
-    // Use of `_public` is required by the legacy traits code that will go away
-    // once bug-637633 is fixed.
-    return this._public || this;
-  },
-
-  /**
-   * Registers an event `listener` that is called once the next time an event
-   * of the specified `type` is emitted.
-   * @param {String} type
-   *    The type of the event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   */
-  once: function once(type, listener) {
-    this.on(type, function selfRemovableListener() {
-      this.removeListener(type, selfRemovableListener);
-      listener.apply(this, arguments);
-    });
-  },
-
-  /**
-   * Unregister `listener` for the specified event type.
-   * @param {String} type
-   *    The type of event.
-   * @param {Function} listener
-   *    The listener function that processes the event.
-   */
-  removeListener: function removeListener(type, listener) {
-    if ('function' !== typeof listener)
-      throw new Error(BAD_LISTENER);
-    let listeners = this._listeners(type),
-        index = listeners.indexOf(listener);
-    if (0 <= index)
-      listeners.splice(index, 1);
-    // Use of `_public` is required by the legacy traits code, that will go away
-    // once bug-637633 is fixed.
-    return this._public || this;
-  },
-
-  /**
-   * Hash of listeners on this EventEmitter.
-   */
-  _events: null,
-
-  /**
-   * Returns an array of listeners for the specified event `type`. This array
-   * can be manipulated, e.g. to remove listeners.
-   * @param {String} type
-   *    The type of event.
-   */
-  _listeners: function listeners(type) {
-    let events = this._events || (this._events = {});
-    return (events.hasOwnProperty(type) && events[type]) || (events[type] = []);
-  },
-
-  /**
-   * Execute each of the listeners in order with the supplied arguments.
-   * Returns `true` if listener for this event was called, `false` if there are
-   * no listeners for this event `type`.
-   *
-   * All the exceptions that are thrown by listeners during the emit
-   * are caught and can be handled by listeners of 'error' event. Thrown
-   * exceptions are passed as an argument to an 'error' event listener.
-   * If no 'error' listener is registered exception will propagate to a
-   * caller of this method.
-   *
-   * **It's recommended to have a default 'error' listener in all the complete
-   * composition that in worst case may dump errors to the console.**
-   *
-   * @param {String} type
-   *    The type of event.
-   * @params {Object|Number|String|Boolean}
-   *    Arguments that will be passed to listeners.
-   * @returns {Boolean}
-   */
-  _emit: function _emit(type, event) {
-    let args = Array.slice(arguments);
-    // Use of `_public` is required by the legacy traits code that will go away
-    // once bug-637633 is fixed.
-    args.unshift(this._public || this);
-    return this._emitOnObject.apply(this, args);
-  },
-
-  /**
-   * A version of _emit that lets you specify the object on which listeners are
-   * called.  This is a hack that is sometimes necessary when such an object
-   * (exports, for example) cannot be an EventEmitter for some reason, but other
-   * object(s) managing events for the object are EventEmitters.  Once bug
-   * 577782 is fixed, this method shouldn't be necessary.
-   *
-   * @param {object} targetObj
-   *    The object on which listeners will be called.
-   * @param {string} type
-   *    The event name.
-   * @param {value} event
-   *    The first argument to pass to listeners.
-   * @param {value} ...
-   *    More arguments to pass to listeners.
-   * @returns {boolean}
-   */
-  _emitOnObject: function _emitOnObject(targetObj, type, event /* , ... */) {
-    let listeners = this._listeners(type).slice(0);
-    // If there is no 'error' event listener then throw.
-    if (type === ERROR_TYPE && !listeners.length)
-      console.exception(event);
-    if (!listeners.length)
-      return false;
-    let params = Array.slice(arguments, 2);
-    for (let listener of listeners) {
-      try {
-        listener.apply(targetObj, params);
-      } catch(e) {
-        // Bug 726967: Ignore exceptions being throws while notifying the error
-        // in order to avoid infinite loops.
-        if (type !== ERROR_TYPE)
-          this._emit(ERROR_TYPE, e);
-        else
-          console.exception("Exception in error event listener " + e);
-      }
-    }
-    return true;
-  },
-
-  /**
-   * Removes all the event listeners for the specified event `type`.
-   * @param {String} type
-   *    The type of event.
-   */
-  _removeAllListeners: function _removeAllListeners(type) {
-    if (typeof type == "undefined") {
-      this._events = null;
-      return this;
-    }
-
-    this._listeners(type).splice(0);
-    return this;
-  }
-};
-exports.EventEmitter = require("./traits").Trait.compose(eventEmitter);
-exports.EventEmitterTrait = require('./light-traits').Trait(eventEmitter);
--- a/addon-sdk/source/lib/sdk/deprecated/events/assembler.js
+++ b/addon-sdk/source/lib/sdk/deprecated/events/assembler.js
@@ -1,20 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
 "use strict";
 
 const { Class } = require("../../core/heritage");
 const { removeListener, on } = require("../../dom/events");
 
 /**
- * Trait may be used for building objects / composing traits that wish to handle
- * multiple dom events from multiple event targets in one place. Event targets
+ * Event targets
  * can be added / removed by calling `observe / ignore` methods. Composer should
  * provide array of event types it wishes to handle as property
  * `supportedEventsTypes` and function for handling all those events as
  * `handleEvent` property.
  */
 exports.DOMEventAssembler = Class({
   /**
    * Function that is supposed to handle all the supported events (that are
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/light-traits.js
+++ /dev/null
@@ -1,599 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-// `var` is being used in the module in order to make it reusable in
-// environments in which `let` is not yet supported.
-
-// Shortcut to `Object.prototype.hasOwnProperty.call`.
-// owns(object, name) would be the same as
-// Object.prototype.hasOwnProperty.call(object, name);
-var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
-
-/**
- * Whether or not given property descriptors are equivalent. They are
- * equivalent either if both are marked as 'conflict' or 'required' property
- * or if all the properties of descriptors are equal.
- * @param {Object} actual
- * @param {Object} expected
- */
-function equivalentDescriptors(actual, expected) {
-  return (actual.conflict && expected.conflict) ||
-         (actual.required && expected.required) ||
-         equalDescriptors(actual, expected);
-}
-/**
- * Whether or not given property descriptors define equal properties.
- */
-function equalDescriptors(actual, expected) {
-  return actual.get === expected.get &&
-         actual.set === expected.set &&
-         actual.value === expected.value &&
-         !!actual.enumerable === !!expected.enumerable &&
-         !!actual.configurable === !!expected.configurable &&
-         !!actual.writable === !!expected.writable;
-}
-
-// Utilities that throwing exceptions for a properties that are marked
-// as "required" or "conflict" properties.
-function throwConflictPropertyError(name) {
-  throw new Error("Remaining conflicting property: `" + name + "`");
-}
-function throwRequiredPropertyError(name) {
-  throw new Error("Missing required property: `" + name + "`");
-}
-
-/**
- * Generates custom **required** property descriptor. Descriptor contains
- * non-standard property `required` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function RequiredPropertyDescriptor(name) {
-  // Creating function by binding first argument to a property `name` on the
-  // `throwConflictPropertyError` function. Created function is used as a
-  // getter & setter of the created property descriptor. This way we ensure
-  // that we throw exception late (on property access) if object with
-  // `required` property was instantiated using built-in `Object.create`.
-  var accessor = throwRequiredPropertyError.bind(null, name);
-  return { get: accessor, set: accessor, required: true };
-}
-
-/**
- * Generates custom **conflicting** property descriptor. Descriptor contains
- * non-standard property `conflict` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function ConflictPropertyDescriptor(name) {
-  // For details see `RequiredPropertyDescriptor` since idea is same.
-  var accessor = throwConflictPropertyError.bind(null, name);
-  return { get: accessor, set: accessor, conflict: true };
-}
-
-/**
- * Tests if property is marked as `required` property.
- */
-function isRequiredProperty(object, name) {
-  return !!object[name].required;
-}
-
-/**
- * Tests if property is marked as `conflict` property.
- */
-function isConflictProperty(object, name) {
-  return !!object[name].conflict;
-}
-
-/**
- * Function tests whether or not method of the `source` object with a given
- * `name` is inherited from `Object.prototype`.
- */
-function isBuiltInMethod(name, source) {
-  var target = Object.prototype[name];
-
-  // If methods are equal then we know it's `true`.
-  return target == source ||
-  // If `source` object comes form a different sandbox `==` will evaluate
-  // to `false`, in that case we check if functions names and sources match.
-         (String(target) === String(source) && target.name === source.name);
-}
-
-/**
- * Function overrides `toString` and `constructor` methods of a given `target`
- * object with a same-named methods of a given `source` if methods of `target`
- * object are inherited / copied from `Object.prototype`.
- * @see create
- */
-function overrideBuiltInMethods(target, source) {
-  if (isBuiltInMethod("toString", target.toString)) {
-    Object.defineProperty(target, "toString",  {
-      value: source.toString,
-      configurable: true,
-      enumerable: false
-    });
-  }
-
-  if (isBuiltInMethod("constructor", target.constructor)) {
-    Object.defineProperty(target, "constructor", {
-      value: source.constructor,
-      configurable: true,
-      enumerable: false
-    });
-  }
-}
-
-/**
- * Composes new trait with the same own properties as the original trait,
- * except that all property names appearing in the first argument are replaced
- * by "required" property descriptors.
- * @param {String[]} keys
- *    Array of strings property names.
- * @param {Object} trait
- *    A trait some properties of which should be excluded.
- * @returns {Object}
- * @example
- *    var newTrait = exclude(["name", ...], trait)
- */
-function exclude(names, trait) {
-  var map = {};
-
-  Object.keys(trait).forEach(function(name) {
-
-    // If property is not excluded (the array of names does not contain it),
-    // or it is a "required" property, copy it to the property descriptor `map`
-    // that will be used for creation of resulting trait.
-    if (!~names.indexOf(name) || isRequiredProperty(trait, name))
-      map[name] = { value: trait[name], enumerable: true };
-
-    // For all the `names` in the exclude name array we create required
-    // property descriptors and copy them to the `map`.
-    else
-      map[name] = { value: RequiredPropertyDescriptor(name), enumerable: true };
-  });
-
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- * Composes new instance of `Trait` with a properties of a given `trait`,
- * except that all properties whose name is an own property of `renames` will
- * be renamed to `renames[name]` and a `"required"` property for name will be
- * added instead.
- *
- * For each renamed property, a required property is generated. If
- * the `renames` map two properties to the same name, a conflict is generated.
- * If the `renames` map a property to an existing unrenamed property, a
- * conflict is generated.
- *
- * @param {Object} renames
- *    An object whose own properties serve as a mapping from old names to new
- *    names.
- * @param {Object} trait
- *    A new trait with renamed properties.
- * @returns {Object}
- * @example
- *
- *    // Return trait with `bar` property equal to `trait.foo` and with
- *    // `foo` and `baz` "required" properties.
- *    var renamedTrait = rename({ foo: "bar", baz: null }), trait);
- *
- *    // t1 and t2 are equivalent traits
- *    var t1 = rename({a: "b"}, t);
- *    var t2 = compose(exclude(["a"], t), { a: { required: true }, b: t[a] });
- */
-function rename(renames, trait) {
-  var map = {};
-
-  // Loop over all the properties of the given `trait` and copy them to a
-  // property descriptor `map` that will be used for the creation of the
-  // resulting trait.  Also, rename properties in the `map` as specified by
-  // `renames`.
-  Object.keys(trait).forEach(function(name) {
-    var alias;
-
-    // If the property is in the `renames` map, and it isn't a "required"
-    // property (which should never need to be aliased because "required"
-    // properties never conflict), then we must try to rename it.
-    if (owns(renames, name) && !isRequiredProperty(trait, name)) {
-      alias = renames[name];
-
-      // If the `map` already has the `alias`, and it isn't a "required"
-      // property, that means the `alias` conflicts with an existing name for a
-      // provided trait (that can happen if >=2 properties are aliased to the
-      // same name). In this case we mark it as a conflicting property.
-      // Otherwise, everything is fine, and we copy property with an `alias`
-      // name.
-      if (owns(map, alias) && !map[alias].value.required) {
-        map[alias] = {
-          value: ConflictPropertyDescriptor(alias),
-          enumerable: true
-        };
-      }
-      else {
-        map[alias] = {
-          value: trait[name],
-          enumerable: true
-        };
-      }
-
-      // Regardless of whether or not the rename was successful, we check to
-      // see if the original `name` exists in the map (such a property
-      // could exist if previous another property was aliased to this `name`).
-      // If it isn't, we mark it as "required", to make sure the caller
-      // provides another value for the old name, which methods of the trait
-      // might continue to reference.
-      if (!owns(map, name)) {
-        map[name] = {
-          value: RequiredPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-    }
-
-    // Otherwise, either the property isn't in the `renames` map (thus the
-    // caller is not trying to rename it) or it is a "required" property.
-    // Either way, we don't have to alias the property, we just have to copy it
-    // to the map.
-    else {
-      // The property isn't in the map yet, so we copy it over.
-      if (!owns(map, name)) {
-        map[name] = { value: trait[name], enumerable: true };
-      }
-
-      // The property is already in the map (that means another property was
-      // aliased with this `name`, which creates a conflict if the property is
-      // not marked as "required"), so we have to mark it as a "conflict"
-      // property.
-      else if (!isRequiredProperty(trait, name)) {
-        map[name] = {
-          value: ConflictPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-    }
-  });
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- * Composes new resolved trait, with all the same properties as the original
- * `trait`, except that all properties whose name is an own property of
- * `resolutions` will be renamed to `resolutions[name]`.
- *
- * If `resolutions[name]` is `null`, the value is mapped to a property
- * descriptor that is marked as a "required" property.
- */
-function resolve(resolutions, trait) {
-    var renames = {};
-    var exclusions = [];
-
-    // Go through each mapping in `resolutions` object and distribute it either
-    // to `renames` or `exclusions`.
-    Object.keys(resolutions).forEach(function(name) {
-
-      // If `resolutions[name]` is a truthy value then it's a mapping old -> new
-      // so we copy it to `renames` map.
-      if (resolutions[name])
-        renames[name] = resolutions[name];
-
-      // Otherwise it's not a mapping but an exclusion instead in which case we
-      // add it to the `exclusions` array.
-      else
-        exclusions.push(name);
-    });
-
-    // First `exclude` **then** `rename` and order is important since
-    // `exclude` and `rename` are not associative.
-    return rename(renames, exclude(exclusions, trait));
-}
-
-/**
- * Create a Trait (a custom property descriptor map) that represents the given
- * `object`'s own properties. Property descriptor map is a "custom", because it
- * inherits from `Trait.prototype` and it's property descriptors may contain
- * two attributes that is not part of the ES5 specification:
- *
- *  - "required" (this property must be provided by another trait
- *    before an instance of this trait can be created)
- *  - "conflict" (when the trait is composed with another trait,
- *    a unique value for this property is provided by two or more traits)
- *
- * Data properties bound to the `Trait.required` singleton exported by
- * this module will be marked as "required" properties.
- *
- * @param {Object} object
- *    Map of properties to compose trait from.
- * @returns {Trait}
- *    Trait / Property descriptor map containing all the own properties of the
- *    given argument.
- */
-function trait(object) {
-  var map;
-  var trait = object;
-
-  if (!(object instanceof Trait)) {
-    // If the passed `object` is not already an instance of `Trait`, we create
-    // a property descriptor `map` containing descriptors for the own properties
-    // of the given `object`.  `map` is then used to create a `Trait` instance
-    // after all properties are mapped.  Note that we can't create a trait and
-    // then just copy properties into it since that will fail for inherited
-    // read-only properties.
-    map = {};
-
-    // Each own property of the given `object` is mapped to a data property
-    // whose value is a property descriptor.
-    Object.keys(object).forEach(function (name) {
-
-      // If property of an `object` is equal to a `Trait.required`, it means
-      // that it was marked as "required" property, in which case we map it
-      // to "required" property.
-      if (Trait.required ==
-          Object.getOwnPropertyDescriptor(object, name).value) {
-        map[name] = {
-          value: RequiredPropertyDescriptor(name),
-          enumerable: true
-        };
-      }
-      // Otherwise property is mapped to it's property descriptor.
-      else {
-        map[name] = {
-          value: Object.getOwnPropertyDescriptor(object, name),
-          enumerable: true
-        };
-      }
-    });
-
-    trait = Object.create(Trait.prototype, map);
-  }
-  return trait;
-}
-
-/**
- * Compose a property descriptor map that inherits from `Trait.prototype` and
- * contains property descriptors for all the own properties of the passed
- * traits.
- *
- * If two or more traits have own properties with the same name, the returned
- * trait will contain a "conflict" property for that name. Composition is a
- * commutative and associative operation, and the order of its arguments is
- * irrelevant.
- */
-function compose(trait1, trait2/*, ...*/) {
-  // Create a new property descriptor `map` to which all the own properties
-  // of the passed traits are copied.  This map will be used to create a `Trait`
-  // instance that will be the result of this composition.
-  var map = {};
-
-  // Properties of each passed trait are copied to the composition.
-  Array.prototype.forEach.call(arguments, function(trait) {
-    // Copying each property of the given trait.
-    Object.keys(trait).forEach(function(name) {
-
-      // If `map` already owns a property with the `name` and it is not
-      // marked "required".
-      if (owns(map, name) && !map[name].value.required) {
-
-        // If the source trait's property with the `name` is marked as
-        // "required", we do nothing, as the requirement was already resolved
-        // by a property in the `map` (because it already contains a
-        // non-required property with that `name`).  But if properties are just
-        // different, we have a name clash and we substitute it with a property
-        // that is marked "conflict".
-        if (!isRequiredProperty(trait, name) &&
-            !equivalentDescriptors(map[name].value, trait[name])
-        ) {
-          map[name] = {
-            value: ConflictPropertyDescriptor(name),
-            enumerable: true
-          };
-        }
-      }
-
-      // Otherwise, the `map` does not have an own property with the `name`, or
-      // it is marked "required".  Either way, the trait's property is copied to
-      // the map (if the property of the `map` is marked "required", it is going
-      // to be resolved by the property that is being copied).
-      else {
-        map[name] = { value: trait[name], enumerable: true };
-      }
-    });
-  });
-
-  return Object.create(Trait.prototype, map);
-}
-
-/**
- *  `defineProperties` is like `Object.defineProperties`, except that it
- *  ensures that:
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "required" property and same named property is not
- *      found in a given `prototype`.
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "conflict" property.
- * @param {Object} object
- *    Object to define properties on.
- * @param {Object} properties
- *    Properties descriptor map.
- * @returns {Object}
- *    `object` that was passed as a first argument.
- */
-function defineProperties(object, properties) {
-
-  // Create a map into which we will copy each verified property from the given
-  // `properties` description map. We use it to verify that none of the
-  // provided properties is marked as a "conflict" property and that all
-  // "required" properties are resolved by a property of an `object`, so we
-  // can throw an exception before mutating object if that isn't the case.
-  var verifiedProperties = {};
-
-  // Coping each property from a given `properties` descriptor map to a
-  // verified map of property descriptors.
-  Object.keys(properties).forEach(function(name) {
-
-    // If property is marked as "required" property and we don't have a same
-    // named property in a given `object` we throw an exception. If `object`
-    // has same named property just skip this property since required property
-    // is was inherited and there for requirement was satisfied.
-    if (isRequiredProperty(properties, name)) {
-      if (!(name in object))
-        throwRequiredPropertyError(name);
-    }
-
-    // If property is marked as "conflict" property we throw an exception.
-    else if (isConflictProperty(properties, name)) {
-      throwConflictPropertyError(name);
-    }
-
-    // If property is not marked neither as "required" nor "conflict" property
-    // we copy it to verified properties map.
-    else {
-      verifiedProperties[name] = properties[name];
-    }
-  });
-
-  // If no exceptions were thrown yet, we know that our verified property
-  // descriptor map has no properties marked as "conflict" or "required",
-  // so we just delegate to the built-in `Object.defineProperties`.
-  return Object.defineProperties(object, verifiedProperties);
-}
-
-/**
- *  `create` is like `Object.create`, except that it ensures that:
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "required" property and same named property is not
- *      found in a given `prototype`.
- *    - An exception is thrown if any property in a given `properties` map
- *      is marked as "conflict" property.
- * @param {Object} prototype
- *    prototype of the composed object
- * @param {Object} properties
- *    Properties descriptor map.
- * @returns {Object}
- *    An object that inherits form a given `prototype` and implements all the
- *    properties defined by a given `properties` descriptor map.
- */
-function create(prototype, properties) {
-
-  // Creating an instance of the given `prototype`.
-  var object = Object.create(prototype);
-
-  // Overriding `toString`, `constructor` methods if they are just inherited
-  // from `Object.prototype` with a same named methods of the `Trait.prototype`
-  // that will have more relevant behavior.
-  overrideBuiltInMethods(object, Trait.prototype);
-
-  // Trying to define given `properties` on the `object`. We use our custom
-  // `defineProperties` function instead of build-in `Object.defineProperties`
-  // that behaves exactly the same, except that it will throw if any
-  // property in the given `properties` descriptor is marked as "required" or
-  // "conflict" property.
-  return defineProperties(object, properties);
-}
-
-/**
- * Composes new trait. If two or more traits have own properties with the
- * same name, the new trait will contain a "conflict" property for that name.
- * "compose" is a commutative and associative operation, and the order of its
- * arguments is not significant.
- *
- * **Note:** Use `Trait.compose` instead of calling this function with more
- * than one argument. The multiple-argument functionality is strictly for
- * backward compatibility.
- *
- * @params {Object} trait
- *    Takes traits as an arguments
- * @returns {Object}
- *    New trait containing the combined own properties of all the traits.
- * @example
- *    var newTrait = compose(trait_1, trait_2, ..., trait_N)
- */
-function Trait(trait1, trait2) {
-
-  // If the function was called with one argument, the argument should be
-  // an object whose properties are mapped to property descriptors on a new
-  // instance of Trait, so we delegate to the trait function.
-  // If the function was called with more than one argument, those arguments
-  // should be instances of Trait or plain property descriptor maps
-  // whose properties should be mixed into a new instance of Trait,
-  // so we delegate to the compose function.
-
-  return trait2 === undefined ? trait(trait1) : compose.apply(null, arguments);
-}
-
-Object.freeze(Object.defineProperties(Trait.prototype, {
-  toString: {
-    value: function toString() {
-      return "[object " + this.constructor.name + "]";
-    }
-  },
-
-  /**
-   * `create` is like `Object.create`, except that it ensures that:
-   *    - An exception is thrown if this trait defines a property that is
-   *      marked as required property and same named property is not
-   *      found in a given `prototype`.
-   *    - An exception is thrown if this trait contains property that is
-   *      marked as "conflict" property.
-   * @param {Object}
-   *    prototype of the compared object
-   * @returns {Object}
-   *    An object with all of the properties described by the trait.
-   */
-  create: {
-    value: function createTrait(prototype) {
-      return create(undefined === prototype ? Object.prototype : prototype,
-                    this);
-    },
-    enumerable: true
-  },
-
-  /**
-   * Composes a new resolved trait, with all the same properties as the original
-   * trait, except that all properties whose name is an own property of
-   * `resolutions` will be renamed to the value of `resolutions[name]`. If
-   * `resolutions[name]` is `null`, the property is marked as "required".
-   * @param {Object} resolutions
-   *   An object whose own properties serve as a mapping from old names to new
-   *   names, or to `null` if the property should be excluded.
-   * @returns {Object}
-   *   New trait with the same own properties as the original trait but renamed.
-   */
-  resolve: {
-    value: function resolveTrait(resolutions) {
-      return resolve(resolutions, this);
-    },
-    enumerable: true
-  }
-}));
-
-/**
- * @see compose
- */
-Trait.compose = Object.freeze(compose);
-Object.freeze(compose.prototype);
-
-/**
- * Constant singleton, representing placeholder for required properties.
- * @type {Object}
- */
-Trait.required = Object.freeze(Object.create(Object.prototype, {
-  toString: {
-    value: Object.freeze(function toString() {
-      return "<Trait.required>";
-    })
-  }
-}));
-Object.freeze(Trait.required.toString.prototype);
-
-exports.Trait = Object.freeze(Trait);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/list.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "experimental"
-};
-
-const { Trait } = require('../deprecated/traits');
-
-/**
- * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/util_list
- */
-const Iterable = Trait.compose({
-  /**
-   * Hash map of key-values to iterate over.
-   * Note: That this property can be a getter if you need dynamic behavior.
-   * @type {Object}
-   */
-  _keyValueMap: Trait.required,
-  /**
-   * Custom iterator providing `Iterable`s enumeration behavior.
-   * @param {Boolean} onKeys
-   */
-  __iterator__: function __iterator__(onKeys, onKeyValue) {
-    let map = this._keyValueMap;
-    for (let key in map)
-      yield onKeyValue ? [key, map[key]] : onKeys ? key : map[key];
-  }
-});
-exports.Iterable = Iterable;
-
-/**
- * An ordered collection (also known as a sequence) disallowing duplicate
- * elements. List is composed out of `Iterable` there for it provides custom
- * enumeration behavior that is similar to array (enumerates only on the
- * elements of the list). List is a base trait and is meant to be a part of
- * composition, since all of it's API is private except length property.
- */
-const listOptions = {
-  _keyValueMap: null,
-  /**
-   * List constructor can take any number of element to populate itself.
-   * @params {Object|String|Number} element
-   * @example
-   *    List(1,2,3).length == 3 // true
-   */
-  constructor: function List() {
-    this._keyValueMap = [];
-    for (let i = 0, ii = arguments.length; i < ii; i++)
-      this._add(arguments[i]);
-  },
-  /**
-   * Number of elements in this list.
-   * @type {Number}
-   */
-  get length() this._keyValueMap.length,
-   /**
-    * Returns a string representing this list.
-    * @returns {String}
-    */
-  toString: function toString() 'List(' + this._keyValueMap + ')',
-  /**
-   * Returns `true` if this list contains the specified `element`.
-   * @param {Object|Number|String} element
-   * @returns {Boolean}
-   */
-  _has: function _has(element) 0 <= this._keyValueMap.indexOf(element),
-  /**
-   * Appends the specified `element` to the end of this list, if it doesn't
-   * contains it. Ignores the call if `element` is already contained.
-   * @param {Object|Number|String} element
-   */
-  _add: function _add(element) {
-    let list = this._keyValueMap,
-        index = list.indexOf(element);
-    if (0 > index)
-      list.push(this._public[list.length] = element);
-  },
-  /**
-   * Removes specified `element` from this list, if it contains it.
-   * Ignores the call if `element` is not contained.
-   * @param {Object|Number|String} element
-   */
-  _remove: function _remove(element) {
-    let list = this._keyValueMap,
-        index = list.indexOf(element);
-    if (0 <= index) {
-      delete this._public[list.length - 1];
-      list.splice(index, 1);
-      for (let length = list.length; index < length; index++)
-        this._public[index] = list[index];
-    }
-  },
-  /**
-   * Removes all of the elements from this list.
-   */
-  _clear: function _clear() {
-    for (let i = 0, ii = this._keyValueMap.length; i < ii; i ++)
-      delete this._public[i];
-    this._keyValueMap.splice(0);
-  },
-  /**
-   * Custom iterator providing `List`s enumeration behavior.
-   * We cant reuse `_iterator` that is defined by `Iterable` since it provides
-   * iteration in an arbitrary order.
-   * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
-   * @param {Boolean} onKeys
-   */
-  __iterator__: function __iterator__(onKeys, onKeyValue) {
-    let array = this._keyValueMap.slice(0),
-        i = -1;
-    for (let element of array)
-      yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
-  },
-};
-listOptions[Symbol.iterator] = function* iterator() {
-  let array = this._keyValueMap.slice(0);
-
-  for (let element of array)
-    yield element;
-}
-const List = Trait.resolve({ toString: null }).compose(listOptions);
-exports.List = List;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/symbiont.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const { Worker } = require('./traits-worker');
-const { Loader } = require('../content/loader');
-const hiddenFrames = require('../frame/hidden-frame');
-const { on, off } = require('../system/events');
-const unload = require('../system/unload');
-const { getDocShell } = require("../frame/utils");
-const { ignoreWindow } = require('../private-browsing/utils');
-
-// Everything coming from add-on's xpi considered an asset.
-const assetsURI = require('../self').data.url().replace(/data\/$/, "");
-
-/**
- * This trait is layered on top of `Worker` and in contrast to symbiont
- * Worker constructor requires `content` option that represents content
- * that will be loaded in the provided frame, if frame is not provided
- * Worker will create hidden one.
- */
-const Symbiont = Worker.resolve({
-    constructor: '_initWorker',
-    destroy: '_workerDestroy'
-  }).compose(Loader, {
-
-  /**
-   * The constructor requires all the options that are required by
-   * `require('content').Worker` with the difference that the `frame` option
-   * is optional. If `frame` is not provided, `contentURL` is expected.
-   * @param {Object} options
-   * @param {String} options.contentURL
-   *    URL of a content to load into `this._frame` and create worker for.
-   * @param {Element} [options.frame]
-   *    iframe element that is used to load `options.contentURL` into.
-   *    if frame is not provided hidden iframe will be created.
-   */
-  constructor: function Symbiont(options) {
-    options = options || {};
-
-    if ('contentURL' in options)
-        this.contentURL = options.contentURL;
-    if ('contentScriptWhen' in options)
-      this.contentScriptWhen = options.contentScriptWhen;
-    if ('contentScriptOptions' in options)
-      this.contentScriptOptions = options.contentScriptOptions;
-    if ('contentScriptFile' in options)
-      this.contentScriptFile = options.contentScriptFile;
-    if ('contentScript' in options)
-      this.contentScript = options.contentScript;
-    if ('allow' in options)
-      this.allow = options.allow;
-    if ('onError' in options)
-        this.on('error', options.onError);
-    if ('onMessage' in options)
-        this.on('message', options.onMessage);
-    if ('frame' in options) {
-      this._initFrame(options.frame);
-    }
-    else {
-      let self = this;
-      this._hiddenFrame = hiddenFrames.HiddenFrame({
-        onReady: function onFrame() {
-          self._initFrame(this.element);
-        },
-        onUnload: function onUnload() {
-          // Bug 751211: Remove reference to _frame when hidden frame is
-          // automatically removed on unload, otherwise we are going to face
-          // "dead object" exception
-          self.destroy();
-        }
-      });
-      hiddenFrames.add(this._hiddenFrame);
-    }
-
-    unload.ensure(this._public, "destroy");
-  },
-
-  destroy: function destroy() {
-    this._workerDestroy();
-    this._unregisterListener();
-    this._frame = null;
-    if (this._hiddenFrame) {
-      hiddenFrames.remove(this._hiddenFrame);
-      this._hiddenFrame = null;
-    }
-  },
-
-  /**
-   * XUL iframe or browser elements with attribute `type` being `content`.
-   * Used to create `ContentSymbiont` from.
-   * @type {nsIFrame|nsIBrowser}
-   */
-  _frame: null,
-
-  /**
-   * Listener to the `'frameReady"` event (emitted when `iframe` is ready).
-   * Removes listener, sets right permissions to the frame and loads content.
-   */
-  _initFrame: function _initFrame(frame) {
-    if (this._loadListener)
-      this._unregisterListener();
-
-    this._frame = frame;
-
-    if (getDocShell(frame)) {
-      this._reallyInitFrame(frame);
-    }
-    else {
-      if (this._waitForFrame) {
-        off('content-document-global-created', this._waitForFrame);
-      }
-      this._waitForFrame = this.__waitForFrame.bind(this, frame);
-      on('content-document-global-created', this._waitForFrame);
-    }
-  },
-
-  __waitForFrame: function _waitForFrame(frame, { subject: win }) {
-    if (frame.contentWindow == win) {
-      off('content-document-global-created', this._waitForFrame);
-      delete this._waitForFrame;
-      this._reallyInitFrame(frame);
-    }
-  },
-
-  _reallyInitFrame: function _reallyInitFrame(frame) {
-    getDocShell(frame).allowJavascript = this.allow.script;
-    frame.setAttribute("src", this._contentURL);
-
-    // Inject `addon` object in document if we load a document from
-    // one of our addon folder and if no content script are defined. bug 612726
-    let isDataResource =
-      typeof this._contentURL == "string" &&
-      this._contentURL.indexOf(assetsURI) == 0;
-    let hasContentScript =
-      (Array.isArray(this.contentScript) ? this.contentScript.length > 0
-                                             : !!this.contentScript) ||
-      (Array.isArray(this.contentScriptFile) ? this.contentScriptFile.length > 0
-                                             : !!this.contentScriptFile);
-    // If we have to inject `addon` we have to do it before document
-    // script execution, so during `start`:
-    this._injectInDocument = isDataResource && !hasContentScript;
-    if (this._injectInDocument)
-      this.contentScriptWhen = "start";
-
-    if ((frame.contentDocument.readyState == "complete" ||
-        (frame.contentDocument.readyState == "interactive" &&
-         this.contentScriptWhen != 'end' )) &&
-        frame.contentDocument.location == this._contentURL) {
-      // In some cases src doesn't change and document is already ready
-      // (for ex: when the user moves a widget while customizing toolbars.)
-      this._onInit();
-      return;
-    }
-
-    let self = this;
-
-    if ('start' == this.contentScriptWhen) {
-      this._loadEvent = 'start';
-      on('document-element-inserted',
-        this._loadListener = function onStart({ subject: doc }) {
-          let window = doc.defaultView;
-
-          if (ignoreWindow(window)) {
-            return;
-          }
-
-          if (window && window == frame.contentWindow) {
-            self._unregisterListener();
-            self._onInit();
-          }
-
-        });
-      return;
-    }
-
-    let eventName = 'end' == this.contentScriptWhen ? 'load' : 'DOMContentLoaded';
-    this._loadEvent = eventName;
-    frame.addEventListener(eventName,
-      this._loadListener = function _onReady(event) {
-
-        if (event.target != frame.contentDocument)
-          return;
-        self._unregisterListener();
-
-        self._onInit();
-
-      }, true);
-
-  },
-
-  /**
-   * Unregister listener that watchs for document being ready to be injected.
-   * This listener is registered in `Symbiont._initFrame`.
-   */
-  _unregisterListener: function _unregisterListener() {
-    if (this._waitForFrame) {
-      off('content-document-global-created', this._waitForFrame);
-      delete this._waitForFrame;
-    }
-
-    if (!this._loadListener)
-      return;
-    if (this._loadEvent == "start") {
-      off('document-element-inserted', this._loadListener);
-    }
-    else {
-      this._frame.removeEventListener(this._loadEvent, this._loadListener,
-                                      true);
-    }
-    this._loadListener = null;
-  },
-
-  /**
-   * Called by Symbiont itself when the frame is ready to load
-   * content scripts according to contentScriptWhen. Overloaded by Panel.
-   */
-  _onInit: function () {
-    this._initWorker({ window: this._frame.contentWindow });
-  }
-
-});
-exports.Symbiont = Symbiont;
--- a/addon-sdk/source/lib/sdk/deprecated/sync-worker.js
+++ b/addon-sdk/source/lib/sdk/deprecated/sync-worker.js
@@ -85,17 +85,17 @@ const Worker = Class({
       attach(this, options.window);
   },
 
   /**
    * Sends a message to the worker's global scope. Method takes single
    * argument, which represents data to be sent to the worker. The data may
    * be any primitive type value or `JSON`. Call of this method asynchronously
    * emits `message` event with data value in the global scope of this
-   * symbiont.
+   * worker.
    *
    * `message` event listeners can be set either by calling
    * `self.on` with a first argument string `"message"` or by
    * implementing `onMessage` function in the global scope of this worker.
    * @param {Number|String|JSON} data
    */
   postMessage: function (...data) {
     let model = modelFor(this);
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits-worker.js
+++ /dev/null
@@ -1,636 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- *
- * `deprecated/traits-worker` was previously `content/worker` and kept
- * only due to `deprecated/symbiont` using it, which is necessary for
- * `widget`, until that reaches deprecation EOL.
- *
- */
-
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const { Trait } = require('./traits');
-const { EventEmitter, EventEmitterTrait } = require('./events');
-const { Ci, Cu, Cc } = require('chrome');
-const timer = require('../timers');
-const { URL } = require('../url');
-const unload = require('../system/unload');
-const observers = require('../system/events');
-const { Cortex } = require('./cortex');
-const { sandbox, evaluate, load } = require("../loader/sandbox");
-const { merge } = require('../util/object');
-const { getInnerId } = require("../window/utils");
-const { getTabForWindow } = require('../tabs/helpers');
-const { getTabForContentWindow } = require('../tabs/utils');
-
-/* Trick the linker in order to ensure shipping these files in the XPI.
-  require('../content/content-worker.js');
-  Then, retrieve URL of these files in the XPI:
-*/
-let prefix = module.uri.split('deprecated/traits-worker.js')[0];
-const CONTENT_WORKER_URL = prefix + 'content/content-worker.js';
-
-// Fetch additional list of domains to authorize access to for each content
-// script. It is stored in manifest `metadata` field which contains
-// package.json data. This list is originaly defined by authors in
-// `permissions` attribute of their package.json addon file.
-const permissions = require('@loader/options').metadata['permissions'] || {};
-const EXPANDED_PRINCIPALS = permissions['cross-domain-content'] || [];
-
-const JS_VERSION = '1.8';
-
-const ERR_DESTROYED =
-  "Couldn't find the worker to receive this message. " +
-  "The script may not be initialized yet, or may already have been unloaded.";
-
-const ERR_FROZEN = "The page is currently hidden and can no longer be used " +
-                   "until it is visible again.";
-
-
-const WorkerSandbox = EventEmitter.compose({
-
-  /**
-   * Emit a message to the worker content sandbox
-   */
-  emit: function emit() {
-    // First ensure having a regular array
-    // (otherwise, `arguments` would be mapped to an object by `stringify`)
-    let array = Array.slice(arguments);
-    // JSON.stringify is buggy with cross-sandbox values,
-    // it may return "{}" on functions. Use a replacer to match them correctly.
-    function replacer(k, v) {
-      return typeof v === "function" ? undefined : v;
-    }
-    // Ensure having an asynchronous behavior
-    let self = this;
-    timer.setTimeout(function () {
-      self._emitToContent(JSON.stringify(array, replacer));
-    }, 0);
-  },
-
-  /**
-   * Synchronous version of `emit`.
-   * /!\ Should only be used when it is strictly mandatory /!\
-   *     Doesn't ensure passing only JSON values.
-   *     Mainly used by context-menu in order to avoid breaking it.
-   */
-  emitSync: function emitSync() {
-    let args = Array.slice(arguments);
-    return this._emitToContent(Cu.cloneInto(args, this._addonWorker._window));
-  },
-
-  /**
-   * Method called by the worker sandbox when it needs to send a message
-   */
-  _onContentEvent: function onContentEvent(args) {
-    // As `emit`, we ensure having an asynchronous behavior
-    let self = this;
-    timer.setTimeout(function () {
-      // We emit event to chrome/addon listeners
-      self._emit.apply(self, JSON.parse(args));
-    }, 0);
-  },
-
-  /**
-   * Configures sandbox and loads content scripts into it.
-   * @param {Worker} worker
-   *    content worker
-   */
-  constructor: function WorkerSandbox(worker) {
-    this._addonWorker = worker;
-
-    // Ensure that `emit` has always the right `this`
-    this.emit = this.emit.bind(this);
-    this.emitSync = this.emitSync.bind(this);
-
-    // We receive a wrapped window, that may be an xraywrapper if it's content
-    let window = worker._window;
-    let proto = window;
-
-    // Eventually use expanded principal sandbox feature, if some are given.
-    //
-    // But prevent it when the Worker isn't used for a content script but for
-    // injecting `addon` object into a Panel, Widget, ... scope.
-    // That's because:
-    // 1/ It is useless to use multiple domains as the worker is only used
-    // to communicate with the addon,
-    // 2/ By using it it would prevent the document to have access to any JS
-    // value of the worker. As JS values coming from multiple domain principals
-    // can't be accessed by "mono-principals" (principal with only one domain).
-    // Even if this principal is for a domain that is specified in the multiple
-    // domain principal.
-    let principals  = window;
-    let wantGlobalProperties = []
-    if (EXPANDED_PRINCIPALS.length > 0 && !worker._injectInDocument) {
-      principals = EXPANDED_PRINCIPALS.concat(window);
-      // We have to replace XHR constructor of the content document
-      // with a custom cross origin one, automagically added by platform code:
-      delete proto.XMLHttpRequest;
-      wantGlobalProperties.push("XMLHttpRequest");
-    }
-
-    // Create the sandbox and bind it to window in order for content scripts to
-    // have access to all standard globals (window, document, ...)
-    let content = this._sandbox = sandbox(principals, {
-      sandboxPrototype: proto,
-      wantXrays: !worker._injectInDocument,
-      wantGlobalProperties: wantGlobalProperties,
-      sameZoneAs: window,
-      metadata: {
-        SDKContentScript: true,
-        'inner-window-id': getInnerId(window)
-      }
-    });
-    // We have to ensure that window.top and window.parent are the exact same
-    // object than window object, i.e. the sandbox global object. But not
-    // always, in case of iframes, top and parent are another window object.
-    let top = window.top === window ? content : content.top;
-    let parent = window.parent === window ? content : content.parent;
-    merge(content, {
-      // We need "this === window === top" to be true in toplevel scope:
-      get window() content,
-      get top() top,
-      get parent() parent
-    });
-    // Use the Greasemonkey naming convention to provide access to the
-    // unwrapped window object so the content script can access document
-    // JavaScript values.
-    // NOTE: this functionality is experimental and may change or go away
-    // at any time!
-    //
-    // Note that because waivers aren't propagated between origins, we
-    // need the unsafeWindow getter to live in the sandbox.
-    var unsafeWindowGetter =
-      new content.Function('return window.wrappedJSObject || window;');
-    Object.defineProperty(content, 'unsafeWindow', {get: unsafeWindowGetter});
-
-
-    // Load trusted code that will inject content script API.
-    let ContentWorker = load(content, CONTENT_WORKER_URL);
-
-    // prepare a clean `self.options`
-    let options = 'contentScriptOptions' in worker ?
-      JSON.stringify( worker.contentScriptOptions ) :
-      undefined;
-
-    // Then call `inject` method and communicate with this script
-    // by trading two methods that allow to send events to the other side:
-    //   - `onEvent` called by content script
-    //   - `result.emitToContent` called by addon script
-    let chromeAPI = Cu.cloneInto({
-      timers: {
-        setTimeout: timer.setTimeout.bind(timer),
-        setInterval: timer.setInterval.bind(timer),
-        clearTimeout: timer.clearTimeout.bind(timer),
-        clearInterval: timer.clearInterval.bind(timer),
-      },
-      sandbox: {
-        evaluate: evaluate,
-      },
-    }, ContentWorker, {cloneFunctions: true});
-    let onEvent = Cu.exportFunction(this._onContentEvent.bind(this), ContentWorker);
-    let result = Cu.waiveXrays(ContentWorker).inject(content, chromeAPI, onEvent, options);
-    this._emitToContent = result;
-
-    // Handle messages send by this script:
-    let self = this;
-    // console.xxx calls
-    this.on("console", function consoleListener(kind) {
-      console[kind].apply(console, Array.slice(arguments, 1));
-    });
-
-    // self.postMessage calls
-    this.on("message", function postMessage(data) {
-      // destroyed?
-      if (self._addonWorker)
-        self._addonWorker._emit('message', data);
-    });
-
-    // self.port.emit calls
-    this.on("event", function portEmit(name, args) {
-      // destroyed?
-      if (self._addonWorker)
-        self._addonWorker._onContentScriptEvent.apply(self._addonWorker, arguments);
-    });
-
-    // unwrap, recreate and propagate async Errors thrown from content-script
-    this.on("error", function onError({instanceOfError, value}) {
-      if (self._addonWorker) {
-        let error = value;
-        if (instanceOfError) {
-          error = new Error(value.message, value.fileName, value.lineNumber);
-          error.stack = value.stack;
-          error.name = value.name;
-        }
-        self._addonWorker._emit('error', error);
-      }
-    });
-
-    // Inject `addon` global into target document if document is trusted,
-    // `addon` in document is equivalent to `self` in content script.
-    if (worker._injectInDocument) {
-      let win = window.wrappedJSObject ? window.wrappedJSObject : window;
-      Object.defineProperty(win, "addon", {
-          value: content.self,
-          configurable: true
-        }
-      );
-    }
-
-    // Inject our `console` into target document if worker doesn't have a tab
-    // (e.g Panel, PageWorker, Widget).
-    // `worker.tab` can't be used because bug 804935.
-    if (!getTabForContentWindow(window)) {
-      let win = window.wrappedJSObject ? window.wrappedJSObject : window;
-
-      // export our chrome console to content window as described here:
-      // https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
-      let con = Cu.createObjectIn(win);
-
-      let genPropDesc = function genPropDesc(fun) {
-        return { enumerable: true, configurable: true, writable: true,
-          value: console[fun] };
-      }
-
-      const properties = {
-        log: genPropDesc('log'),
-        info: genPropDesc('info'),
-        warn: genPropDesc('warn'),
-        error: genPropDesc('error'),
-        debug: genPropDesc('debug'),
-        trace: genPropDesc('trace'),
-        dir: genPropDesc('dir'),
-        group: genPropDesc('group'),
-        groupCollapsed: genPropDesc('groupCollapsed'),
-        groupEnd: genPropDesc('groupEnd'),
-        time: genPropDesc('time'),
-        timeEnd: genPropDesc('timeEnd'),
-        profile: genPropDesc('profile'),
-        profileEnd: genPropDesc('profileEnd'),
-        exception: genPropDesc('exception'),
-        assert: genPropDesc('assert'),
-        count: genPropDesc('count'),
-        table: genPropDesc('table'),
-        clear: genPropDesc('clear'),
-        dirxml: genPropDesc('dirxml'),
-        markTimeline: genPropDesc('markTimeline'),
-        timeline: genPropDesc('timeline'),
-        timelineEnd: genPropDesc('timelineEnd'),
-        timeStamp: genPropDesc('timeStamp'),
-      };
-
-      Object.defineProperties(con, properties);
-      Cu.makeObjectPropsNormal(con);
-
-      win.console = con;
-    };
-
-    // The order of `contentScriptFile` and `contentScript` evaluation is
-    // intentional, so programs can load libraries like jQuery from script URLs
-    // and use them in scripts.
-    let contentScriptFile = ('contentScriptFile' in worker) ? worker.contentScriptFile
-          : null,
-        contentScript = ('contentScript' in worker) ? worker.contentScript : null;
-
-    if (contentScriptFile) {
-      if (Array.isArray(contentScriptFile))
-        this._importScripts.apply(this, contentScriptFile);
-      else
-        this._importScripts(contentScriptFile);
-    }
-    if (contentScript) {
-      this._evaluate(
-        Array.isArray(contentScript) ? contentScript.join(';\n') : contentScript
-      );
-    }
-  },
-  destroy: function destroy() {
-    this.emitSync("detach");
-    this._sandbox = null;
-    this._addonWorker = null;
-  },
-
-  /**
-   * JavaScript sandbox where all the content scripts are evaluated.
-   * {Sandbox}
-   */
-  _sandbox: null,
-
-  /**
-   * Reference to the addon side of the worker.
-   * @type {Worker}
-   */
-  _addonWorker: null,
-
-  /**
-   * Evaluates code in the sandbox.
-   * @param {String} code
-   *    JavaScript source to evaluate.
-   * @param {String} [filename='javascript:' + code]
-   *    Name of the file
-   */
-  _evaluate: function(code, filename) {
-    try {
-      evaluate(this._sandbox, code, filename || 'javascript:' + code);
-    }
-    catch(e) {
-      this._addonWorker._emit('error', e);
-    }
-  },
-  /**
-   * Imports scripts to the sandbox by reading files under urls and
-   * evaluating its source. If exception occurs during evaluation
-   * `"error"` event is emitted on the worker.
-   * This is actually an analog to the `importScript` method in web
-   * workers but in our case it's not exposed even though content
-   * scripts may be able to do it synchronously since IO operation
-   * takes place in the UI process.
-   */
-  _importScripts: function _importScripts(url) {
-    let urls = Array.slice(arguments, 0);
-    for (let contentScriptFile of urls) {
-      try {
-        let uri = URL(contentScriptFile);
-        if (uri.scheme === 'resource')
-          load(this._sandbox, String(uri));
-        else
-          throw Error("Unsupported `contentScriptFile` url: " + String(uri));
-      }
-      catch(e) {
-        this._addonWorker._emit('error', e);
-      }
-    }
-  }
-});
-
-/**
- * Message-passing facility for communication between code running
- * in the content and add-on process.
- * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker
- */
-const Worker = EventEmitter.compose({
-  on: Trait.required,
-  _removeAllListeners: Trait.required,
-
-  // List of messages fired before worker is initialized
-  get _earlyEvents() {
-    delete this._earlyEvents;
-    this._earlyEvents = [];
-    return this._earlyEvents;
-  },
-
-  /**
-   * Sends a message to the worker's global scope. Method takes single
-   * argument, which represents data to be sent to the worker. The data may
-   * be any primitive type value or `JSON`. Call of this method asynchronously
-   * emits `message` event with data value in the global scope of this
-   * symbiont.
-   *
-   * `message` event listeners can be set either by calling
-   * `self.on` with a first argument string `"message"` or by
-   * implementing `onMessage` function in the global scope of this worker.
-   * @param {Number|String|JSON} data
-   */
-  postMessage: function (data) {
-    let args = ['message'].concat(Array.slice(arguments));
-    if (!this._inited) {
-      this._earlyEvents.push(args);
-      return;
-    }
-    processMessage.apply(this, args);
-  },
-
-  /**
-   * EventEmitter, that behaves (calls listeners) asynchronously.
-   * A way to send customized messages to / from the worker.
-   * Events from in the worker can be observed / emitted via
-   * worker.on / worker.emit.
-   */
-  get port() {
-    // We generate dynamically this attribute as it needs to be accessible
-    // before Worker.constructor gets called. (For ex: Panel)
-
-    // create an event emitter that receive and send events from/to the worker
-    this._port = EventEmitterTrait.create({
-      emit: this._emitEventToContent.bind(this)
-    });
-
-    // expose wrapped port, that exposes only public properties:
-    // We need to destroy this getter in order to be able to set the
-    // final value. We need to update only public port attribute as we never
-    // try to access port attribute from private API.
-    delete this._public.port;
-    this._public.port = Cortex(this._port);
-    // Replicate public port to the private object
-    delete this.port;
-    this.port = this._public.port;
-
-    return this._port;
-  },
-
-  /**
-   * Same object than this.port but private API.
-   * Allow access to _emit, in order to send event to port.
-   */
-  _port: null,
-
-  /**
-   * Emit a custom event to the content script,
-   * i.e. emit this event on `self.port`
-   */
-  _emitEventToContent: function () {
-    let args = ['event'].concat(Array.slice(arguments));
-    if (!this._inited) {
-      this._earlyEvents.push(args);
-      return;
-    }
-    processMessage.apply(this, args);
-  },
-
-  // Is worker connected to the content worker sandbox ?
-  _inited: false,
-
-  // Is worker being frozen? i.e related document is frozen in bfcache.
-  // Content script should not be reachable if frozen.
-  _frozen: true,
-
-  constructor: function Worker(options) {
-    options = options || {};
-
-    if ('contentScriptFile' in options)
-      this.contentScriptFile = options.contentScriptFile;
-    if ('contentScriptOptions' in options)
-      this.contentScriptOptions = options.contentScriptOptions;
-    if ('contentScript' in options)
-      this.contentScript = options.contentScript;
-
-    this._setListeners(options);
-
-    unload.ensure(this._public, "destroy");
-
-    // Ensure that worker._port is initialized for contentWorker to be able
-    // to send events during worker initialization.
-    this.port;
-
-    this._documentUnload = this._documentUnload.bind(this);
-    this._pageShow = this._pageShow.bind(this);
-    this._pageHide = this._pageHide.bind(this);
-
-    if ("window" in options) this._attach(options.window);
-  },
-
-  _setListeners: function(options) {
-    if ('onError' in options)
-      this.on('error', options.onError);
-    if ('onMessage' in options)
-      this.on('message', options.onMessage);
-    if ('onDetach' in options)
-      this.on('detach', options.onDetach);
-  },
-
-  _attach: function(window) {
-    this._window = window;
-    // Track document unload to destroy this worker.
-    // We can't watch for unload event on page's window object as it
-    // prevents bfcache from working:
-    // https://developer.mozilla.org/En/Working_with_BFCache
-    this._windowID = getInnerId(this._window);
-    observers.on("inner-window-destroyed", this._documentUnload);
-
-    // Listen to pagehide event in order to freeze the content script
-    // while the document is frozen in bfcache:
-    this._window.addEventListener("pageshow", this._pageShow, true);
-    this._window.addEventListener("pagehide", this._pageHide, true);
-
-    // will set this._contentWorker pointing to the private API:
-    this._contentWorker = WorkerSandbox(this);
-
-    // Mainly enable worker.port.emit to send event to the content worker
-    this._inited = true;
-    this._frozen = false;
-
-    // Process all events and messages that were fired before the
-    // worker was initialized.
-    this._earlyEvents.forEach((function (args) {
-      processMessage.apply(this, args);
-    }).bind(this));
-  },
-
-  _documentUnload: function _documentUnload({ subject, data }) {
-    let innerWinID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    if (innerWinID != this._windowID) return false;
-    this._workerCleanup();
-    return true;
-  },
-
-  _pageShow: function _pageShow() {
-    this._contentWorker.emitSync("pageshow");
-    this._emit("pageshow");
-    this._frozen = false;
-  },
-
-  _pageHide: function _pageHide() {
-    this._contentWorker.emitSync("pagehide");
-    this._emit("pagehide");
-    this._frozen = true;
-  },
-
-  get url() {
-    // this._window will be null after detach
-    return this._window ? this._window.document.location.href : null;
-  },
-
-  get tab() {
-    // this._window will be null after detach
-    if (this._window)
-      return getTabForWindow(this._window);
-    return null;
-  },
-
-  /**
-   * Tells content worker to unload itself and
-   * removes all the references from itself.
-   */
-  destroy: function destroy() {
-    this._workerCleanup();
-    this._inited = true;
-    this._removeAllListeners();
-  },
-
-  /**
-   * Remove all internal references to the attached document
-   * Tells _port to unload itself and removes all the references from itself.
-   */
-  _workerCleanup: function _workerCleanup() {
-    // maybe unloaded before content side is created
-    // As Symbiont call worker.constructor on document load
-    if (this._contentWorker)
-      this._contentWorker.destroy();
-    this._contentWorker = null;
-    if (this._window) {
-      this._window.removeEventListener("pageshow", this._pageShow, true);
-      this._window.removeEventListener("pagehide", this._pageHide, true);
-    }
-    this._window = null;
-    // This method may be called multiple times,
-    // avoid dispatching `detach` event more than once
-    if (this._windowID) {
-      this._windowID = null;
-      observers.off("inner-window-destroyed", this._documentUnload);
-      this._earlyEvents.length = 0;
-      this._emit("detach");
-    }
-    this._inited = false;
-  },
-
-  /**
-   * Receive an event from the content script that need to be sent to
-   * worker.port. Provide a way for composed object to catch all events.
-   */
-  _onContentScriptEvent: function _onContentScriptEvent() {
-    this._port._emit.apply(this._port, arguments);
-  },
-
-  /**
-   * Reference to the content side of the worker.
-   * @type {WorkerGlobalScope}
-   */
-  _contentWorker: null,
-
-  /**
-   * Reference to the window that is accessible from
-   * the content scripts.
-   * @type {Object}
-   */
-  _window: null,
-
-  /**
-   * Flag to enable `addon` object injection in document. (bug 612726)
-   * @type {Boolean}
-   */
-  _injectInDocument: false
-});
-
-/**
- * Fired from postMessage and _emitEventToContent, or from the _earlyMessage
- * queue when fired before the content is loaded. Sends arguments to
- * contentWorker if able
- */
-
-function processMessage () {
-  if (!this._contentWorker)
-    throw new Error(ERR_DESTROYED);
-  if (this._frozen)
-    throw new Error(ERR_FROZEN);
-
-  this._contentWorker.emit.apply(null, Array.slice(arguments));
-}
-
-exports.Worker = Worker;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits.js
+++ /dev/null
@@ -1,186 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-const {
-  compose: _compose,
-  override: _override,
-  resolve: _resolve,
-  trait: _trait,
-  //create: _create,
-  required,
-} = require('./traits/core');
-
-const { getOwnPropertyIdentifiers } = require('../util/object');
-const defineProperties = Object.defineProperties;
-const freeze = Object.freeze;
-const create = Object.create;
-
-/**
- * Work around bug 608959 by defining the _create function here instead of
- * importing it from traits/core.  For docs on this function, see the create
- * function in that module.
- *
- * FIXME: remove this workaround in favor of importing the function once that
- * bug has been fixed.
- */
-function _create(proto, trait) {
-  let properties = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    let descriptor = trait[key];
-    if (descriptor.required &&
-        !Object.prototype.hasOwnProperty.call(proto, key))
-      throw new Error('Missing required property: ' + key);
-    else if (descriptor.conflict)
-      throw new Error('Remaining conflicting property: ' + key);
-    else
-      properties[key] = descriptor;
-  }
-  return Object.create(proto, properties);
-}
-
-/**
- * Placeholder for `Trait.prototype`
- */
-let TraitProto = Object.prototype;
-
-function Get(key) this[key]
-function Set(key, value) this[key] = value
-
-/**
- * Creates anonymous trait descriptor from the passed argument, unless argument
- * is a trait constructor. In later case trait's already existing properties
- * descriptor is returned.
- * This is module's internal function and is used as a gateway to a trait's
- * internal properties descriptor.
- * @param {Function} $
- *    Composed trait's constructor.
- * @returns {Object}
- *    Private trait property of the composition.
- */
-function TraitDescriptor(object)
-  (
-    'function' == typeof object &&
-    (object.prototype == TraitProto || object.prototype instanceof Trait)
-  ) ? object._trait(TraitDescriptor) : _trait(object)
-
-function Public(instance, trait) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    if (typeof key === 'string' && '_' === key.charAt(0) && '__iterator__' !== key )
-      continue;
-    let property = trait[key],
-        descriptor = {
-          configurable: property.configurable,
-          enumerable: property.enumerable
-        };
-    if (property.get)
-      descriptor.get = property.get.bind(instance);
-    if (property.set)
-      descriptor.set = property.set.bind(instance);
-    if ('value' in property) {
-      let value = property.value;
-      if ('function' === typeof value) {
-        descriptor.value = property.value.bind(instance);
-        descriptor.writable = property.writable;
-      } else {
-        descriptor.get = Get.bind(instance, key);
-        descriptor.set = Set.bind(instance, key);
-      }
-    }
-    result[key] = descriptor;
-  }
-  return result;
-}
-
-/**
- * This is private function that composes new trait with privates.
- */
-function Composition(trait) {
-  function Trait() {
-    let self = _create({}, trait);
-    self._public = create(Trait.prototype, Public(self, trait));
-    delete self._public.constructor;
-    if (Object === self.constructor)
-      self.constructor = Trait;
-    else
-      return self.constructor.apply(self, arguments) || self._public;
-    return self._public;
-  }
-  defineProperties(Trait, {
-    prototype: { value: freeze(create(TraitProto, {
-      constructor: { value: constructor, writable: true }
-    }))}, // writable is `true` to avoid getters in custom ES5
-    displayName: { value: (trait.constructor || constructor).name },
-    compose: { value: compose, enumerable: true },
-    override: { value: override, enumerable: true },
-    resolve: { value: resolve, enumerable: true },
-    required: { value: required, enumerable: true },
-    _trait: { value: function _trait(caller)
-        caller ===  TraitDescriptor ? trait : undefined
-    }
-  });
-  return freeze(Trait);
-}
-
-/**
- * Composes new trait out of itself and traits / property maps passed as an
- * arguments. If two or more traits / property maps have properties with the
- * same name, the new trait will contain a "conflict" property for that name.
- * This is a commutative and associative operation, and the order of its
- * arguments is not significant.
- * @params {Object|Function}
- *    List of Traits or property maps to create traits from.
- * @returns {Function}
- *    New trait containing the combined properties of all the traits.
- */
-function compose() {
-  let traits = Array.slice(arguments, 0);
-  traits.push(this);
-  return Composition(_compose.apply(null, traits.map(TraitDescriptor)));
-}
-
-/**
- * Composes a new trait with all of the combined properties of `this` and the
- * argument traits. In contrast to `compose`, `override` immediately resolves
- * all conflicts resulting from this composition by overriding the properties of
- * later traits. Trait priority is from left to right. I.e. the properties of
- * the leftmost trait are never overridden.
- * @params {Object} trait
- * @returns {Object}
- */
-function override() {
-  let traits = Array.slice(arguments, 0);
-  traits.push(this);
-  return Composition(_override.apply(null, traits.map(TraitDescriptor)));
-}
-
-/**
- * Composes new resolved trait, with all the same properties as this
- * trait, except that all properties whose name is an own property of
- * `resolutions` will be renamed to `resolutions[name]`. If it is
- * `resolutions[name]` is `null` value is changed into a required property
- * descriptor.
- */
-function resolve(resolutions)
-  Composition(_resolve(resolutions, TraitDescriptor(this)))
-
-/**
- * Base Trait, that all the traits are composed of.
- */
-const Trait = Composition({
-  /**
-   * Internal property holding public API of this instance.
-   */
-  _public: { value: null, configurable: true, writable: true },
-  toString: { value: function() '[object ' + this.constructor.name + ']' }
-});
-TraitProto = Trait.prototype;
-exports.Trait = Trait;
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/deprecated/traits/core.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
-  "stability": "deprecated"
-};
-
-// Design inspired by: http://www.traitsjs.org/
-
-const { getOwnPropertyIdentifiers } = require('../../util/object');
-const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-const hasOwn = Object.prototype.hasOwnProperty;
-const _create = Object.create;
-
-function doPropertiesMatch(object1, object2, name) {
-  // If `object1` has property with the given `name`
-  return name in object1 ?
-         // then `object2` should have it with the same value.
-         name in object2 && object1[name] === object2[name] :
-         // otherwise `object2` should not have property with the given `name`.
-         !(name in object2);
-}
-
-/**
- * Compares two trait custom property descriptors if they are the same. If
- * both are `conflict` or all the properties of descriptor are equal returned
- * value will be `true`, otherwise it will be `false`.
- * @param {Object} desc1
- * @param {Object} desc2
- */
-function areSame(desc1, desc2) {
-  return ('conflict' in desc1 && desc1.conflict &&
-          'conflict' in desc2 && desc2.conflict) ||
-         (doPropertiesMatch(desc1, desc2, 'get') &&
-          doPropertiesMatch(desc1, desc2, 'set') &&
-          doPropertiesMatch(desc1, desc2, 'value') &&
-          doPropertiesMatch(desc1, desc2, 'enumerable') &&
-          doPropertiesMatch(desc1, desc2, 'required') &&
-          doPropertiesMatch(desc1, desc2, 'conflict'));
-}
-
-/**
- * Converts array to an object whose own property names represent
- * values of array.
- * @param {String[]} names
- * @returns {Object}
- * @example
- *  Map(['foo', ...]) => { foo: true, ...}
- */
-function Map(names) {
-  let map = {};
-  for (let name of names)
-    map[name] = true;
-  return map;
-}
-
-
-const ERR_CONFLICT = 'Remaining conflicting property: ',
-      ERR_REQUIRED = 'Missing required property: ';
-/**
- * Constant singleton, representing placeholder for required properties.
- * @type {Object}
- */
-const required = { toString: function()'<Trait.required>' };
-exports.required = required;
-
-/**
- * Generates custom **required** property descriptor. Descriptor contains
- * non-standard property `required` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function Required(name) {
-  function required() { throw new Error(ERR_REQUIRED + name) }
-  return {
-    get: required,
-    set: required,
-    required: true
-  };
-}
-
-/**
- * Generates custom **conflicting** property descriptor. Descriptor contains
- * non-standard property `conflict` that is equal to `true`.
- * @param {String} name
- *    property name to generate descriptor for.
- * @returns {Object}
- *    custom property descriptor
- */
-function Conflict(name) {
-  function conflict() { throw new Error(ERR_CONFLICT + name) }
-  return {
-    get: conflict,
-    set: conflict,
-    conflict: true
-  };
-}
-
-/**
- * Function generates custom properties descriptor of the `object`s own
- * properties. All the inherited properties are going to be ignored.
- * Properties with values matching `required` singleton will be marked as
- * 'required' properties.
- * @param {Object} object
- *    Set of properties to generate trait from.
- * @returns {Object}
- *    Properties descriptor of all of the `object`'s own properties.
- */
-function trait(properties) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(properties);
-  for (let key of keys) {
-    let descriptor = getOwnPropertyDescriptor(properties, key);
-    result[key] = (required === descriptor.value) ? Required(key) : descriptor;
-  }
-  return result;
-}
-exports.Trait = exports.trait = trait;
-
-/**
- * Composes new trait. If two or more traits have own properties with the
- * same name, the new trait will contain a 'conflict' property for that name.
- * 'compose' is a commutative and associative operation, and the order of its
- * arguments is not significant.
- *
- * @params {Object} trait
- *    Takes traits as an arguments
- * @returns {Object}
- *    New trait containing the combined own properties of all the traits.
- * @example
- *    var newTrait = compose(trait_1, trait_2, ..., trait_N);
- */
-function compose(trait1, trait2) {
-  let traits = Array.slice(arguments, 0),
-      result = {};
-  for (let trait of traits) {
-    let keys = getOwnPropertyIdentifiers(trait);
-    for (let key of keys) {
-      let descriptor = trait[key];
-      // if property already exists and it's not a requirement
-      if (hasOwn.call(result, key) && !result[key].required) {
-        if (descriptor.required)
-          continue;
-        if (!areSame(descriptor, result[key]))
-          result[key] = Conflict(key);
-      } else {
-        result[key] = descriptor;
-      }
-    }
-  }
-  return result;
-}
-exports.compose = compose;
-
-/**
- * Composes new trait with the same own properties as the original trait,
- * except that all property names appearing in the first argument are replaced
- * by 'required' property descriptors.
- * @param {String[]} keys
- *    Array of strings property names.
- * @param {Object} trait
- *    A trait some properties of which should be excluded.
- * @returns {Object}
- * @example
- *    var newTrait = exclude(['name', ...], trait)
- */
-function exclude(keys, trait) {
-  let exclusions = Map(keys),
-      result = {};
-
-  keys = getOwnPropertyIdentifiers(trait);
-
-  for (let key of keys) {
-    if (!hasOwn.call(exclusions, key) || trait[key].required)
-      result[key] = trait[key];
-    else
-      result[key] = Required(key);
-  }
-  return result;
-}
-
-/**
- * Composes a new trait with all of the combined properties of the argument
- * traits. In contrast to `compose`, `override` immediately resolves all
- * conflicts resulting from this composition by overriding the properties of
- * later traits. Trait priority is from left to right. I.e. the properties of
- * the leftmost trait are never overridden.
- * @params {Object} trait
- * @returns {Object}
- * @examples
- *    // override is associative:
- *    override(t1,t2,t3)
- *    // is equivalent to
- *    override(t1, override(t2, t3))
- *    // or
- *    to override(override(t1, t2), t3)
- *
- *    // override is not commutative:
- *    override(t1,t2)
- *    // is not equivalent to
- *    override(t2,t1)
- */
-function override() {
-  let traits = Array.slice(arguments, 0),
-      result = {};
-  for (let trait of traits) {
-    let keys = getOwnPropertyIdentifiers(trait);
-    for (let key of keys) {
-      let descriptor = trait[key];
-      if (!hasOwn.call(result, key) || result[key].required)
-        result[key] = descriptor;
-    }
-  }
-  return result;
-}
-exports.override = override;
-
-/**
- * Composes a new trait with the same properties as the original trait, except
- * that all properties whose name is an own property of map will be renamed to
- * map[name], and a 'required' property for name will be added instead.
- * @param {Object} map
- *    An object whose own properties serve as a mapping from old names to new
- *    names.
- * @param {Object} trait
- *    A trait object
- * @returns {Object}
- * @example
- *    var newTrait = rename(map, trait);
- */
-function rename(map, trait) {
-  let result = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    // must be renamed & it's not requirement
-    if (hasOwn.call(map, key) && !trait[key].required) {
-      let alias = map[key];
-      if (hasOwn.call(result, alias) && !result[alias].required)
-        result[alias] = Conflict(alias);
-      else
-        result[alias] = trait[key];
-      if (!hasOwn.call(result, key))
-        result[key] = Required(key);
-    } else { // must not be renamed or its a requirement
-      // property is not in result trait yet
-      if (!hasOwn.call(result, key))
-        result[key] = trait[key];
-      // property is already in resulted trait & it's not requirement
-      else if (!trait[key].required)
-        result[key] = Conflict(key);
-    }
-  }
-  return result;
-}
-
-/**
-* Composes new resolved trait, with all the same properties as the original
-* trait, except that all properties whose name is an own property of
-* resolutions will be renamed to `resolutions[name]`. If it is
-* `resolutions[name]` is `null` value is changed into a required property
-* descriptor.
-* function can be implemented as `rename(map,exclude(exclusions, trait))`
-* where map is the subset of mappings from oldName to newName and exclusions
-* is an array of all the keys that map to `null`.
-* Note: it's important to **first** `exclude`, **then** `rename`, since
-* `exclude` and rename are not associative.
-* @param {Object} resolutions
-*   An object whose own properties serve as a mapping from old names to new
-*   names, or to `null` if the property should be excluded.
-* @param {Object} trait
-*   A trait object
-* @returns {Object}
-*   Resolved trait with the same own properties as the original trait.
-*/
-function resolve(resolutions, trait) {
-  let renames = {},
-      exclusions = [],
-      keys = getOwnPropertyIdentifiers(resolutions);
-  for (let key of keys) {  // pre-process renamed and excluded properties
-    if (resolutions[key])       // old name -> new name
-      renames[key] = resolutions[key];
-    else                        // name -> undefined
-      exclusions.push(key);
-  }
-  return rename(renames, exclude(exclusions, trait));
-}
-exports.resolve = resolve;
-
-/**
- * `create` is like `Object.create`, except that it ensures that:
- *    - an exception is thrown if 'trait' still contains required properties
- *    - an exception is thrown if 'trait' still contains conflicting
- *      properties
- * @param {Object}
- *    prototype of the completed object
- * @param {Object} trait
- *    trait object to be turned into a complete object
- * @returns {Object}
- *    An object with all of the properties described by the trait.
- */
-function create(proto, trait) {
-  let properties = {},
-      keys = getOwnPropertyIdentifiers(trait);
-  for (let key of keys) {
-    let descriptor = trait[key];
-    if (descriptor.required && !hasOwn.call(proto, key))
-      throw new Error(ERR_REQUIRED + key);
-    else if (descriptor.conflict)
-      throw new Error(ERR_CONFLICT + key);
-    else
-      properties[key] = descriptor;
-  }
-  return _create(proto, properties);
-}
-exports.create = create;
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test.js
@@ -9,17 +9,17 @@ module.metadata = {
 
 const memory = require("./memory");
 const timer = require("../timers");
 const cfxArgs = require("../test/options");
 const { getTabs, closeTab, getURI, getTabId, getSelectedTab } = require("../tabs/utils");
 const { windows, isBrowser, getMostRecentBrowserWindow } = require("../window/utils");
 const { defer, all, Debugging: PromiseDebugging, resolve } = require("../core/promise");
 const { getInnerId } = require("../window/utils");
-const { cleanUI } = require("../test/utils")
+const { cleanUI } = require("../test/utils");
 
 const findAndRunTests = function findAndRunTests(options) {
   var TestFinder = require("./unit-test-finder").TestFinder;
   var finder = new TestFinder({
     filter: options.filter,
     testInProcess: options.testInProcess,
     testOutOfProcess: options.testOutOfProcess
   });
--- a/addon-sdk/source/lib/sdk/deprecated/window-utils.js
+++ b/addon-sdk/source/lib/sdk/deprecated/window-utils.js
@@ -3,23 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   'stability': 'deprecated'
 };
 
 const { Cc, Ci } = require('chrome');
-const { EventEmitter } = require('../deprecated/events');
-const { Trait } = require('../deprecated/traits');
-const { when } = require('../system/unload');
 const events = require('../system/events');
 const { getInnerId, getOuterId, windows, isDocumentLoaded, isBrowser,
         getMostRecentBrowserWindow, getMostRecentWindow } = require('../window/utils');
-const errors = require('../deprecated/errors');
 const { deprecateFunction } = require('../util/deprecate');
 const { ignoreWindow } = require('sdk/private-browsing/utils');
 const { isPrivateBrowsingSupported } = require('../self');
 
 const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
                        getService(Ci.nsIWindowWatcher);
 const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
                         getService(Ci.nsIAppShellService);
@@ -119,73 +115,53 @@ WindowTracker.prototype = {
 
   unload: function unload() {
     windowWatcher.unregisterNotification(this);
     events.off('toplevel-window-ready', this._onToplevelWindowReady);
     for (let window of getWindows())
       this._unregWindow(window);
   },
 
-  handleEvent: errors.catchAndLog(function handleEvent(event) {
-    if (event.type == 'load' && event.target) {
-      var window = event.target.defaultView;
-      if (window)
-        this._regWindow(window);
+  handleEvent: function handleEvent(event) {
+    try {
+      if (event.type == 'load' && event.target) {
+        var window = event.target.defaultView;
+        if (window)
+          this._regWindow(window);
+      }
     }
-  }),
+    catch(e) {
+      console.exception(e);
+    }
+  },
 
   _onToplevelWindowReady: function _onToplevelWindowReady({subject}) {
     let window = subject;
     // ignore private windows if they are not supported
     if (ignoreWindow(window))
       return;
     this._regWindow(window);
   },
 
-  observe: errors.catchAndLog(function observe(subject, topic, data) {
-    var window = subject.QueryInterface(Ci.nsIDOMWindow);
-    // ignore private windows if they are not supported
-    if (ignoreWindow(window))
-      return;
-    if (topic == 'domwindowclosed')
+  observe: function observe(subject, topic, data) {
+    try {
+      var window = subject.QueryInterface(Ci.nsIDOMWindow);
+      // ignore private windows if they are not supported
+      if (ignoreWindow(window))
+        return;
+      if (topic == 'domwindowclosed')
       this._unregWindow(window);
-  })
+    }
+    catch(e) {
+      console.exception(e);
+    }
+  }
 };
 exports.WindowTracker = WindowTracker;
 
-const WindowTrackerTrait = Trait.compose({
-  _onTrack: Trait.required,
-  _onUntrack: Trait.required,
-  constructor: function WindowTrackerTrait() {
-    WindowTracker({
-      onTrack: this._onTrack.bind(this),
-      onUntrack: this._onUntrack.bind(this)
-    });
-  }
-});
-exports.WindowTrackerTrait = WindowTrackerTrait;
-
-var gDocsToClose = [];
-
-function onDocUnload(event) {
-  var index = gDocsToClose.indexOf(event.target);
-  if (index == -1)
-    throw new Error('internal error: unloading document not found');
-  var document = gDocsToClose.splice(index, 1)[0];
-  // Just in case, let's remove the event listener too.
-  document.defaultView.removeEventListener('unload', onDocUnload, false);
-}
-
-onDocUnload = require('./errors').catchAndLog(onDocUnload);
-
-exports.closeOnUnload = function closeOnUnload(window) {
-  window.addEventListener('unload', onDocUnload, false);
-  gDocsToClose.push(window.document);
-};
-
 Object.defineProperties(exports, {
   activeWindow: {
     enumerable: true,
     get: function() {
       return getMostRecentWindow(null);
     },
     set: function(window) {
       try {
@@ -214,14 +190,8 @@ exports.getOuterId = deprecateFunction(g
 );
 
 exports.isBrowser = deprecateFunction(isBrowser,
   'require("window-utils").isBrowser is deprecated, ' +
   'please use require("sdk/window/utils").isBrowser instead'
 );
 
 exports.hiddenWindow = appShellService.hiddenDOMWindow;
-
-when(
-  function() {
-    gDocsToClose.slice().forEach(
-      function(doc) { doc.defaultView.close(); });
-  });
--- a/addon-sdk/source/lib/sdk/event/core.js
+++ b/addon-sdk/source/lib/sdk/event/core.js
@@ -81,45 +81,53 @@ exports.once = once;
  * @param {Object} target
  *    Event target object.
  * @param {String} type
  *    The type of event.
  * @params {Object|Number|String|Boolean} args
  *    Arguments that will be passed to listeners.
  */
 function emit (target, type, ...args) {
+  emitOnObject(target, type, target, ...args);
+}
+exports.emit = emit;
+
+/**
+ * A variant of emit that allows setting the this property for event listeners
+ */
+function emitOnObject(target, type, thisArg, ...args) {
   let all = observers(target, '*').length;
   let state = observers(target, type);
   let listeners = state.slice();
   let count = listeners.length;
   let index = 0;
 
   // If error event and there are no handlers (explicit or catch-all)
   // then print error message to the console.
   if (count === 0 && type === 'error' && all === 0)
     console.exception(args[0]);
   while (index < count) {
     try {
       let listener = listeners[index];
       // Dispatch only if listener is still registered.
       if (~state.indexOf(listener))
-        listener.apply(target, args);
+        listener.apply(thisArg, args);
     }
     catch (error) {
       // If exception is not thrown by a error listener and error listener is
       // registered emit `error` event. Otherwise dump exception to the console.
       if (type !== 'error') emit(target, 'error', error);
       else console.exception(error);
     }
     index++;
   }
    // Also emit on `"*"` so that one could listen for all events.
   if (type !== '*') emit(target, '*', type, ...args);
 }
-exports.emit = emit;
+exports.emitOnObject = emitOnObject;
 
 /**
  * Removes an event `listener` for the given event `type` on the given event
  * `target`. If no `listener` is passed removes all listeners of the given
  * `type`. If `type` is not passed removes all the listeners of the given
  * event `target`.
  * @param {Object} target
  *    The event target object.
--- a/addon-sdk/source/lib/sdk/frame/hidden-frame.js
+++ b/addon-sdk/source/lib/sdk/frame/hidden-frame.js
@@ -4,17 +4,16 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Cc, Ci } = require("chrome");
-const errors = require("../deprecated/errors");
 const { Class } = require("../core/heritage");
 const { List, addListItem, removeListItem } = require("../util/list");
 const { EventTarget } = require("../event/target");
 const { emit } = require("../event/core");
 const { create: makeFrame } = require("./utils");
 const { defer } = require("../core/promise");
 const { when: unload } = require("../system/unload");
 const { validateOptions, getTypeOf } = require("../deprecated/api-utils");
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/input/window.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const { windows, isInteractive, isDocumentLoaded,
-        getOuterId, isTopLevel } = require("../window/utils");
-const { InputPort } = require("./system");
-const { lift, merges, foldp, keepIf, start, Input } = require("../event/utils");
-const { patch } = require("diffpatcher/index");
-const { on } = require("../event/core");
-const { Sequence,  seq, filter, object, pairs } = require("../util/sequence");
-
-
-// Create lazy iterators from the regular arrays, although
-// once https://github.com/mozilla/addon-sdk/pull/1314 lands
-// `windows` will be transforme to lazy iterators.
-// When iterated over belowe sequences items will represent
-// state of windows at the time of iteration.
-const opened = seq(function*() {
-  const items = windows(null, {includePrivates: true});
-  for (let item of items)
-    yield [getOuterId(item), item];
-});
-const interactive = filter(([_, window]) => isInteractive(window), opened);
-const loaded = filter(([_, window]) => isDocumentLoaded(window), opened);
-
-// Helper function that converts given argument to a delta.
-const Update = window => window && object([getOuterId(window), window]);
-const Delete = window => window && object([getOuterId(window), null]);
-
-// Signal represents delta for last opened top level window.
-const LastOpened = lift(Update, new InputPort({topic: "domwindowopened"}));
-exports.LastOpened = LastOpened;
-
-// Signal represents delta for last top level window close.
-const LastClosed = lift(Delete, new InputPort({topic: "domwindowclosed"}));
-exports.LastClosed = LastClosed;
-
-const windowFor = document => document && document.defaultView;
-
-// Signal represent delta for last top level window document becoming interactive.
-const InteractiveDoc = new InputPort({topic: "chrome-document-interactive"});
-const InteractiveWin = lift(windowFor, InteractiveDoc);
-const LastInteractive = lift(Update, keepIf(isTopLevel, null, InteractiveWin));
-exports.LastInteractive = LastInteractive;
-
-// Signal represent delta for last top level window loaded.
-const LoadedDoc = new InputPort({topic: "chrome-document-loaded"});
-const LoadedWin = lift(windowFor, LoadedDoc);
-const LastLoaded = lift(Update, keepIf(isTopLevel, null, LoadedWin));
-exports.LastLoaded = LastLoaded;
-
-
-const initialize = input => {
-  if (!input.initialized) {
-    input.value = object(...input.value);
-    Input.start(input);
-    input.initialized = true;
-  }
-};
-
-// Signal represents set of currently opened top level windows, updated
-// to new set any time window is opened or closed.
-const Opened = foldp(patch, opened, merges([LastOpened, LastClosed]));
-Opened[start] = initialize;
-exports.Opened = Opened;
-
-// Signal represents set of top level interactive windows, updated any
-// time new window becomes interactive or one get's closed.
-const Interactive = foldp(patch, interactive, merges([LastInteractive,
-                                                      LastClosed]));
-Interactive[start] = initialize;
-exports.Interactive = Interactive;
-
-// Signal represents set of top level loaded window, updated any time
-// new window becomes interactive or one get's closed.
-const Loaded = foldp(patch, loaded, merges([LastLoaded, LastClosed]));
-Loaded[start] = initialize;
-exports.Loaded = Loaded;
--- a/addon-sdk/source/lib/sdk/io/file.js
+++ b/addon-sdk/source/lib/sdk/io/file.js
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 module.metadata = {
-  "stability": "experimental"
+  "stability": "deprecated"
 };
 
 const {Cc,Ci,Cr} = require("chrome");
 const byteStreams = require("./byte-streams");
 const textStreams = require("./text-streams");
 
 // Flags passed when opening a file.  See nsprpub/pr/include/prio.h.
 const OPEN_FLAGS = {
--- a/addon-sdk/source/lib/sdk/io/fs.js
+++ b/addon-sdk/source/lib/sdk/io/fs.js
@@ -879,16 +879,17 @@ function writeFile(path, content, encodi
   }
 };
 exports.writeFile = writeFile;
 
 /**
  * The synchronous version of `fs.writeFile`.
  */
 function writeFileSync(filename, data, encoding) {
+  // TODO: Implement this in bug 1148209 https://bugzilla.mozilla.org/show_bug.cgi?id=1148209
   throw Error("Not implemented");
 };
 exports.writeFileSync = writeFileSync;
 
 
 function utimesSync(path, atime, mtime) {
   throw Error("Not implemented");
 }
--- a/addon-sdk/source/lib/sdk/io/stream.js
+++ b/addon-sdk/source/lib/sdk/io/stream.js
@@ -27,17 +27,17 @@ const ArrayBufferInputStream = CC("@mozi
 const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
                              "nsIBinaryInputStream", "setInputStream");
 const InputStreamPump = CC("@mozilla.org/network/input-stream-pump;1",
                            "nsIInputStreamPump", "init");
 
 const threadManager = Cc["@mozilla.org/thread-manager;1"].
                       getService(Ci.nsIThreadManager);
 
-const eventTarget = Cc["@mozilla.org/network/socket-transport-service;1"].
+const eventTarget = Cc["@mozilla.org/network/stream-transport-service;1"].
                     getService(Ci.nsIEventTarget);
 
 let isFunction = value => typeof(value) === "function"
 
 function accessor() {
   let map = new WeakMap();
   return function(target, value) {
     if (value)
--- a/addon-sdk/source/lib/sdk/lang/type.js
+++ b/addon-sdk/source/lib/sdk/lang/type.js
@@ -120,29 +120,27 @@ function isGenerator(aValue) {
 exports.isGenerator = isGenerator;
 
 /**
  * Returns true if `value` is an Array.
  * @examples
  *    isArray([1, 2, 3])  // true
  *    isArray({ 0: 'foo', length: 1 }) // false
  */
-var isArray = Array.isArray || function isArray(value) {
-  Object.prototype.toString.call(value) === "[object Array]";
-}
+var isArray = Array.isArray;
 exports.isArray = isArray;
 
 /**
  * Returns `true` if `value` is an Arguments object.
  * @examples
  *    (function(){ return isArguments(arguments); })(1, 2, 3); // true
  *    isArguments([1,2,3]); // false
  */
 function isArguments(value) {
-  Object.prototype.toString.call(value) === "[object Arguments]";
+  return Object.prototype.toString.call(value) === "[object Arguments]";
 }
 exports.isArguments = isArguments;
 
 let isMap = value => Object.prototype.toString.call(value) === "[object Map]"
 exports.isMap = isMap;
 
 let isSet = value => Object.prototype.toString.call(value) === "[object Set]"
 exports.isSet = isSet;
--- a/addon-sdk/source/lib/sdk/model/core.js
+++ b/addon-sdk/source/lib/sdk/model/core.js
@@ -1,13 +1,11 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { dispatcher } = require("../util/dispatcher");
 
--- a/addon-sdk/source/lib/sdk/notifications.js
+++ b/addon-sdk/source/lib/sdk/notifications.js
@@ -5,17 +5,16 @@
 "use strict";
 
 module.metadata = {
   "stability": "stable"
 };
 
 const { Cc, Ci, Cr } = require("chrome");
 const apiUtils = require("./deprecated/api-utils");
-const errors = require("./deprecated/errors");
 const { isString, isUndefined, instanceOf } = require('./lang/type');
 const { URL, isLocalURL } = require('./url');
 const { data } = require('./self');
 
 const NOTIFICATION_DIRECTIONS  = ["auto", "ltr", "rtl"];
 
 try {
   let alertServ = Cc["@mozilla.org/alerts-service;1"].
@@ -29,19 +28,25 @@ catch (err) {
   // service, e.g., if Growl is not installed on OS X.  In that case, use a
   // mock notification function that just logs to the console.
   notify = notifyUsingConsole;
 }
 
 exports.notify = function notifications_notify(options) {
   let valOpts = validateOptions(options);
   let clickObserver = !valOpts.onClick ? null : {
-    observe: function notificationClickObserved(subject, topic, data) {
-      if (topic === "alertclickcallback")
-        errors.catchAndLog(valOpts.onClick).call(exports, valOpts.data);
+    observe: (subject, topic, data) => {
+      if (topic === "alertclickcallback") {
+        try {
+          valOpts.onClick.call(exports, valOpts.data);
+        }
+        catch(e) {
+          console.exception(e);
+        }
+      }
     }
   };
   function notifyWithOpts(notifyFn) {
     let { iconURL } = valOpts;
     iconURL = iconURL && isLocalURL(iconURL) ? data.url(iconURL) : iconURL;
 
     notifyFn(iconURL, valOpts.title, valOpts.text, !!clickObserver,
              valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
--- a/addon-sdk/source/lib/sdk/page-mod.js
+++ b/addon-sdk/source/lib/sdk/page-mod.js
@@ -120,19 +120,22 @@ const PageMod = Class({
 
     function serializeRules(rules) {
       for (let rule of rules) {
         yield isRegExp(rule) ? { type: "regexp", pattern: rule.source, flags: rule.flags }
                              : { type: "string", value: rule };
       }
     }
 
-    model.childOptions = omit(model, ["include", "exclude"]);
+    model.childOptions = omit(model, ["include", "exclude", "contentScriptOptions"]);
     model.childOptions.include = [...serializeRules(model.include)];
     model.childOptions.exclude = [...serializeRules(model.exclude)];
+    model.childOptions.contentScriptOptions = model.contentScriptOptions ?
+                                              JSON.stringify(model.contentScriptOptions) :
+                                              null;
 
     processes.port.emit('sdk/page-mod/create', model.childOptions);
   },
 
   dispose: function(reason) {
     processes.port.emit('sdk/page-mod/destroy', modelFor(this).id);
     pagemods.delete(modelFor(this).id);
     workers.delete(this);
--- a/addon-sdk/source/lib/sdk/page-worker.js
+++ b/addon-sdk/source/lib/sdk/page-worker.js
@@ -22,16 +22,17 @@ const { window } = require('./addon/wind
 const { getParentWindow } = require('./window/utils');
 const { create: makeFrame, getDocShell } = require('./frame/utils');
 const { contract } = require('./util/contract');
 const { contract: loaderContract } = require('./content/loader');
 const { has } = require('./util/array');
 const { Rules } = require('./util/rules');
 const { merge } = require('./util/object');
 const { data } = require('./self');
+const { getActiveView } = require("./view/core");
 
 const views = new WeakMap();
 const workers = new WeakMap();
 const pages = new WeakMap();
 
 const readyEventNames = [
   'DOMContentLoaded',
   'document-element-inserted',
@@ -176,8 +177,10 @@ function pageFromDoc(doc) {
   if (!parentWindow) return;
 
   let frames = parentWindow.document.getElementsByTagName('iframe');
   for (let i = frames.length; i--;)
     if (frames[i].contentDocument === doc && (page = pageFor(frames[i])))
       return page;
   return null;
 }
+
+getActiveView.define(Page, viewFor);
--- a/addon-sdk/source/lib/sdk/places/contract.js
+++ b/addon-sdk/source/lib/sdk/places/contract.js
@@ -1,33 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci } = require('chrome');
-const { EventEmitter } = require('../deprecated/events');
 const { isValidURI, URL } = require('../url');
 const { contract } = require('../util/contract');
 const { extend } = require('../util/object');
 
 // map of property validations
 const validItem = {
   id: {
     is: ['number', 'undefined', 'null'],
   },
   group: {
     is: ['object', 'number', 'undefined', 'null'],
     ok: function (value) {
-      return value && 
+      return value &&
         (value.toString && value.toString() === '[object Group]') ||
         typeof value === 'number' ||
         value.type === 'group';
     },
     msg: 'The `group` property must be a valid Group object'
   },
   index: {
     is: ['undefined', 'null', 'number'],
@@ -43,17 +41,17 @@ const validTitle = {
   title: {
     is: ['string'],
     msg: 'The `title` property must be defined.'
   }
 };
 
 const validURL = {
   url: {
-    is: ['string'], 
+    is: ['string'],
     ok: isValidURI,
     msg: 'The `url` property must be a valid URL.'
   }
 };
 
 const validTags = {
   tags: {
     is: ['object'],
--- a/addon-sdk/source/lib/sdk/remote/parent.js
+++ b/addon-sdk/source/lib/sdk/remote/parent.js
@@ -41,17 +41,17 @@ else {
 let pathMapping = Object.keys(options.paths)
                         .sort((a, b) => b.length - a.length)
                         .map(p => [p, options.paths[p]]);
 
 // Load the scripts in the child processes
 let { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm');
 let PATH = options.paths[''];
 
-const childOptions = omit(options, ['modules', 'globals']);
+const childOptions = omit(options, ['modules', 'globals', 'resolve', 'load']);
 childOptions.modules = {};
 // @l10n/data is just JSON data and can be safely sent across to the child loader
 try {
   childOptions.modules["@l10n/data"] = require("@l10n/data");
 }
 catch (e) {
   // There may be no l10n data
 }
--- a/addon-sdk/source/lib/sdk/request.js
+++ b/addon-sdk/source/lib/sdk/request.js
@@ -159,16 +159,18 @@ const Request = Class({
   }
 });
 exports.Request = Request;
 
 const Response = Class({
   initialize: function initialize(request) {
     response(this).request = request;
   },
+  // more about responseURL: https://bugzilla.mozilla.org/show_bug.cgi?id=998076
+  get url() response(this).request.responseURL,
   get text() response(this).request.responseText,
   get xml() {
     throw new Error("Sorry, the 'xml' property is no longer available. " +
                     "see bug 611042 for more information.");
   },
   get status() response(this).request.status,
   get statusText() response(this).request.statusText,
   get json() {
--- a/addon-sdk/source/lib/sdk/system.js
+++ b/addon-sdk/source/lib/sdk/system.js
@@ -4,17 +4,16 @@
 'use strict';
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, CC } = require('chrome');
 const options = require('@loader/options');
-const file = require('./io/file');
 const runtime = require("./system/runtime");
 const { when: unload } = require("./system/unload");
 
 const appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
                    getService(Ci.nsIAppStartup);
 const appInfo = Cc["@mozilla.org/xre/app-info;1"].
                 getService(Ci.nsIXULAppInfo);
 const directoryService = Cc['@mozilla.org/file/directory_service;1'].
--- a/addon-sdk/source/lib/sdk/tabs.js
+++ b/addon-sdk/source/lib/sdk/tabs.js
@@ -2,32 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-const { modelFor } = require("./model/core");
-const { viewFor } = require("./view/core");
-const { isTab } = require("./tabs/utils");
-
-
 if (require("./system/xul-app").is("Fennec")) {
   module.exports = require("./windows/tabs-fennec").tabs;
 }
 else {
   module.exports = require("./tabs/tabs-firefox");
 }
 
 const tabs = module.exports;
-
-// Implement `modelFor` function for the Tab instances.
-// Finds a right model by iterating over all tab models
-// and finding one that wraps given `view`.
-modelFor.when(isTab, view => {
-  for (let model of tabs) {
-    if (viewFor(model) === view)
-      return model;
-  }
-  return null;
-});
--- a/addon-sdk/source/lib/sdk/tabs/helpers.js
+++ b/addon-sdk/source/lib/sdk/tabs/helpers.js
@@ -7,35 +7,26 @@ module.metadata = {
   'stability': 'unstable'
 };
 
 
 // NOTE: This file should only export Tab instances
 
 
 const { getTabForContentWindow, getTabForBrowser: getRawTabForBrowser } = require('./utils');
-const { Tab } = require('./tab');
-const { rawTabNS } = require('./namespace');
+const { modelFor } = require('../model/core');
 
 function getTabForWindow(win) {
   let tab = getTabForContentWindow(win);
   // We were unable to find the related tab!
   if (!tab)
     return null;
 
-  return getTabForRawTab(tab) || Tab({ tab: tab });
+  return modelFor(tab);
 }
 exports.getTabForWindow = getTabForWindow;
 
-// only works on fennec atm
-function getTabForRawTab(rawTab) {
-  let tab = rawTabNS(rawTab).tab;
-  if (tab) {
-    return tab;
-  }
-  return null;
-}
-exports.getTabForRawTab = getTabForRawTab;
+exports.getTabForRawTab = modelFor;
 
 function getTabForBrowser(browser) {
-  return getTabForRawTab(getRawTabForBrowser(browser));
+  return modelFor(getRawTabForBrowser(browser));
 }
 exports.getTabForBrowser = getTabForBrowser;
--- a/addon-sdk/source/lib/sdk/tabs/observer.js
+++ b/addon-sdk/source/lib/sdk/tabs/observer.js
@@ -10,16 +10,17 @@ module.metadata = {
 const { EventTarget } = require("../event/target");
 const { emit } = require("../event/core");
 const { DOMEventAssembler } = require("../deprecated/events/assembler");
 const { Class } = require("../core/heritage");
 const { getActiveTab, getTabs } = require("./utils");
 const { browserWindowIterator } = require("../deprecated/window-utils");
 const { isBrowser, windows, getMostRecentBrowserWindow } = require("../window/utils");
 const { observer: windowObserver } = require("../windows/observer");
+const { when } = require("../system/unload");
 
 const EVENTS = {
   "TabOpen": "open",
   "TabClose": "close",
   "TabSelect": "select",
   "TabMove": "move",
   "TabPinned": "pinned",
   "TabUnpinned": "unpinned"
@@ -82,16 +83,21 @@ const Observer = Class({
       }
     });
 
     // We should synchronize state, since probably we already have at least one
     // window open.
     for (let chromeWindow of browserWindowIterator()) {
       this.observe(chromeWindow);
     }
+
+    when(_ => {
+      // Don't dispatch a deactivate event during unload.
+      this[selectedTab] = null;
+    });
   },
   /**
    * Events that are supported and emitted by the module.
    */
   supportedEventsTypes: Object.keys(EVENTS),
   /**
    * Function handles all the supported events on all the windows that are
    * observed. Method is used to proxy events to the listeners registered on
--- a/addon-sdk/source/lib/sdk/tabs/tab-fennec.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab-fennec.js
@@ -248,8 +248,13 @@ function onTabClose(event) {
 
   emit(this, EVENTS.close.name, this);
   cleanupTab(this);
 };
 
 isPrivate.implement(Tab, tab => {
   return isWindowPrivate(getTabContentWindow(tabNS(tab).tab));
 });
+
+// Implement `modelFor` function for the Tab instances.
+modelFor.when(isTab, rawTab => {
+  return rawTabNS(rawTab).tab;
+});
--- a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
@@ -1,303 +1,324 @@
- /*This Source Code Form is subject to the terms of the Mozilla Public
+/* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const { Trait } = require("../deprecated/traits");
-const { EventEmitter } = require("../deprecated/events");
-const { defer } = require("../lang/functional");
-const { has } = require("../util/array");
-const { each } = require("../util/object");
-const { EVENTS } = require("./events");
-const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
+const { Class } = require('../core/heritage');
+const { observer } = require('./observer');
+const { observer: windowObserver } = require('../windows/observer');
+const { addListItem, removeListItem } = require('../util/list');
+const { viewFor } = require('../view/core');
+const { modelFor } = require('../model/core');
+const { emit, setListeners } = require('../event/core');
+const { EventTarget } = require('../event/target');
+const { getBrowserForTab, setTabURL, getTabId, getTabURL, getTabForBrowser,
+        getTabs, getTabTitle, setTabTitle, getIndex, closeTab, reload, move,
+        activateTab, pin, unpin, isTab } = require('./utils');
+const { isBrowser, getInnerId, isWindowPrivate } = require('../window/utils');
 const { getFaviconURIForLocation } = require("../io/data");
-const { activateTab, getOwnerWindow, getBrowserForTab, getTabTitle,
-        setTabTitle, getTabContentDocument, getTabURL, setTabURL,
-        getTabContentType, getTabId } = require('./utils');
-const { isPrivate } = require('../private-browsing/utils');
-const { isWindowPrivate } = require('../window/utils');
-const viewNS = require('../core/namespace').ns();
 const { deprecateUsage } = require('../util/deprecate');
+const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
+const { when } = require('../system/unload');
+const { ignoreWindow, isPrivate } = require('../private-browsing/utils')
+const { defer } = require('../lang/functional');
 const { getURL } = require('../url/utils');
-const { viewFor } = require('../view/core');
-const { observer } = require('./observer');
-const { remoteRequire, frames } = require('../remote/parent');
+const { frames, remoteRequire } = require('../remote/parent');
 remoteRequire('sdk/content/tab-events');
 
-// Array of the inner instances of all the wrapped tabs.
-const TABS = [];
+const modelsFor = new WeakMap();
+const viewsFor = new WeakMap();
+const destroyed = new WeakMap();
+
+const tabEvents = {};
+exports.tabEvents = tabEvents;
+
+function browser(tab) {
+  return getBrowserForTab(viewsFor.get(tab));
+}
+
+function isDestroyed(tab) {
+  return destroyed.has(tab);
+}
+
+function isClosed(tab) {
+  if (!viewsFor.has(tab))
+    return true;
+  return viewsFor.get(tab).closing;
+}
 
-/**
- * Trait used to create tab wrappers.
- */
-const TabTrait = Trait.compose(EventEmitter, {
-  on: Trait.required,
-  _emit: Trait.required,
-  /**
-   * Tab DOM element that is being wrapped.
-   */
-  _tab: null,
-  /**
-   * Window wrapper whose tab this object represents.
-   */
-  window: null,
-  constructor: function Tab(options) {
-    this._tab = options.tab;
-    // TODO: Remove this dependency
-    let window = this.window = options.window || require('../windows').BrowserWindow({ window: getOwnerWindow(this._tab) });
+const Tab = Class({
+  implements: [EventTarget],
+  initialize: function(tabElement, options = null) {
+    modelsFor.set(tabElement, this);
+    viewsFor.set(this, tabElement);
+
+    if (options) {
+      EventTarget.prototype.initialize.call(this, options);
 
-    // Setting event listener if was passed.
-    each(EVENTS, (type) => {
-      let listener = options[type.listener];
-      if (listener) {
-        this.on(type.name, options[type.listener]);
-      }
-      // window spreads this event.
-      if (!has(['ready', 'load', 'pageshow'], (type.name)))
-        window.tabs.on(type.name, this._onEvent.bind(this, type.name));
+      if (options.isPinned)
+        this.pin();
+
+      // Note that activate is defered and so will run after any open event
+      // is sent out
+      if (!options.inBackground)
+        this.activate();
+    }
+
+    getURL.implement(this, tab => tab.url);
+    isPrivate.implement(this, tab => {
+      return isWindowPrivate(viewsFor.get(tab).ownerDocument.defaultView);
     });
-
-    this.on(EVENTS.close.name, this.destroy.bind(this));
-
-    this._onContentEvent = this._onContentEvent.bind(this);
-    frames.port.on('sdk/tab/event', this._onContentEvent);
-
-    // bug 1024632 - first tab inNewWindow gets events from the synthetic 
-    // about:blank document. ignore them unless that is the actual target url.
-    this._skipBlankEvents = options.inNewWindow && options.url !== 'about:blank';
-
-    if (options.isPinned)
-      this.pin();
-
-    viewNS(this._public).tab = this._tab;
-    viewFor.implement(this._public, getTabView);
-    isPrivate.implement(this._public, tab => isWindowPrivate(getChromeTab(tab)));
-
-    // Add tabs to getURL method
-    getURL.implement(this._public, (function (obj) this._public.url).bind(this));
-
-    // Since we will have to identify tabs by a DOM elements facade function
-    // is used as constructor that collects all the instances and makes sure
-    // that they more then one wrapper is not created per tab.
-    return this;
-  },
-  destroy: function destroy() {
-    this._removeAllListeners();
-    if (this._tab) {
-      frames.port.off('sdk/tab/event', this._onContentEvent);
-      this._tab = null;
-      TABS.splice(TABS.indexOf(this), 1);
-    }
   },
 
-  /**
-   * internal message listener emits public events (ready, load and pageshow)
-   * forwarded from content frame script tab-event.js
-   */
-  _onContentEvent: function(frame, event, persisted) {
-    if (frame.frameElement !== this._browser)
+  get id() {
+    return isDestroyed(this) ? undefined : getTabId(viewsFor.get(this));
+  },
+
+  get title() {
+    return isDestroyed(this) ? undefined : getTabTitle(viewsFor.get(this));
+  },
+
+  set title(val) {
+    if (isDestroyed(this))
       return;
 
-    // bug 1024632 - skip initial events from synthetic about:blank document
-    if (this._skipBlankEvents && this.window.tabs.length === 1 && this.url === 'about:blank')
-      return;
+    setTabTitle(viewsFor.get(this), val);
+  },
 
-    // first time we don't skip blank events, disable further skipping
-    this._skipBlankEvents = false;
-
-    this._emit(event, this._public, persisted);
+  get url() {
+    return isDestroyed(this) ? undefined : getTabURL(viewsFor.get(this));
   },
 
-  /**
-   * Internal tab event router. Window will emit tab related events for all it's
-   * tabs, this listener will propagate all the events for this tab to it's
-   * listeners.
-   */
-  _onEvent: function _onEvent(type, tab) {
-    if (viewNS(tab).tab == this._tab)
-      this._emit(type, tab);
-  },
-  /**
-   * Browser DOM element where page of this tab is currently loaded.
-   */
-  get _browser() getBrowserForTab(this._tab),
-  /**
-   * Window DOM element containing this tab.
-   */
-  get _window() getOwnerWindow(this._tab),
-  /**
-   * Document object of the page that is currently loaded in this tab.
-   */
-  get _contentDocument() getTabContentDocument(this._tab),
-  /**
-   * Window object of the page that is currently loaded in this tab.
-   */
-  get _contentWindow() this._browser.contentWindow,
+  set url(val) {
+    if (isDestroyed(this))
+      return;
 
-  /**
-   * tab's document readyState, or 'uninitialized' if it doesn't even exist yet.
-   */
-  get readyState() {
-    let doc = this._contentDocument;
-    return doc && doc.readyState || 'uninitialized';
+    setTabURL(viewsFor.get(this), val);
   },
 
-  /**
-   * Unique id for the tab, actually maps to tab.linkedPanel but with some munging.
-   */
-  get id() this._tab ? getTabId(this._tab) : undefined,
-
-  /**
-   * The title of the page currently loaded in the tab.
-   * Changing this property changes an actual title.
-   * @type {String}
-   */
-  get title() this._tab ? getTabTitle(this._tab) : undefined,
-  set title(title) this._tab && setTabTitle(this._tab, title),
-
-  /**
-   * Returns the MIME type that the document loaded in the tab is being
-   * rendered as.
-   * @type {String}
-   */
-  get contentType() this._tab ? getTabContentType(this._tab) : undefined,
-
-  /**
-   * Location of the page currently loaded in this tab.
-   * Changing this property will loads page under under the specified location.
-   * @type {String}
-   */
-  get url() this._tab ? getTabURL(this._tab) : undefined,
-  set url(url) this._tab && setTabURL(this._tab, url),
-  /**
-   * URI of the favicon for the page currently loaded in this tab.
-   * @type {String}
-   */
   get favicon() {
     deprecateUsage(
       'tab.favicon is deprecated, ' +
       'please use require("sdk/places/favicon").getFavicon instead.'
     );
-    return this._tab ? getFaviconURIForLocation(this.url) : undefined
+    return isDestroyed(this) ? undefined : getFaviconURIForLocation(this.url);
+  },
+
+  get contentType() {
+    return isDestroyed(this) ? undefined : browser(this).documentContentType;
+  },
+
+  get index() {
+    return isDestroyed(this) ? undefined : getIndex(viewsFor.get(this));
   },
-  /**
-   * The CSS style for the tab
-   */
-  get style() null, // TODO
-  /**
-   * The index of the tab relative to other tabs in the application window.
-   * Changing this property will change order of the actual position of the tab.
-   * @type {Number}
-   */
-  get index()
-    this._tab ?
-    this._window.gBrowser.getBrowserIndexForDocument(this._contentDocument) :
-    undefined,
-  set index(value)
-    this._tab && this._window.gBrowser.moveTabTo(this._tab, value),
-  /**
-   * Thumbnail data URI of the page currently loaded in this tab.
-   * @type {String}
-   */
-  getThumbnail() {
-    if (!this._tab)
-      return undefined;
-    if (this._tab.getAttribute('remote')) {
-      console.error('This method is not supported with E10S');
-      return BLANK;
-    }
-    return getThumbnailURIForWindow(this._contentWindow);
+
+  set index(val) {
+    if (isDestroyed(this))
+      return;
+
+    move(viewsFor.get(this), val);
   },
-  /**
-   * Whether or not tab is pinned (Is an app-tab).
-   * @type {Boolean}
-   */
-  get isPinned() this._tab ? this._tab.pinned : undefined,
-  pin: function pin() {
-    if (!this._tab)
-      return;
-    this._window.gBrowser.pinTab(this._tab);
-  },
-  unpin: function unpin() {
-    if (!this._tab)
-      return;
-    this._window.gBrowser.unpinTab(this._tab);
+
+  get isPinned() {
+    return isDestroyed(this) ? undefined : viewsFor.get(this).pinned;
   },
 
-  /**
-   * Create a worker for this tab, first argument is options given to Worker.
-   * @type {Worker}
-   */
-  attach: function attach(options) {
-    if (!this._tab)
-      return;
-    // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
-    // TODO: fix this circular dependency
-    let { Worker } = require('./worker');
-    return Worker(options, this._contentWindow);
+  get window() {
+    if (isClosed(this))
+      return undefined;
+
+    // TODO: Remove the dependency on the windows module, see bug 792670
+    require('../windows');
+    let tabElement = viewsFor.get(this);
+    let domWindow = tabElement.ownerDocument.defaultView;
+    return modelFor(domWindow);
+  },
+
+  get readyState() {
+    // TODO: This will use CPOWs in e10s: bug 1146606
+    return isDestroyed(this) ? undefined : browser(this).contentDocument.readyState;
   },
 
-  /**
-   * Make this tab active.
-   * Please note: That this function is called asynchronous since in E10S that
-   * will be the case. Besides this function is called from a constructor where
-   * we would like to return instance before firing a 'TabActivated' event.
-   */
-  activate: defer(function activate() {
-    if (!this._tab)
+  pin: function() {
+    if (isDestroyed(this))
       return;
-    activateTab(this._tab);
-  }),
-  /**
-   * Close the tab
-   */
-  close: function close(callback) {
-    // Bug 699450: the tab may already have been detached
-    if (!this._tab || !this._tab.parentNode) {
+
+    pin(viewsFor.get(this));
+  },
+
+  unpin: function() {
+    if (isDestroyed(this))
+      return;
+
+    unpin(viewsFor.get(this));
+  },
+
+  close: function(callback) {
+    let tabElement = viewsFor.get(this);
+
+    if (isDestroyed(this) || !tabElement || !tabElement.parentNode) {
       if (callback)
         callback();
       return;
     }
-    if (callback) {
-      if (this.window.tabs.activeTab && (this.window.tabs.activeTab.id == this.id))
-        observer.once('select', callback);
-      else
-        this.once(EVENTS.close.name, callback);
-    }
-    this._window.gBrowser.removeTab(this._tab);
+
+    this.once('close', () => {
+      this.destroy();
+      if (callback)
+        callback();
+    });
+
+    closeTab(tabElement);
+  },
+
+  reload: function() {
+    if (isDestroyed(this))
+      return;
+
+    reload(viewsFor.get(this));
   },
-  /**
-   * Reload the tab
-   */
-  reload: function reload() {
-    if (!this._tab)
+
+  activate: defer(function() {
+    if (isDestroyed(this))
       return;
-    this._window.gBrowser.reloadTab(this._tab);
+
+    activateTab(viewsFor.get(this));
+  }),
+
+  getThumbnail: function() {
+    if (isDestroyed(this))
+      return BLANK;
+
+    // TODO: This is unimplemented in e10s: bug 1148601
+    if (browser(this).isRemoteBrowser) {
+      console.error('This method is not supported with E10S');
+      return BLANK;
+    }
+    return getThumbnailURIForWindow(browser(this).contentWindow);
+  },
+
+  attach: function(options) {
+    if (isDestroyed(this))
+      return;
+
+    // BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
+    // TODO: fix this circular dependency
+    let { Worker } = require('./worker');
+    return Worker(options, browser(this).contentWindow);
+  },
+
+  destroy: function() {
+    if (isDestroyed(this))
+      return;
+
+    destroyed.set(this, true);
   }
 });
+exports.Tab = Tab;
 
-function getChromeTab(tab) {
-  return getOwnerWindow(viewNS(tab).tab);
+viewFor.define(Tab, tab => viewsFor.get(tab));
+
+// Returns the high-level window for this DOM window if the windows module has
+// ever been loaded otherwise returns null
+function maybeWindowFor(domWindow) {
+  try {
+    return modelFor(domWindow);
+  }
+  catch (e) {
+    return null;
+  }
 }
 
-// Implement `viewFor` polymorphic function for the Tab
-// instances.
-const getTabView = tab => viewNS(tab).tab;
+function tabEmit(tab, event, ...args) {
+  // Don't emit events for destroyed tabs
+  if (isDestroyed(tab))
+    return;
 
-function Tab(options, existingOnly) {
-  let chromeTab = options.tab;
-  for (let tab of TABS) {
-    if (chromeTab == tab._tab)
-      return tab._public;
+  // If the windows module was never loaded this will return null. We don't need
+  // to emit to the window.tabs object in this case as nothing can be listening.
+  let tabElement = viewsFor.get(tab);
+  let window = maybeWindowFor(tabElement.ownerDocument.defaultView);
+  if (window)
+    emit(window.tabs, event, tab, ...args);
+
+  emit(tabEvents, event, tab, ...args);
+  emit(tab, event, tab, ...args);
+}
+
+function windowClosed(domWindow) {
+  if (!isBrowser(domWindow))
+    return;
+
+  for (let tabElement of getTabs(domWindow)) {
+    tabEventListener("close", tabElement);
   }
-  // If called asked to return only existing wrapper,
-  // we should return null here as no matching Tab object has been found
-  if (existingOnly)
-    return null;
+}
+windowObserver.on('close', windowClosed);
+
+// Don't want to send close events after unloaded
+when(_ => {
+  windowObserver.off('close', windowClosed);
+});
+
+// Listen for tabbrowser events
+function tabEventListener(event, tabElement, ...args) {
+  let domWindow = tabElement.ownerDocument.defaultView;
+
+  if (ignoreWindow(domWindow))
+    return;
+
+  // Don't send events for tabs that are already closing
+  if (event != "close" && (tabElement.closing || !tabElement.parentNode))
+    return;
+
+  let tab = modelsFor.get(tabElement);
+  if (!tab)
+    tab = new Tab(tabElement);
+
+  let window = maybeWindowFor(domWindow);
 
-  let tab = TabTrait(options);
-  TABS.push(tab);
-  return tab._public;
+  if (event == "open") {
+    // Note, add to the window tabs first because if this is the first access to
+    // window.tabs it will be prefilling itself with everything from tabs
+    if (window)
+      addListItem(window.tabs, tab);
+    // The tabs module will take care of adding to its internal list
+  }
+  else if (event == "close") {
+    if (window)
+      removeListItem(window.tabs, tab);
+    // The tabs module will take care of removing from its internal list
+  }
+  else if (event == "ready" || event == "load") {
+    // Ignore load events from before browser windows have fully loaded, these
+    // are for about:blank in the initial tab
+    if (isBrowser(domWindow) && !domWindow.gBrowserInit.delayedStartupFinished)
+      return;
+  }
+
+  tabEmit(tab, event, ...args);
+
+  // The tab object shouldn't be reachable after closed
+  if (event == "close") {
+    viewsFor.delete(tab);
+    modelsFor.delete(tabElement);
+  }
 }
-Tab.prototype = TabTrait.prototype;
-exports.Tab = Tab;
+observer.on('*', tabEventListener);
+
+// Listen for tab events from content
+frames.port.on('sdk/tab/event', (frame, event, ...args) => {
+  if (!frame.isTab)
+    return;
+
+  let tabElement = getTabForBrowser(frame.frameElement);
+  if (!tabElement)
+    return;
+
+  tabEventListener(event, tabElement, ...args);
+});
+
+// Implement `modelFor` function for the Tab instances..
+modelFor.when(isTab, view => {
+  return modelsFor.get(view);
+});
--- a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
@@ -1,68 +1,134 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
+"use strict";
 
-// TODO: BUG 792670 - remove dependency below
-const { browserWindows: windows } = require('../windows');
-const { tabs } = require('../windows/tabs-firefox');
+const { Class } = require('../core/heritage');
+const { Tab, tabEvents } = require('./tab');
+const { EventTarget } = require('../event/target');
+const { emit, setListeners } = require('../event/core');
+const { pipe } = require('../event/utils');
+const { observer: windowObserver } = require('../windows/observer');
+const { List, addListItem, removeListItem } = require('../util/list');
+const { modelFor } = require('../model/core');
+const { viewFor } = require('../view/core');
+const { getTabs, getSelectedTab } = require('./utils');
+const { getMostRecentBrowserWindow, isBrowser } = require('../window/utils');
+const { Options } = require('./common');
 const { isPrivate } = require('../private-browsing');
-const { isWindowPBSupported } = require('../private-browsing/utils')
+const { ignoreWindow, isWindowPBSupported } = require('../private-browsing/utils')
 const { isPrivateBrowsingSupported } = require('sdk/self');
 
 const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
 
-function newTabWindow(options) {
-  // `tabs` option is under review and may be removed.
-  return windows.open({
-    tabs: [ options ],
-    isPrivate: options.isPrivate
-  });
-}
+const Tabs = Class({
+  implements: [EventTarget],
+  extends: List,
+  initialize: function() {
+    List.prototype.initialize.call(this);
+
+    // We must do the list manipulation here where the object is extensible
+    this.on("open", tab => {
+      addListItem(this, tab);
+    });
+
+    this.on("close", tab => {
+      removeListItem(this, tab);
+    });
+  },
 
-Object.defineProperties(tabs, {
-  open: { value: function open(options) {
-    if (options.inNewWindow) {
-        newTabWindow(options);
-        return undefined;
+  get activeTab() {
+    let activeDomWin = getMostRecentBrowserWindow();
+    if (!activeDomWin)
+      return null;
+    return modelFor(getSelectedTab(activeDomWin));
+  },
+
+  open: function(options) {
+    options = Options(options);
+
+    // TODO: Remove the dependency on the windows module: bug 792670
+    let windows = require('../windows').browserWindows;
+    let activeWindow = windows.activeWindow;
+
+    let privateState = supportPrivateTabs && options.isPrivate;
+    // When no isPrivate option was passed use the private state of the active
+    // window
+    if (activeWindow && privateState === undefined)
+      privateState = isPrivate(activeWindow);
+
+    function getWindow(privateState) {
+      for (let window of windows) {
+        if (privateState === isPrivate(window)) {
+          return window;
+        }
+      }
+      return null;
     }
 
-    let activeWindow = windows.activeWindow;
-    let privateState = (supportPrivateTabs && (options.isPrivate || isPrivate(activeWindow))) || false;
+    function openNewWindowWithTab() {
+      windows.open({
+        url: options.url,
+        isPrivate: privateState,
+        onOpen: function(newWindow) {
+          let tab = newWindow.tabs[0];
+          setListeners(tab, options);
+
+          if (options.isPinned)
+            tab.pin();
+
+          // We don't emit the open event for the first tab in a new window so
+          // do it now the listeners are attached
+          emit(tab, "open", tab);
+        }
+      });
+    }
+
+    if (options.inNewWindow)
+      return openNewWindowWithTab();
 
     // if the active window is in the state that we need then use it
-    if (activeWindow && (!supportPrivateTabs || privateState === isPrivate(activeWindow))) {
-      activeWindow.tabs.open(options);
-    }
-    else {
-      // find a window in the state that we need
-      let window = getWindow(privateState);
-      if (window) {
-        window.tabs.open(options);
-      }
-      // open a window in the state that we need
-      else {
-        newTabWindow(options);
-      }
-    }
+    if (activeWindow && (privateState === isPrivate(activeWindow)))
+      return activeWindow.tabs.open(options);
 
-    return undefined;
-  }}
+    // find a window in the state that we need
+    let window = getWindow(privateState);
+    if (window)
+      return window.tabs.open(options);
+
+    return openNewWindowWithTab();
+  }
 });
 
-function getWindow(privateState) {
-  for (let window of windows) {
-    if (privateState === isPrivate(window)) {
-      return window;
-    }
-  }
-  return null;
+const allTabs = new Tabs();
+// Export a new object with allTabs as the prototype, otherwise allTabs becomes
+// frozen and addListItem and removeListItem don't work correctly.
+module.exports = Object.create(allTabs);
+pipe(tabEvents, module.exports);
+
+function addWindowTab(window, tabElement) {
+  let tab = new Tab(tabElement);
+  if (window)
+    addListItem(window.tabs, tab);
+  addListItem(allTabs, tab);
 }
 
-// Workaround for bug 674195. Freezing objects from other compartments fail,
-// so we use `Object.freeze` from the same component as objects
-// `hasOwnProperty`. Since `hasOwnProperty` here will be from other component
-// we override it to support our workaround.
-module.exports = Object.create(tabs, {
-  isPrototypeOf: { value: Object.prototype.isPrototypeOf }
+// Find tabs in already open windows
+for (let tabElement of getTabs())
+  addWindowTab(null, tabElement);
+
+// Detect tabs in new windows
+windowObserver.on('open', domWindow => {
+  if (!isBrowser(domWindow) || ignoreWindow(domWindow))
+    return;
+
+  let window = null;
+  try {
+    modelFor(domWindow);
+  }
+  catch (e) { }
+
+  for (let tabElement of getTabs(domWindow)) {
+    addWindowTab(window, tabElement);
+  }
 });
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ b/addon-sdk/source/lib/sdk/tabs/utils.js
@@ -208,24 +208,35 @@ function getTabId(tab) {
 exports.getTabId = getTabId;
 
 function getTabForId(id) {
   return getTabs().find(tab => getTabId(tab) === id) || null;
 }
 exports.getTabForId = getTabForId;
 
 function getTabTitle(tab) {
-  return getBrowserForTab(tab).contentDocument.title || tab.label || "";
+  return getBrowserForTab(tab).contentTitle || tab.label || "";
 }
 exports.getTabTitle = getTabTitle;
 
 function setTabTitle(tab, title) {
   title = String(title);
-  if (tab.browser)
+  if (tab.browser) {
+    // Fennec
     tab.browser.contentDocument.title = title;
+  }
+  else {
+    let browser = getBrowserForTab(tab);
+    // Note that we aren't actually setting the document title in e10s, just
+    // the title the browser thinks the content has
+    if (browser.isRemoteBrowser)
+      browser._contentTitle = title;
+    else
+      browser.contentDocument.title = title;
+  }
   tab.label = String(title);
 }
 exports.setTabTitle = setTabTitle;
 
 function getTabContentDocument(tab) {
   return getBrowserForTab(tab).contentDocument;
 }
 exports.getTabContentDocument = getTabContentDocument;
@@ -245,27 +256,23 @@ exports.getAllTabContentWindows = getAll
 
 // gets the tab containing the provided window
 function getTabForContentWindow(window) {
   return getTabs().find(tab => getTabContentWindow(tab) === window.top) || null;
 }
 exports.getTabForContentWindow = getTabForContentWindow;
 
 function getTabURL(tab) {
-  if (tab.browser) // fennec
-    return String(tab.browser.currentURI.spec);
   return String(getBrowserForTab(tab).currentURI.spec);
 }
 exports.getTabURL = getTabURL;
 
 function setTabURL(tab, url) {
-  url = String(url);
-  if (tab.browser)
-    return tab.browser.loadURI(url);
-  return getBrowserForTab(tab).loadURI(url);
+  let browser = getBrowserForTab(tab);
+  browser.loadURI(String(url));
 }
 // "TabOpen" event is fired when it's still "about:blank" is loaded in the
 // changing `location` property of the `contentDocument` has no effect since
 // seems to be either ignored or overridden by internal listener, there for
 // location change is enqueued for the next turn of event loop.
 exports.setTabURL = defer(setTabURL);
 
 function getTabContentType(tab) {
@@ -313,30 +320,25 @@ function unpin(tab) {
   if (gBrowser) gBrowser.unpinTab(tab);
 }
 exports.unpin = unpin;
 
 function isPinned(tab) !!tab.pinned
 exports.isPinned = isPinned;
 
 function reload(tab) {
-  let gBrowser = getTabBrowserForTab(tab);
-  // Firefox
-  if (gBrowser) gBrowser.unpinTab(tab);
-  // Fennec
-  else if (tab.browser) tab.browser.reload();
+  getBrowserForTab(tab).reload();
 }
 exports.reload = reload
 
 function getIndex(tab) {
   let gBrowser = getTabBrowserForTab(tab);
   // Firefox
   if (gBrowser) {
-    let document = getBrowserForTab(tab).contentDocument;
-    return gBrowser.getBrowserIndexForDocument(document);
+    return tab._tPos;
   }
   // Fennec
   else {
     let window = getWindowHoldingTab(tab)
     let tabs = window.BrowserApp.tabs;
     for (let i = tabs.length; i >= 0; i--)
       if (tabs[i] === tab) return i;
   }
--- a/addon-sdk/source/lib/sdk/test/harness.js
+++ b/addon-sdk/source/lib/sdk/test/harness.js
@@ -434,16 +434,22 @@ var POINTLESS_ERRORS = [
   '[JavaScript Warning: "Duplicate resource declaration for',
   'file: "chrome://browser/content/',
   'file: "chrome://global/content/',
   '[JavaScript Warning: "The character encoding of a framed document was ' +
     'not declared.',
   'file: "chrome://browser/skin/'
 ];
 
+// These are messages that will cause a test to fail if logged through the
+// console service
+var IMPORTANT_ERRORS = [
+  'Sending message that cannot be cloned. Are you trying to send an XPCOM object?',
+];
+
 var consoleListener = {
   registered: false,
 
   register: function() {
     if (this.registered)
       return;
     cService.registerListener(this);
     this.registered = true;
@@ -458,16 +464,20 @@ var consoleListener = {
 
   errorsLogged: 0,
 
   observe: function(object) {
     if (!(object instanceof Ci.nsIScriptError))
       return;
     this.errorsLogged++;
     var message = object.QueryInterface(Ci.nsIConsoleMessage).message;
+    if (IMPORTANT_ERRORS.find(msg => message.indexOf(msg) >= 0)) {
+      testConsole.error(message);
+      return;
+    }
     var pointless = [err for (err of POINTLESS_ERRORS)
                          if (message.indexOf(err) >= 0)];
     if (pointless.length == 0 && message)
       testConsole.log(message);
   }
 };
 
 function TestRunnerConsole(base, options) {
@@ -5