Merge m-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 24 Jan 2017 18:53:29 -0800
changeset 330949 6dccae211ae5fec6a1c1244b878ce0b93860154f
parent 330948 36896a90b68cc4e3a9a7d3d18186d95d6a56d852 (current diff)
parent 330833 6abcbe944f8f36edf1f710c9ab32dec6b371d392 (diff)
child 330950 e95b9a135ec11325a8484b06af262ae31cb89f88
child 330999 31fbf417b0fe07e7418b30e16ec99dc547042e3a
push id86116
push userphilringnalda@gmail.com
push dateWed, 25 Jan 2017 02:57:57 +0000
treeherdermozilla-inbound@e95b9a135ec1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
6dccae211ae5 / 54.0a1 / 20170125110119 / files
nightly linux64
6dccae211ae5 / 54.0a1 / 20170125110119 / files
nightly mac
6dccae211ae5 / 54.0a1 / 20170125030214 / files
nightly win32
6dccae211ae5 / 54.0a1 / 20170125030214 / files
nightly win64
6dccae211ae5 / 54.0a1 / 20170125030214 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c, a=merge
browser/components/extensions/ext-devtools.js
dom/ipc/TabChild.cpp
toolkit/components/telemetry/Histograms.json
toolkit/identity/FirefoxAccounts.jsm
toolkit/identity/Identity.jsm
toolkit/identity/IdentityCryptoService.cpp
toolkit/identity/IdentityProvider.jsm
toolkit/identity/IdentityStore.jsm
toolkit/identity/IdentityUtils.jsm
toolkit/identity/LogUtils.jsm
toolkit/identity/MinimalIdentity.jsm
toolkit/identity/RelyingParty.jsm
toolkit/identity/Sandbox.jsm
toolkit/identity/jwcrypto.jsm
toolkit/identity/moz.build
toolkit/identity/nsIIdentityCryptoService.idl
toolkit/identity/tests/chrome/.eslintrc.js
toolkit/identity/tests/chrome/chrome.ini
toolkit/identity/tests/chrome/sandbox_content.html
toolkit/identity/tests/chrome/sandbox_content.sjs
toolkit/identity/tests/chrome/sandbox_content_alert.html
toolkit/identity/tests/chrome/sandbox_content_framed.html
toolkit/identity/tests/chrome/sandbox_content_perms.html
toolkit/identity/tests/chrome/sandbox_content_popup.html
toolkit/identity/tests/chrome/sandbox_content_redirect.html
toolkit/identity/tests/chrome/sandbox_content_redirect.html^headers^
toolkit/identity/tests/chrome/test_sandbox.xul
toolkit/identity/tests/unit/.eslintrc.js
toolkit/identity/tests/unit/data/idp_1/.well-known/browserid
toolkit/identity/tests/unit/data/idp_invalid_1/.well-known/browserid
toolkit/identity/tests/unit/head_identity.js
toolkit/identity/tests/unit/test_authentication.js
toolkit/identity/tests/unit/test_crypto_service.js
toolkit/identity/tests/unit/test_firefox_accounts.js
toolkit/identity/tests/unit/test_identity.js
toolkit/identity/tests/unit/test_identity_utils.js
toolkit/identity/tests/unit/test_jwcrypto.js
toolkit/identity/tests/unit/test_load_modules.js
toolkit/identity/tests/unit/test_log_utils.js
toolkit/identity/tests/unit/test_minimalidentity.js
toolkit/identity/tests/unit/test_observer_topics.js
toolkit/identity/tests/unit/test_provisioning.js
toolkit/identity/tests/unit/test_relying_party.js
toolkit/identity/tests/unit/test_store.js
toolkit/identity/tests/unit/test_well-known.js
toolkit/identity/tests/unit/xpcshell.ini
--- a/.eslintignore
+++ b/.eslintignore
@@ -205,17 +205,16 @@ toolkit/components/microformats/test/**
 toolkit/components/reader/Readability.js
 toolkit/components/reader/JSDOMParser.js
 
 # Uses preprocessing
 toolkit/content/widgets/wizard.xml
 toolkit/components/jsdownloads/src/DownloadIntegration.jsm
 toolkit/components/url-classifier/**
 toolkit/components/urlformatter/nsURLFormatter.js
-toolkit/identity/FirefoxAccounts.jsm
 toolkit/modules/AppConstants.jsm
 toolkit/mozapps/downloads/nsHelperAppDlg.js
 toolkit/mozapps/extensions/internal/AddonConstants.jsm
 toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
 toolkit/webapps/**
 
 # Third party
 toolkit/modules/third_party/**
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -7,16 +7,23 @@
 #include "DocAccessibleParent.h"
 #include "mozilla/a11y/Platform.h"
 #include "mozilla/dom/TabParent.h"
 #include "xpcAccessibleDocument.h"
 #include "xpcAccEvents.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 
+#if defined(XP_WIN)
+#include "AccessibleWrap.h"
+#include "Compatibility.h"
+#include "nsWinUtils.h"
+#include "RootAccessible.h"
+#endif
+
 namespace mozilla {
 namespace a11y {
 
 mozilla::ipc::IPCResult
 DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
                                    const bool& aFromUser)
 {
   if (mShutdown)
@@ -520,17 +527,53 @@ DocAccessibleParent::SetCOMProxy(const R
   IAccessible* rawNative = nullptr;
   if (outerDoc) {
     outerDoc->GetNativeInterface((void**) &rawNative);
     MOZ_ASSERT(rawNative);
   }
 
   IAccessibleHolder::COMPtrType ptr(rawNative);
   IAccessibleHolder holder(Move(ptr));
-  Unused << SendParentCOMProxy(holder);
+
+  if (nsWinUtils::IsWindowEmulationStarted()) {
+    RootAccessible* rootDocument = outerDoc->RootAccessible();
+    MOZ_ASSERT(rootDocument);
+
+    bool isActive = true;
+    nsIntRect rect(CW_USEDEFAULT, CW_USEDEFAULT, 0, 0);
+    if (Compatibility::IsDolphin()) {
+      rect = Bounds();
+      nsIntRect rootRect = rootDocument->Bounds();
+      rect.x = rootRect.x - rect.x;
+      rect.y -= rootRect.y;
+      tab->GetDocShellIsActive(&isActive);
+    }
+
+    HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
+    HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
+                                               parentWnd, rect.x, rect.y,
+                                               rect.width, rect.height,
+                                               isActive);
+    if (hWnd) {
+      // Attach accessible document to the emulated native window
+      ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this);
+      SetEmulatedWindowHandle(hWnd);
+    }
+  }
+  Unused << SendParentCOMProxy(holder, reinterpret_cast<uintptr_t>(
+                               mEmulatedWindowHandle));
+}
+
+void
+DocAccessibleParent::SetEmulatedWindowHandle(HWND aWindowHandle)
+{
+  if (!aWindowHandle && mEmulatedWindowHandle && IsTopLevel()) {
+    ::DestroyWindow(mEmulatedWindowHandle);
+  }
+  mEmulatedWindowHandle = aWindowHandle;
 }
 
 mozilla::ipc::IPCResult
 DocAccessibleParent::RecvGetWindowedPluginIAccessible(
       const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy)
 {
 #if defined(MOZ_CONTENT_SANDBOX)
   // We don't actually want the accessible object for aHwnd, but rather the
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -25,16 +25,19 @@ class xpcAccessibleGeneric;
  */
 class DocAccessibleParent : public ProxyAccessible,
     public PDocAccessibleParent
 {
 public:
   DocAccessibleParent() :
     ProxyAccessible(this), mParentDoc(nullptr),
     mTopLevel(false), mShutdown(false)
+#if defined(XP_WIN)
+                                      , mEmulatedWindowHandle(nullptr)
+#endif // defined(XP_WIN)
   { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); }
   ~DocAccessibleParent()
   {
     MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
     MOZ_ASSERT(mChildDocs.Length() == 0);
     MOZ_ASSERT(!ParentDoc());
   }
 
@@ -146,16 +149,23 @@ public:
   const DocAccessibleParent* ChildDocAt(size_t aIdx) const
     { return mChildDocs[aIdx]; }
 
 #if defined(XP_WIN)
   void SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy);
 
   virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible(
       const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override;
+
+  /**
+   * Set emulated native window handle for a document.
+   * @param aWindowHandle emulated native window handle
+   */
+  void SetEmulatedWindowHandle(HWND aWindowHandle);
+  HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
 #endif
 
 private:
 
   class ProxyEntry : public PLDHashEntryHdr
   {
   public:
     explicit ProxyEntry(const void*) : mProxy(nullptr) {}
@@ -182,16 +192,21 @@ private:
                       const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
                       uint32_t aIdxInParent);
   MOZ_MUST_USE bool CheckDocTree() const;
   xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
 
   nsTArray<DocAccessibleParent*> mChildDocs;
   DocAccessibleParent* mParentDoc;
 
+#if defined(XP_WIN)
+  // The handle associated with the emulated window that contains this document
+  HWND mEmulatedWindowHandle;
+#endif
+
   /*
    * Conceptually this is a map from IDs to proxies, but we store the ID in the
    * proxy object so we can't use a real map.
    */
   nsTHashtable<ProxyEntry> mAccessibles;
   bool mTopLevel;
   bool mShutdown;
 };
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -13,16 +13,17 @@
 
 namespace mozilla {
 namespace a11y {
 
 static StaticAutoPtr<PlatformChild> sPlatformChild;
 
 DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
   : DocAccessibleChildBase(aDoc)
+  , mEmulatedWindowHandle(nullptr)
   , mIsRemoteConstructed(false)
 {
   MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
   if (!sPlatformChild) {
     sPlatformChild = new PlatformChild();
     ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown);
   }
 }
@@ -40,21 +41,23 @@ DocAccessibleChild::Shutdown()
     return;
   }
 
   PushDeferredEvent(MakeUnique<SerializedShutdown>(this));
   DetachDocument();
 }
 
 ipc::IPCResult
-DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy)
+DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy,
+                                       const WindowsHandle& aEmulatedWindowHandle)
 {
   MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull());
   mParentProxy.reset(const_cast<IAccessibleHolder&>(aParentCOMProxy).Release());
   SetConstructedInParentProcess();
+  mEmulatedWindowHandle = reinterpret_cast<HWND>(aEmulatedWindowHandle);
 
   for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) {
     mDeferredEvents[i]->Dispatch();
   }
 
   mDeferredEvents.Clear();
 
   return IPC_OK();
--- a/accessible/ipc/win/DocAccessibleChild.h
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -23,17 +23,20 @@ class DocAccessibleChild : public DocAcc
 {
 public:
   explicit DocAccessibleChild(DocAccessible* aDoc);
   ~DocAccessibleChild();
 
   virtual void Shutdown() override;
 
   virtual ipc::IPCResult
-  RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
+  RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy,
+                     const WindowsHandle& aEmulatedWindowHandle) override;
+
+  HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
 
   IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }
 
   bool SendEvent(const uint64_t& aID, const uint32_t& type);
   bool SendHideEvent(const uint64_t& aRootID, const bool& aFromUser);
   bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState,
                             const bool& aEnabled);
   bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset);
@@ -305,14 +308,15 @@ private:
     {
       aIPCDoc->Shutdown();
     }
   };
 
   bool mIsRemoteConstructed;
   mscom::ProxyUniquePtr<IAccessible> mParentProxy;
   nsTArray<UniquePtr<DeferredEvent>> mDeferredEvents;
+  HWND mEmulatedWindowHandle;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_DocAccessibleChild_h
--- a/accessible/ipc/win/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -61,15 +61,16 @@ parent:
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
   sync GetWindowedPluginIAccessible(WindowsHandle aHwnd)
     returns (IAccessibleHolder aPluginCOMProxy);
 
 child:
-  async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
+  async ParentCOMProxy(IAccessibleHolder aParentCOMProxy,
+                       WindowsHandle aEmulatedWindowHandle);
 
   async __delete__();
 };
 
 }
 }
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -1394,17 +1394,20 @@ AccessibleWrap::GetIAccessibleFor(const 
     varChild.lVal = GetExistingID();
   }
 
   if (IsProxy() ? Proxy()->MustPruneChildren() : nsAccUtils::MustPrune(this)) {
     return nullptr;
   }
 
   // If the MSAA ID is not a chrome id then we already know that we won't
-  // find it here and should look remotely instead.
+  // find it here and should look remotely instead. This handles the case when
+  // accessible is part of the chrome process and is part of the xul browser
+  // window and the child id points in the content documents. Thus we need to
+  // make sure that it is never called on proxies.
   if (XRE_IsParentProcess() && !IsProxy() && !sIDGen.IsChromeID(varChild.lVal)) {
     return GetRemoteIAccessibleFor(varChild);
   }
   MOZ_ASSERT(XRE_IsParentProcess() ||
              sIDGen.IsIDForThisContentProcess(varChild.lVal));
 
   if (varChild.lVal > 0) {
     // Gecko child indices are 0-based in contrast to indices used in MSAA.
--- a/accessible/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/windows/msaa/DocAccessibleWrap.cpp
@@ -115,16 +115,21 @@ DocAccessibleWrap::Shutdown()
 ////////////////////////////////////////////////////////////////////////////////
 // DocAccessible public
 
 void*
 DocAccessibleWrap::GetNativeWindow() const
 {
   if (XRE_IsContentProcess()) {
     DocAccessibleChild* ipcDoc = IPCDoc();
+    HWND hWnd = ipcDoc->GetEmulatedWindowHandle();
+    if (hWnd) {
+      return hWnd;
+    }
+
     auto tab = static_cast<dom::TabChild*>(ipcDoc->Manager());
     MOZ_ASSERT(tab);
     return reinterpret_cast<HWND>(tab->GetNativeWindowHandle());
   } else if (mHWND) {
     return mHWND;
   }
   return DocAccessible::GetNativeWindow();
 }
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -80,16 +80,20 @@ void
 a11y::ProxyDestroyed(ProxyAccessible* aProxy)
 {
   AccessibleWrap* wrapper =
     reinterpret_cast<AccessibleWrap*>(aProxy->GetWrapper());
   MOZ_ASSERT(wrapper);
   if (!wrapper)
     return;
 
+  if (aProxy->IsDoc() && nsWinUtils::IsWindowEmulationStarted()) {
+    aProxy->AsDoc()->SetEmulatedWindowHandle(nullptr);
+  }
+
   wrapper->Shutdown();
   aProxy->SetWrapper(0);
   wrapper->Release();
 }
 
 void
 a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
 {
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -9,16 +9,17 @@ EXPORTS += [
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'Compatibility.h',
     'HyperTextAccessibleWrap.h',
     'IDSet.h',
     'MsaaIdGenerator.h',
+    'nsWinUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
--- a/accessible/windows/msaa/nsWinUtils.cpp
+++ b/accessible/windows/msaa/nsWinUtils.cpp
@@ -7,24 +7,26 @@
 
 #include "nsWinUtils.h"
 
 #include "Compatibility.h"
 #include "DocAccessible.h"
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 
+#include "mozilla/a11y/DocAccessibleParent.h"
 #include "mozilla/Preferences.h"
 #include "nsArrayUtils.h"
 #include "nsIArray.h"
 #include "nsICSSDeclaration.h"
 #include "nsIDocument.h"
 #include "nsIDocShellTreeItem.h"
 #include "mozilla/dom/Element.h"
 #include "nsXULAppAPI.h"
+#include "ProxyWrappers.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using mozilla::dom::Element;
 
 // Window property used by ipc related code in identifying accessible
 // tab windows.
 const wchar_t* kPropNameTabContent = L"AccessibleTabWindow";
@@ -148,28 +150,35 @@ WindowProc(HWND hWnd, UINT msg, WPARAM w
 
   switch (msg) {
     case WM_GETOBJECT:
     {
       // Do explicit casting to make it working on 64bit systems (see bug 649236
       // for details).
       int32_t objId = static_cast<DWORD>(lParam);
       if (objId == OBJID_CLIENT) {
+        IAccessible* msaaAccessible = nullptr;
         DocAccessible* document =
           reinterpret_cast<DocAccessible*>(::GetPropW(hWnd, kPropNameDocAcc));
         if (document) {
-          IAccessible* msaaAccessible = nullptr;
           document->GetNativeInterface((void**)&msaaAccessible); // does an addref
-          if (msaaAccessible) {
-            LRESULT result = ::LresultFromObject(IID_IAccessible, wParam,
-                                                 msaaAccessible); // does an addref
-            msaaAccessible->Release(); // release extra addref
-            return result;
+        } else {
+          DocAccessibleParent* docParent = static_cast<DocAccessibleParent*>(
+            ::GetPropW(hWnd, kPropNameDocAccParent));
+          if (docParent) {
+            auto wrapper = WrapperFor(docParent);
+            wrapper->GetNativeInterface((void**)&msaaAccessible); // does an addref
           }
         }
+        if (msaaAccessible) {
+          LRESULT result = ::LresultFromObject(IID_IAccessible, wParam,
+                                               msaaAccessible); // does an addref
+          msaaAccessible->Release(); // release extra addref
+          return result;
+        }
       }
       return 0;
     }
     case WM_NCHITTEST:
     {
       LRESULT lRet = ::DefWindowProc(hWnd, msg, wParam, lParam);
       if (HTCLIENT == lRet)
         lRet = HTTRANSPARENT;
--- a/accessible/windows/msaa/nsWinUtils.h
+++ b/accessible/windows/msaa/nsWinUtils.h
@@ -18,16 +18,17 @@ class nsIContent;
 namespace mozilla {
 namespace a11y {
 
 class DocAccessible;
 
 const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass";
 const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
 const LPCWSTR kPropNameDocAcc = L"MozDocAccessible";
+const LPCWSTR kPropNameDocAccParent = L"MozDocAccessibleParent";
 
 class nsWinUtils
 {
 public:
   /**
    * Return computed styles declaration for the given node.
    *
    * @note Please use it carefully since it can shutdown the accessible tree
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4664,18 +4664,25 @@
                 stringID = tab.linkedBrowser.audioMuted ?
                   "tabs.unmuteAudio.background.tooltip" :
                   "tabs.muteAudio.background.tooltip";
               }
 
               label = this.mStringBundle.getString(stringID);
             }
           } else {
-            label = tab.getAttribute("label") +
-                      (this.AppConstants.E10S_TESTING_ONLY && tab.linkedBrowser && tab.linkedBrowser.isRemoteBrowser ? " - e10s" : "");
+            label = tab.getAttribute("label");
+            if (this.AppConstants.E10S_TESTING_ONLY &&
+                tab.linkedBrowser &&
+                tab.linkedBrowser.isRemoteBrowser) {
+              label += " - e10s";
+              if (Services.prefs.getIntPref("dom.ipc.processCount") > 1) {
+                label += " (" + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
+              }
+            }
             if (tab.userContextId) {
               label = this.mStringBundle.getFormattedString("tabs.containers.tooltip", [label, ContextualIdentityService.getUserContextLabel(tab.userContextId)]);
             }
           }
 
           event.target.setAttribute("label", label);
         ]]></body>
       </method>
--- a/browser/base/content/test/newtab/browser.ini
+++ b/browser/base/content/test/newtab/browser.ini
@@ -22,17 +22,18 @@ skip-if = (os == "mac" && debug) # tempo
 [browser_newtab_bug998387.js]
 [browser_newtab_bug1145428.js]
 [browser_newtab_bug1178586.js]
 [browser_newtab_bug1194895.js]
 [browser_newtab_bug1271075.js]
 [browser_newtab_disable.js]
 [browser_newtab_drag_drop.js]
 [browser_newtab_drag_drop_ext.js]
-subsuite = clipboard # temporary until determine why more intermittent on VM
+# temporary until determine why more intermittent on VM
+subsuite = clipboard
 [browser_newtab_drop_preview.js]
 [browser_newtab_enhanced.js]
 [browser_newtab_focus.js]
 [browser_newtab_perwindow_private_browsing.js]
 [browser_newtab_reportLinkAction.js]
 [browser_newtab_reflow_load.js]
 support-files =
   content-reflows.js
--- a/browser/components/extensions/ext-devtools.js
+++ b/browser/components/extensions/ext-devtools.js
@@ -19,16 +19,18 @@ Cu.import("resource://gre/modules/Extens
 const {
   HiddenExtensionPage,
   watchExtensionProxyContextLoad,
 } = ExtensionParent;
 
 // Map[extension -> DevToolsPageDefinition]
 let devtoolsPageDefinitionMap = new Map();
 
+let initDevTools;
+
 /**
  * Retrieve the devtools target for the devtools extension proxy context
  * (lazily cloned from the target of the toolbox associated to the context
  * the first time that it is accessed).
  *
  * @param {DevToolsExtensionPageContextParent} context
  *   A devtools extension proxy context.
  *
@@ -189,16 +191,18 @@ class DevToolsPage extends HiddenExtensi
  *
  * @param {Extension} extension
  *   The extension that owns the devtools_page.
  * @param {string}    url
  *   The path to the devtools page html page relative to the extension base URL.
  */
 class DevToolsPageDefinition {
   constructor(extension, url) {
+    initDevTools();
+
     this.url = url;
     this.extension = extension;
 
     // Map[TabTarget -> DevToolsPage]
     this.devtoolsPageForTarget = new Map();
   }
 
   buildForToolbox(toolbox) {
@@ -241,51 +245,60 @@ class DevToolsPageDefinition {
         `Leaked ${this.devtoolsPageForTarget.size} DevToolsPage instances in devtoolsPageForTarget Map`
       );
     }
   }
 }
 
 /* eslint-disable mozilla/balanced-listeners */
 
-// Create a devtools page context for a new opened toolbox,
-// based on the registered devtools_page definitions.
-gDevTools.on("toolbox-created", (evt, toolbox) => {
-  if (!toolbox.target.isLocalTab) {
-    // Only local tabs are currently supported (See Bug 1304378 for additional details
-    // related to remote targets support).
-    let msg = `Ignoring DevTools Toolbox for target "${toolbox.target.toString()}": ` +
-              `"${toolbox.target.name}" ("${toolbox.target.url}"). ` +
-              "Only local tab are currently supported by the WebExtensions DevTools API.";
-    let scriptError = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
-    scriptError.init(msg, null, null, null, null, Ci.nsIScriptError.warningFlag, "content javascript");
-    let consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
-    consoleService.logMessage(scriptError);
-
+let devToolsInitialized = false;
+initDevTools = function() {
+  if (devToolsInitialized) {
     return;
   }
 
-  for (let devtoolsPage of devtoolsPageDefinitionMap.values()) {
-    devtoolsPage.buildForToolbox(toolbox);
-  }
-});
+  // Create a devtools page context for a new opened toolbox,
+  // based on the registered devtools_page definitions.
+  gDevTools.on("toolbox-created", (evt, toolbox) => {
+    if (!toolbox.target.isLocalTab) {
+      // Only local tabs are currently supported (See Bug 1304378 for additional details
+      // related to remote targets support).
+      let msg = `Ignoring DevTools Toolbox for target "${toolbox.target.toString()}": ` +
+                `"${toolbox.target.name}" ("${toolbox.target.url}"). ` +
+                "Only local tab are currently supported by the WebExtensions DevTools API.";
+      let scriptError = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
+      scriptError.init(msg, null, null, null, null, Ci.nsIScriptError.warningFlag, "content javascript");
+      let consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+      consoleService.logMessage(scriptError);
+
+      return;
+    }
 
-// Destroy a devtools page context for a destroyed toolbox,
-// based on the registered devtools_page definitions.
-gDevTools.on("toolbox-destroy", (evt, target) => {
-  if (!target.isLocalTab) {
-    // Only local tabs are currently supported (See Bug 1304378 for additional details
-    // related to remote targets support).
-    return;
-  }
+    for (let devtoolsPage of devtoolsPageDefinitionMap.values()) {
+      devtoolsPage.buildForToolbox(toolbox);
+    }
+  });
 
-  for (let devtoolsPageDefinition of devtoolsPageDefinitionMap.values()) {
-    devtoolsPageDefinition.shutdownForTarget(target);
-  }
-});
+  // Destroy a devtools page context for a destroyed toolbox,
+  // based on the registered devtools_page definitions.
+  gDevTools.on("toolbox-destroy", (evt, target) => {
+    if (!target.isLocalTab) {
+      // Only local tabs are currently supported (See Bug 1304378 for additional details
+      // related to remote targets support).
+      return;
+    }
+
+    for (let devtoolsPageDefinition of devtoolsPageDefinitionMap.values()) {
+      devtoolsPageDefinition.shutdownForTarget(target);
+    }
+  });
+
+  devToolsInitialized = true;
+};
 
 // Create and register a new devtools_page definition as specified in the
 // "devtools_page" property in the extension manifest.
 extensions.on("manifest_devtools_page", (type, directive, extension, manifest) => {
   let devtoolsPageDefinition = new DevToolsPageDefinition(extension, manifest[directive]);
   devtoolsPageDefinitionMap.set(extension, devtoolsPageDefinition);
 });
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -228,17 +228,16 @@
 @RESPATH@/components/fastfind.xpt
 @RESPATH@/components/feeds.xpt
 #ifdef MOZ_GTK
 @RESPATH@/components/filepicker.xpt
 #endif
 @RESPATH@/components/gfx.xpt
 @RESPATH@/components/html5.xpt
 @RESPATH@/components/htmlparser.xpt
-@RESPATH@/components/identity.xpt
 @RESPATH@/components/imglib2.xpt
 @RESPATH@/components/inspector.xpt
 @RESPATH@/components/intl.xpt
 @RESPATH@/components/jar.xpt
 @RESPATH@/components/jsdebugger.xpt
 @RESPATH@/components/jsdownloads.xpt
 @RESPATH@/browser/components/jsinspector.xpt
 @RESPATH@/components/layout_base.xpt
--- a/caps/nsNullPrincipalURI.cpp
+++ b/caps/nsNullPrincipalURI.cpp
@@ -93,16 +93,18 @@ nsNullPrincipalURI::GetAsciiHostPort(nsA
 }
 
 NS_IMETHODIMP
 nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
 {
   nsAutoCString buffer;
   // Ignore the return value -- nsNullPrincipalURI::GetSpec() is infallible.
   Unused << GetSpec(buffer);
+  // This uses the infallible version of |NS_EscapeURL| as |GetSpec| is
+  // already infallible.
   NS_EscapeURL(buffer, esc_OnlyNonASCII | esc_AlwaysCopy, _spec);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNullPrincipalURI::GetHost(nsACString &_host)
 {
   _host.Truncate();
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -751,16 +751,18 @@ DecreasePrivateDocShellCount()
       obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
     }
   }
 }
 
 nsDocShell::nsDocShell()
   : nsDocLoader()
   , mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto)
+  , mReferrerPolicy(0)
+  , mFailedLoadType(0)
   , mTreeOwner(nullptr)
   , mChromeEventHandler(nullptr)
   , mCharsetReloadState(eCharsetReloadInit)
   , mChildOffset(0)
   , mBusyFlags(BUSY_FLAGS_NONE)
   , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
   , mLoadType(0)
   , mMarginWidth(-1)
@@ -800,16 +802,17 @@ nsDocShell::nsDocShell()
   , mCanExecuteScripts(false)
   , mFiredUnloadEvent(false)
   , mEODForCurrentDocument(false)
   , mURIResultedInDocument(false)
   , mIsBeingDestroyed(false)
   , mIsExecutingOnLoadHandler(false)
   , mIsPrintingOrPP(false)
   , mSavingOldViewer(false)
+  , mDynamicallyCreated(false)
   , mAffectPrivateSessionLifetime(true)
   , mInvisible(false)
   , mHasLoadedNonBlankURI(false)
   , mBlankTiming(false)
   , mCreatingDocument(false)
 #ifdef DEBUG
   , mInEnsureScriptEnv(false)
 #endif
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -153,18 +153,16 @@ class nsDocShell final
 {
   friend class nsDSURIContentListener;
 
 public:
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsDocShell)
 
   nsDocShell();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   virtual nsresult Init() override;
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOCSHELL
   NS_DECL_NSIDOCSHELLTREEITEM
   NS_DECL_NSIWEBNAVIGATION
   NS_DECL_NSIBASEWINDOW
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -232,24 +232,47 @@ public:
 
   void RemoveClone(nsMutationReceiverBase* aClone)
   {
     mTransientReceivers.RemoveObject(aClone);
   }
   
 protected:
   nsMutationReceiverBase(nsINode* aTarget, nsDOMMutationObserver* aObserver)
-  : mTarget(aTarget), mObserver(aObserver), mRegisterTarget(aTarget)
+    : mTarget(aTarget)
+    , mObserver(aObserver)
+    , mRegisterTarget(aTarget)
+    , mSubtree(false)
+    , mChildList(false)
+    , mCharacterData(false)
+    , mCharacterDataOldValue(false)
+    , mNativeAnonymousChildList(false)
+    , mAttributes(false)
+    , mAllAttributes(false)
+    , mAttributeOldValue(false)
+    , mAnimations(false)
   {
   }
 
   nsMutationReceiverBase(nsINode* aRegisterTarget,
                          nsMutationReceiverBase* aParent)
-  : mTarget(nullptr), mObserver(nullptr), mParent(aParent),
-    mRegisterTarget(aRegisterTarget), mKungFuDeathGrip(aParent->Target())
+    : mTarget(nullptr)
+    , mObserver(nullptr)
+    , mParent(aParent)
+    , mRegisterTarget(aRegisterTarget)
+    , mKungFuDeathGrip(aParent->Target())
+    , mSubtree(false)
+    , mChildList(false)
+    , mCharacterData(false)
+    , mCharacterDataOldValue(false)
+    , mNativeAnonymousChildList(false)
+    , mAttributes(false)
+    , mAllAttributes(false)
+    , mAttributeOldValue(false)
+    , mAnimations(false)
   {
     NS_ASSERTION(mParent->Subtree(), "Should clone a non-subtree observer!");
   }
 
   virtual void AddMutationObserver() = 0;
 
   void AddObserver()
   {
@@ -364,17 +387,16 @@ public:
 
     mParent = nullptr;
     NS_ASSERTION(!mTarget, "Should not have mTarget");
     NS_ASSERTION(!mObserver, "Should not have mObserver");
   }
 
   void Disconnect(bool aRemoveFromObserver);
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
   NS_DECL_NSIMUTATIONOBSERVER_NATIVEANONYMOUSCHILDLISTCHANGE
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1278,50 +1278,156 @@ nsIDocument::nsIDocument()
   : nsINode(nullNodeInfo),
     mReferrerPolicySet(false),
     mReferrerPolicy(mozilla::net::RP_Unset),
     mBlockAllMixedContent(false),
     mBlockAllMixedContentPreloads(false),
     mUpgradeInsecureRequests(false),
     mUpgradeInsecurePreloads(false),
     mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
+    mCharacterSetSource(0),
+    mParentDocument(nullptr),
+    mCachedRootElement(nullptr),
     mNodeInfoManager(nullptr),
+    mBidiEnabled(false),
+    mMathMLEnabled(false),
     mIsInitialDocumentInWindow(false),
+    mLoadedAsData(false),
+    mLoadedAsInteractiveData(false),
     mMayStartLayout(true),
+    mHaveFiredTitleChange(false),
+    mIsShowing(false),
     mVisible(true),
+    mHasReferrerPolicyCSP(false),
     mRemovedFromDocShell(false),
     // mAllowDNSPrefetch starts true, so that we can always reliably && it
     // with various values that might disable it.  Since we never prefetch
     // unless we get a window, and in that case the docshell value will get
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
+    mIsStaticDocument(false),
+    mCreatingStaticClone(false),
+    mInUnlinkOrDeletion(false),
+    mHasHadScriptHandlingObject(false),
     mIsBeingUsedAsImage(false),
+    mIsSyntheticDocument(false),
     mHasLinksToUpdate(false),
+    mNeedLayoutFlush(false),
+    mNeedStyleFlush(false),
+    mMayHaveDOMMutationObservers(false),
+    mMayHaveAnimationObservers(false),
+    mHasMixedActiveContentLoaded(false),
+    mHasMixedActiveContentBlocked(false),
+    mHasMixedDisplayContentLoaded(false),
+    mHasMixedDisplayContentBlocked(false),
+    mHasMixedContentObjectSubrequest(false),
+    mHasCSP(false),
+    mHasUnsafeEvalCSP(false),
+    mHasUnsafeInlineCSP(false),
+    mHasTrackingContentBlocked(false),
+    mHasTrackingContentLoaded(false),
+    mBFCacheDisallowed(false),
+    mHasHadDefaultView(false),
+    mStyleSheetChangeEventsEnabled(false),
+    mIsSrcdocDocument(false),
+    mDidDocumentOpen(false),
+    mHasDisplayDocument(false),
     mFontFaceSetDirty(true),
     mGetUserFontSetCalled(false),
     mPostedFlushUserFontSet(false),
+    mEverInForeground(false),
     mCompatMode(eCompatibility_FullStandards),
+    mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
+    mStyleBackendType(mozilla::StyleBackendType::Gecko),
+#ifdef MOZILLA_INTERNAL_API
     mVisibilityState(dom::VisibilityState::Hidden),
+#else
+    mDummy(0),
+#endif
+    mType(eUnknown),
+    mDefaultElementType(0),
+    mAllowXULXBL(eTriUnset),
+#ifdef DEBUG
+    mIsLinkUpdateRegistrationsForbidden(false),
+#endif
     mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
+    mSandboxFlags(0),
     mPartID(0),
+    mMarkedCCGeneration(0),
+    mPresShell(nullptr),
+    mSubtreeModifiedDepth(0),
+    mEventsSuppressed(0),
+    mAnimationsPaused(0),
+    mExternalScriptsBeingEvaluated(0),
+    mFrameRequestCallbackCounter(0),
+    mStaticCloneCount(0),
+    mWindow(nullptr),
+    mBFCacheEntry(nullptr),
+    mInSyncOperationCount(0),
+    mBlockDOMContentLoaded(0),
     mDidFireDOMContentLoaded(true),
     mHasScrollLinkedEffect(false),
+    mUseCounters(0),
+    mChildDocumentUseCounters(0),
+    mNotifiedPageForUseCounter(0),
     mUserHasInteracted(false)
 {
   SetIsInDocument();
 
   PR_INIT_CLIST(&mDOMMediaQueryLists);
 }
 
-// NOTE! nsDocument::operator new() zeroes out all members, so don't
-// bother initializing members to 0.
-
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
+  , mIsTopLevelContentDocument(false)
+  , mIsContentDocument(false)
+  , mSubDocuments(nullptr)
+  , mHeaderData(nullptr)
+  , mIsGoingAway(false)
+  , mInDestructor(false)
+  , mMayHaveTitleElement(false)
+  , mHasWarnedAboutBoxObjects(false)
+  , mDelayFrameLoaderInitialization(false)
+  , mSynchronousDOMContentLoaded(false)
+  , mInXBLUpdate(false)
+  , mInFlush(false)
+  , mParserAborted(false)
+  , mCurrentOrientationAngle(0)
+  , mCurrentOrientationType(OrientationType::Portrait_primary)
+  , mSSApplicableStateNotificationPending(false)
+  , mReportedUseCounters(false)
+  , mStyleSetFilled(false)
+  , mPendingFullscreenRequests(0)
+  , mXMLDeclarationBits(0)
+  , mBoxObjectTable(nullptr)
+  , mUpdateNestLevel(0)
+  , mOnloadBlockCount(0)
+  , mAsyncOnloadBlockCount(0)
+#ifdef DEBUG
+  , mStyledLinksCleared(false)
+#endif
+  , mPreloadPictureDepth(0)
+  , mScrolledToRefAlready(0)
+  , mChangeScrollPosWhenScrollingToRef(0)
   , mViewportType(Unknown)
+  , mValidWidth(false)
+  , mValidHeight(false)
+  , mAutoSize(false)
+  , mAllowZoom(false)
+  , mAllowDoubleTapZoom(false)
+  , mValidScaleFloat(false)
+  , mValidMaxScale(false)
+  , mScaleStrEmpty(false)
+  , mWidthStrEmpty(false)
+  , mStackRefCnt(0)
+  , mNeedsReleaseAfterStackRefCntRelease(false)
+  , mMaybeServiceWorkerControlled(false)
+#ifdef DEBUG
+  , mWillReparent(false)
+#endif
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
 
   if (gDocumentLeakPRLog)
     MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug,
            ("DOCUMENT %p created", this));
 
   // Start out mLastStyleSheetSet as null, per spec
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -4,17 +4,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/. */
 #ifndef nsIDocument_h___
 #define nsIDocument_h___
 
 #include "mozilla/FlushType.h"           // for enum
 #include "nsAutoPtr.h"                   // for member
 #include "nsCOMArray.h"                  // for member
-#include "nsCRT.h"                       // for NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 #include "nsCompatibility.h"             // for member
 #include "nsCOMPtr.h"                    // for member
 #include "nsGkAtoms.h"                   // for static class members
 #include "nsIDocumentObserver.h"         // for typedef (nsUpdateType)
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
 #include "nsIServiceManager.h"
@@ -212,17 +211,16 @@ class nsIDocument : public nsINode,
   typedef mozilla::dom::GlobalObject GlobalObject;
 
 public:
   typedef mozilla::net::ReferrerPolicy ReferrerPolicyEnum;
   typedef mozilla::dom::Element Element;
   typedef mozilla::dom::FullscreenRequest FullscreenRequest;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
 #ifdef MOZILLA_INTERNAL_API
   nsIDocument();
 #endif
 
   // This helper class must be set when we dispatch beforeunload and unload
   // events in order to avoid unterminate sync XHRs.
   class MOZ_RAII PageUnloadingEventTimeStamp
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -40,17 +40,18 @@ class Configuration(DescriptorProvider):
         self.optimizedOutDescriptorNames = set()
         self.generatedEvents = generatedEvents
         self.maxProtoChainLength = 0
         for thing in parseData:
             if isinstance(thing, IDLImplementsStatement):
                 # Our build system doesn't support dep build involving
                 # addition/removal of "implements" statements that appear in a
                 # different .webidl file than their LHS interface.  Make sure we
-                # don't have any of those.
+                # don't have any of those.  See similar block below for partial
+                # interfaces!
                 #
                 # But whitelist a RHS that is LegacyQueryInterface,
                 # since people shouldn't be adding any of those.
                 if (thing.implementor.filename() != thing.filename() and
                     thing.implementee.identifier.name != "LegacyQueryInterface"):
                     raise TypeError(
                         "The binding build system doesn't really support "
                         "'implements' statements which don't appear in the "
@@ -61,16 +62,43 @@ class Configuration(DescriptorProvider):
                         "%s" %
                         (thing.location, thing.implementor.location))
 
             assert not thing.isType()
 
             if not thing.isInterface() and not thing.isNamespace():
                 continue
             iface = thing
+            # Our build system doesn't support dep builds involving
+            # addition/removal of partial interfaces that appear in a different
+            # .webidl file than the interface they are extending.  Make sure we
+            # don't have any of those.  See similar block above for "implements"
+            # statements!
+            if not iface.isExternal():
+                for partialIface in iface.getPartialInterfaces():
+                    if (partialIface.filename() != iface.filename() and
+                        # Unfortunately, NavigatorProperty does exactly the
+                        # thing we're trying to prevent here.  I'm not sure how
+                        # to deal with that, short of effectively requiring a
+                        # clobber when NavigatorProperty is added/removed and
+                        # whitelisting the things it outputs here as
+                        # restrictively as I can.
+                        (partialIface.identifier.name != "Navigator" or
+                         len(partialIface.members) != 1 or
+                         partialIface.members[0].location != partialIface.location or
+                         partialIface.members[0].identifier.location.filename() !=
+                           "<builtin>")):
+                        raise TypeError(
+                            "The binding build system doesn't really support "
+                            "partial interfaces which don't appear in the "
+                            "file in which the interface they are extending is "
+                            "defined.  Don't do this.\n"
+                            "%s\n"
+                            "%s" %
+                            (partialIface.location, iface.location))
             self.interfaces[iface.identifier.name] = iface
             if iface.identifier.name not in config:
                 # Completely skip consequential interfaces with no descriptor
                 # if they have no interface object because chances are we
                 # don't need to do anything interesting with them.
                 if iface.isConsequential() and not iface.hasInterfaceObject():
                     self.optimizedOutDescriptorNames.add(iface.identifier.name)
                     continue
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1475,16 +1475,20 @@ class IDLInterfaceOrNamespace(IDLObjectW
         self.parent = parent
         # Put the new members at the beginning
         self.members = members + self.members
 
     def addPartialInterface(self, partial):
         assert self.identifier.name == partial.identifier.name
         self._partialInterfaces.append(partial)
 
+    def getPartialInterfaces(self):
+        # Don't let people mutate our guts.
+        return list(self._partialInterfaces)
+
     def getJSImplementation(self):
         classId = self.getExtendedAttribute("JSImplementation")
         if not classId:
             return classId
         assert isinstance(classId, list)
         assert len(classId) == 1
         return classId[0]
 
--- a/dom/html/HTMLFormSubmission.cpp
+++ b/dom/html/HTMLFormSubmission.cpp
@@ -277,18 +277,22 @@ HandleMailtoSubject(nsCString& aPath)
                                            nsContentUtils::eFORMS_PROPERTIES,
                                            "DefaultFormSubject",
                                            formatStrings,
                                            subjectStr);
     if (NS_FAILED(rv))
       return;
     aPath.AppendLiteral("subject=");
     nsCString subjectStrEscaped;
-    aPath.Append(NS_EscapeURL(NS_ConvertUTF16toUTF8(subjectStr), esc_Query,
-                              subjectStrEscaped));
+    rv = NS_EscapeURL(NS_ConvertUTF16toUTF8(subjectStr), esc_Query,
+                      subjectStrEscaped, mozilla::fallible);
+    if (NS_FAILED(rv))
+      return;
+
+    aPath.Append(subjectStrEscaped);
   }
 }
 
 nsresult
 FSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
                                    nsIInputStream** aPostDataStream)
 {
   nsresult rv = NS_OK;
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -131,21 +131,31 @@ ImageListener::OnStopRequest(nsIRequest*
   ImageDocument* imgDoc = static_cast<ImageDocument*>(mDocument.get());
   nsContentUtils::DispatchChromeEvent(imgDoc, static_cast<nsIDocument*>(imgDoc),
                                       NS_LITERAL_STRING("ImageContentLoaded"),
                                       true, true);
   return MediaDocumentStreamListener::OnStopRequest(aRequest, aCtxt, aStatus);
 }
 
 ImageDocument::ImageDocument()
-  : MediaDocument(),
-    mOriginalZoomLevel(1.0)
+  : MediaDocument()
+  , mVisibleWidth(0.0)
+  , mVisibleHeight(0.0)
+  , mImageWidth(0)
+  , mImageHeight(0)
+  , mResizeImageByDefault(false)
+  , mClickResizingEnabled(false)
+  , mImageIsOverflowingHorizontally(false)
+  , mImageIsOverflowingVertically(false)
+  , mImageIsResized(false)
+  , mShouldResize(false)
+  , mFirstResize(false)
+  , mObservingImageLoader(false)
+  , mOriginalZoomLevel(1.0)
 {
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
 }
 
 ImageDocument::~ImageDocument()
 {
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ImageDocument, MediaDocument,
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -97,19 +97,16 @@ PluginStreamListener::OnStartRequest(nsI
     return rv;
   }
 
   // Note that because we're now hooked up to a plugin listener, this will
   // likely spawn a plugin, which may re-enter.
   return MediaDocumentStreamListener::OnStartRequest(request, ctxt);
 }
 
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
-
 PluginDocument::PluginDocument()
 {}
 
 PluginDocument::~PluginDocument() = default;
 
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(PluginDocument, MediaDocument,
                                    mPluginContent)
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -116,18 +116,16 @@ class HTMLContentSink;
 class HTMLContentSink : public nsContentSink,
                         public nsIHTMLContentSink
 {
 public:
   friend class SinkContext;
 
   HTMLContentSink();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   nsresult Init(nsIDocument* aDoc, nsIURI* aURI, nsISupports* aContainer,
                 nsIChannel* aChannel);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLContentSink, nsContentSink)
 
   // nsIContentSink
@@ -628,18 +626,22 @@ NS_NewHTMLContentSink(nsIHTMLContentSink
 
   *aResult = it;
   NS_ADDREF(*aResult);
 
   return NS_OK;
 }
 
 HTMLContentSink::HTMLContentSink()
+  : mMaxTextRun(0)
+  , mCurrentContext(nullptr)
+  , mHeadContext(nullptr)
+  , mHaveSeenHead(false)
+  , mNotifiedRootInsertion(false)
 {
-  // Note: operator new zeros our memory
 }
 
 HTMLContentSink::~HTMLContentSink()
 {
   if (mNotificationTimer) {
     mNotificationTimer->Cancel();
   }
 
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -164,25 +164,29 @@ NS_NewHTMLDocument(nsIDocument** aInstan
   }
 
   doc->SetLoadedAsData(aLoadedAsData);
   doc.forget(aInstancePtrResult);
 
   return NS_OK;
 }
 
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
-
 nsHTMLDocument::nsHTMLDocument()
   : nsDocument("text/html")
+  , mNumForms(0)
+  , mWriteLevel(0)
+  , mLoadFlags(0)
+  , mTooDeepWriteRecursion(false)
+  , mDisableDocWrite(false)
+  , mWarnedWidthHeight(false)
+  , mContentEditableCount(0)
+  , mEditingState(EditingState::eOff)
+  , mDisableCookieAccess(false)
+  , mPendingMaybeEditingStateChanged(false)
 {
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
-
   mType = eHTML;
   mDefaultElementType = kNameSpaceID_XHTML;
   mCompatMode = eCompatibility_NavQuirks;
 }
 
 nsHTMLDocument::~nsHTMLDocument()
 {
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3008,24 +3008,25 @@ TabChild::ReinitRendering()
 
   InitAPZState();
 
   nsCOMPtr<nsIDocument> doc(GetDocument());
   doc->NotifyLayerManagerRecreated();
 }
 
 void
-TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier)
+TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier,
+                            uint64_t aDeviceResetSeqNo)
 {
   RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
   ClientLayerManager* clm = lm->AsClientLayerManager();
   MOZ_ASSERT(clm);
 
   mTextureFactoryIdentifier = aNewIdentifier;
-  clm->UpdateTextureFactoryIdentifier(aNewIdentifier);
+  clm->UpdateTextureFactoryIdentifier(aNewIdentifier, aDeviceResetSeqNo);
   FrameLayerBuilder::InvalidateAllLayers(clm);
 }
 
 NS_IMETHODIMP
 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText,
                         const char16_t *aTipDir)
 {
     nsString str(aTipText);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -561,17 +561,18 @@ public:
                     const TimeStamp& aCompositeEnd);
 
   void DidRequestComposite(const TimeStamp& aCompositeReqStart,
                            const TimeStamp& aCompositeReqEnd);
 
   void ClearCachedResources();
   void InvalidateLayers();
   void ReinitRendering();
-  void CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier);
+  void CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier,
+                         uint64_t aDeviceResetSeqNo);
 
   static inline TabChild* GetFrom(nsIDOMWindow* aWindow)
   {
     nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);
     return GetFrom(docShell);
   }
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -97,16 +97,17 @@
 #include "UnitTransforms.h"
 #include <algorithm>
 #include "mozilla/WebBrowserPersistDocumentParent.h"
 #include "nsIGroupedSHistory.h"
 #include "PartialSHistory.h"
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
 #include "mozilla/a11y/AccessibleWrap.h"
+#include "mozilla/a11y/nsWinUtils.h"
 #endif
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
 using namespace mozilla::widget;
@@ -264,16 +265,26 @@ TabParent::SetOwnerElement(Element* aEle
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   if (!mIsDestroyed) {
     uintptr_t newWindowHandle = 0;
     if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
       newWindowHandle =
         reinterpret_cast<uintptr_t>(widget->GetNativeData(NS_NATIVE_WINDOW));
     }
     Unused << SendUpdateNativeWindowHandle(newWindowHandle);
+    a11y::DocAccessibleParent* doc = GetTopLevelDocAccessible();
+    if (doc) {
+      HWND hWnd = reinterpret_cast<HWND>(doc->GetEmulatedWindowHandle());
+      if (hWnd) {
+        HWND parentHwnd = reinterpret_cast<HWND>(newWindowHandle);
+        if (parentHwnd != ::GetParent(hWnd)) {
+          ::SetParent(hWnd, parentHwnd);
+        }
+      }
+    }
   }
 #endif
 
   AddWindowListeners();
   TryCacheDPIAndScale();
 }
 
 void
@@ -916,16 +927,19 @@ TabParent::RecvPDocAccessibleConstructor
     }
 
     auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
     mozilla::ipc::IPCResult added = parentDoc->AddChildDoc(doc, aParentID);
 #ifdef XP_WIN
     MOZ_ASSERT(aDocCOMProxy.IsNull());
     if (added) {
       a11y::WrapperFor(doc)->SetID(aMsaaID);
+      if (a11y::nsWinUtils::IsWindowEmulationStarted()) {
+        doc->SetEmulatedWindowHandle(parentDoc->GetEmulatedWindowHandle());
+      }
     }
 #endif
     if (!added) {
       return added;
     }
     return IPC_OK();
   } else {
     // null aParentDoc means this document is at the top level in the child
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -1140,18 +1140,22 @@ nsJSProtocolHandler::EnsureUTF8Spec(cons
   if (!mTextToSubURI) {
     mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   nsAutoString uStr;
   rv = mTextToSubURI->UnEscapeNonAsciiURI(nsDependentCString(aCharset), aSpec, uStr);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (!IsASCII(uStr))
-    NS_EscapeURL(NS_ConvertUTF16toUTF8(uStr), esc_AlwaysCopy | esc_OnlyNonASCII, aUTF8Spec);
+  if (!IsASCII(uStr)) {
+    rv = NS_EscapeURL(NS_ConvertUTF16toUTF8(uStr),
+                      esc_AlwaysCopy | esc_OnlyNonASCII, aUTF8Spec,
+                      mozilla::fallible);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIProtocolHandler methods:
 
 NS_IMETHODIMP
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -260,18 +260,20 @@ bool ReadSectionHeader(nsPluginManifestL
 }
 
 static bool UnloadPluginsASAP()
 {
   return (Preferences::GetUint(kPrefUnloadPluginTimeoutSecs, kDefaultPluginUnloadingTimeout) == 0);
 }
 
 nsPluginHost::nsPluginHost()
-  // No need to initialize members to nullptr, false etc because this class
-  // has a zeroing operator new.
+  : mPluginsLoaded(false)
+  , mOverrideInternalTypes(false)
+  , mPluginsDisabled(false)
+  , mPluginEpoch(0)
 {
   // Bump the pluginchanged epoch on startup. This insures content gets a
   // good plugin list the first time it requests it. Normally we'd just
   // init this to 1, but due to the unique nature of our ctor we need to do
   // this manually.
   if (XRE_IsParentProcess()) {
     IncrementChromeEpoch();
   } else {
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -80,18 +80,16 @@ class nsPluginHost final : public nsIPlu
   friend class nsFakePluginTag;
   virtual ~nsPluginHost();
 
 public:
   nsPluginHost();
 
   static already_AddRefed<nsPluginHost> GetInst();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGINHOST
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
 
   nsresult LoadPlugins();
   nsresult UnloadPlugins();
 
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -3391,21 +3391,23 @@ QuotaManager::GetQuotaObject(Persistence
     rv = aFile->GetFileSize(&fileSize);
     NS_ENSURE_SUCCESS(rv, nullptr);
   }
   else {
     fileSize = 0;
   }
 
   // Re-escape our parameters above to make sure we get the right quota group.
-  nsAutoCString tempStorage1;
-  const nsCSubstring& group = NS_EscapeURL(aGroup, esc_Query, tempStorage1);
-
-  nsAutoCString tempStorage2;
-  const nsCSubstring& origin = NS_EscapeURL(aOrigin, esc_Query, tempStorage2);
+  nsAutoCString group;
+  rv = NS_EscapeURL(aGroup, esc_Query, group, fallible);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  nsAutoCString origin;
+  rv = NS_EscapeURL(aOrigin, esc_Query, origin, fallible);
+  NS_ENSURE_SUCCESS(rv, nullptr);
 
   RefPtr<QuotaObject> result;
   {
     MutexAutoLock lock(mQuotaMutex);
 
     GroupInfoPair* pair;
     if (!mGroupInfoPairs.Get(group, &pair)) {
       return nullptr;
--- a/dom/storage/StorageObserver.cpp
+++ b/dom/storage/StorageObserver.cpp
@@ -259,19 +259,21 @@ StorageObserver::Observe(nsISupports* aS
     nsAutoCString aceDomain;
     nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
     if (converter) {
       rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
       // In case the IDN service is not available, this is the best we can come
       // up with!
-      NS_EscapeURL(NS_ConvertUTF16toUTF8(aData),
-                   esc_OnlyNonASCII | esc_AlwaysCopy,
-                   aceDomain);
+      rv = NS_EscapeURL(NS_ConvertUTF16toUTF8(aData),
+                        esc_OnlyNonASCII | esc_AlwaysCopy,
+                        aceDomain,
+                        fallible);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsAutoCString originScope;
     rv = CreateReversedDomain(aceDomain, originScope);
     NS_ENSURE_SUCCESS(rv, rv);
 
     StorageDBBridge* db = StorageCache::StartDatabase();
     NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -2541,18 +2541,18 @@ nsWebBrowserPersist::URIData::GetLocalUR
             }
             
             nsAutoCString filename;
             url->GetFileName(filename);
             
             nsAutoCString rawPathURL(mRelativePathToData);
             rawPathURL.Append(filename);
             
-            nsAutoCString buf;
-            aSpecOut = NS_EscapeURL(rawPathURL, esc_FilePath, buf);
+            rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
+            NS_ENSURE_SUCCESS(rv, rv);
         } else {
             nsAutoCString rawPathURL;
             
             nsCOMPtr<nsIFile> dataFile;
             rv = GetLocalFileFromURI(mFile, getter_AddRefs(dataFile));
             NS_ENSURE_SUCCESS(rv, rv);
             
             nsCOMPtr<nsIFile> docFile;
@@ -2561,18 +2561,18 @@ nsWebBrowserPersist::URIData::GetLocalUR
             
             nsCOMPtr<nsIFile> parentDir;
             rv = docFile->GetParent(getter_AddRefs(parentDir));
             NS_ENSURE_SUCCESS(rv, rv);
             
             rv = dataFile->GetRelativePath(parentDir, rawPathURL);
             NS_ENSURE_SUCCESS(rv, rv);
             
-            nsAutoCString buf;
-            aSpecOut = NS_EscapeURL(rawPathURL, esc_FilePath, buf);
+            rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
+            NS_ENSURE_SUCCESS(rv, rv);
         }
     } else {
         fileAsURI->GetSpec(aSpecOut);
     }
     if (mIsSubFrame) {
         AppendUTF16toUTF8(mSubFrameExt, aSpecOut);
     }
 
--- a/dom/webidl/BrowserElement.webidl
+++ b/dom/webidl/BrowserElement.webidl
@@ -166,8 +166,56 @@ interface BrowserElementPrivileged {
                            optional BrowserElementExecuteScriptOptions options);
 
   [Throws,
    Pref="dom.mozBrowserFramesEnabled",
    ChromeOnly]
   DOMRequest getWebManifest();
 
 };
+
+// Bits needed for BrowserElementAudioChannel.
+partial interface BrowserElementPrivileged {
+  [Pure, Cached, Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  readonly attribute sequence<BrowserElementAudioChannel> allowedAudioChannels;
+
+  /**
+   * Mutes all audio in this browser.
+   */
+  [Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  void mute();
+
+  /**
+   * Unmutes all audio in this browser.
+   */
+  [Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  void unmute();
+
+  /**
+   * Obtains whether or not the browser is muted.
+   */
+  [Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  DOMRequest getMuted();
+
+  /**
+   * Sets the volume for the browser.
+   */
+  [Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  void setVolume(float volume);
+
+  /**
+   * Gets the volume for the browser.
+   */
+  [Throws,
+   Pref="dom.mozBrowserFramesEnabled",
+   ChromeOnly]
+  DOMRequest getVolume();
+};
--- a/dom/webidl/BrowserElementAudioChannel.webidl
+++ b/dom/webidl/BrowserElementAudioChannel.webidl
@@ -23,55 +23,8 @@ interface BrowserElementAudioChannel : E
   DOMRequest getMuted();
 
   [Throws]
   DOMRequest setMuted(boolean aMuted);
 
   [Throws]
   DOMRequest isActive();
 };
-
-partial interface BrowserElementPrivileged {
-  [Pure, Cached, Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  readonly attribute sequence<BrowserElementAudioChannel> allowedAudioChannels;
-
-  /**
-   * Mutes all audio in this browser.
-   */
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  void mute();
-
-  /**
-   * Unmutes all audio in this browser.
-   */
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  void unmute();
-
-  /**
-   * Obtains whether or not the browser is muted.
-   */
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  DOMRequest getMuted();
-
-  /**
-   * Sets the volume for the browser.
-   */
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  void setVolume(float volume);
-
-  /**
-   * Gets the volume for the browser.
-   */
-  [Throws,
-   Pref="dom.mozBrowserFramesEnabled",
-   ChromeOnly]
-  DOMRequest getVolume();
-};
--- a/dom/webidl/Notification.webidl
+++ b/dom/webidl/Notification.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.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 origin of this IDL file is
- * http://notifications.spec.whatwg.org/
+ * https://notifications.spec.whatwg.org/
  *
  * Copyright:
  * To the extent possible under law, the editors have waived all copyright and
  * related or neighboring rights to this work.
  */
 
 [Constructor(DOMString title, optional NotificationOptions options),
  Exposed=(Window,Worker),
@@ -91,15 +91,8 @@ enum NotificationPermission {
 
 callback NotificationPermissionCallback = void (NotificationPermission permission);
 
 enum NotificationDirection {
   "auto",
   "ltr",
   "rtl"
 };
-
-partial interface ServiceWorkerRegistration {
-  [Throws, Func="mozilla::dom::ServiceWorkerRegistration::NotificationAPIVisible"]
-  Promise<void> showNotification(DOMString title, optional NotificationOptions options);
-  [Throws, Func="mozilla::dom::ServiceWorkerRegistration::NotificationAPIVisible"]
-  Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter);
-};
--- a/dom/webidl/NotificationEvent.webidl
+++ b/dom/webidl/NotificationEvent.webidl
@@ -15,13 +15,8 @@
  Exposed=ServiceWorker,Func="mozilla::dom::Notification::PrefEnabled"]
 interface NotificationEvent : ExtendableEvent {
   readonly attribute Notification notification;
 };
 
 dictionary NotificationEventInit : ExtendableEventInit {
   required Notification notification;
 };
-
-partial interface ServiceWorkerGlobalScope {
-  attribute EventHandler onnotificationclick;
-  attribute EventHandler onnotificationclose;
-};
--- a/dom/webidl/ServiceWorkerGlobalScope.webidl
+++ b/dom/webidl/ServiceWorkerGlobalScope.webidl
@@ -1,15 +1,17 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.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 origin of this IDL file is
  * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
+ * http://w3c.github.io/push-api/
+ * https://notifications.spec.whatwg.org/
  *
  * You are granted a license to use, reproduce and create derivative works of
  * this document.
  */
 
 [Global=(Worker,ServiceWorker),
  Exposed=ServiceWorker]
 interface ServiceWorkerGlobalScope : WorkerGlobalScope {
@@ -29,8 +31,13 @@ interface ServiceWorkerGlobalScope : Wor
 };
 
 // These are from w3c.github.io/push-api/
 partial interface ServiceWorkerGlobalScope {
   attribute EventHandler onpush;
   attribute EventHandler onpushsubscriptionchange;
 };
 
+// https://notifications.spec.whatwg.org/
+partial interface ServiceWorkerGlobalScope {
+  attribute EventHandler onnotificationclick;
+  attribute EventHandler onnotificationclose;
+};
--- a/dom/webidl/ServiceWorkerRegistration.webidl
+++ b/dom/webidl/ServiceWorkerRegistration.webidl
@@ -1,16 +1,17 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.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 origin of this IDL file is
  * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
- *
+ * https://w3c.github.io/push-api/
+ * https://notifications.spec.whatwg.org/
  */
 
 [Func="mozilla::dom::ServiceWorkerRegistration::Visible",
  Exposed=(Window,Worker)]
 interface ServiceWorkerRegistration : EventTarget {
   [Unforgeable] readonly attribute ServiceWorker? installing;
   [Unforgeable] readonly attribute ServiceWorker? waiting;
   [Unforgeable] readonly attribute ServiceWorker? active;
@@ -22,12 +23,21 @@ interface ServiceWorkerRegistration : Ev
 
   [Throws, NewObject]
   Promise<boolean> unregister();
 
   // event
   attribute EventHandler onupdatefound;
 };
 
+// https://w3c.github.io/push-api/
 partial interface ServiceWorkerRegistration {
   [Throws, Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
   readonly attribute PushManager pushManager;
 };
+
+// https://notifications.spec.whatwg.org/
+partial interface ServiceWorkerRegistration {
+  [Throws, Func="mozilla::dom::ServiceWorkerRegistration::NotificationAPIVisible"]
+  Promise<void> showNotification(DOMString title, optional NotificationOptions options);
+  [Throws, Func="mozilla::dom::ServiceWorkerRegistration::NotificationAPIVisible"]
+  Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter);
+};
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -296,16 +296,17 @@ LoadContextOptions(const char* aPrefName
     return;
   }
 #endif
 
   // Context options.
   JS::ContextOptions contextOptions;
   contextOptions.setAsmJS(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs")))
                 .setWasm(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm")))
+                .setWasmAlwaysBaseline(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_baselinejit")))
                 .setThrowOnAsmJSValidationFailure(GetWorkerPref<bool>(
                       NS_LITERAL_CSTRING("throw_on_asmjs_validation_failure")))
                 .setBaseline(GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit")))
                 .setIon(GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion")))
                 .setNativeRegExp(GetWorkerPref<bool>(NS_LITERAL_CSTRING("native_regexp")))
                 .setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack")))
                 .setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror")))
                 .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")));
@@ -1465,23 +1466,35 @@ bool
 IsCurrentThreadRunningChromeWorker()
 {
   return GetCurrentThreadWorkerPrivate()->UsesSystemPrincipal();
 }
 
 JSContext*
 GetCurrentThreadJSContext()
 {
-  return GetCurrentThreadWorkerPrivate()->GetJSContext();
+  WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
+  if (!wp) {
+    return nullptr;
+  }
+  return wp->GetJSContext();
 }
 
 JSObject*
 GetCurrentThreadWorkerGlobal()
 {
-  return GetCurrentThreadWorkerPrivate()->GlobalScope()->GetGlobalJSObject();
+  WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
+  if (!wp) {
+    return nullptr;
+  }
+  WorkerGlobalScope* scope = wp->GlobalScope();
+  if (!scope) {
+    return nullptr;
+  }
+  return scope->GetGlobalJSObject();
 }
 
 END_WORKERS_NAMESPACE
 
 struct RuntimeService::IdleThreadInfo
 {
   RefPtr<WorkerThread> mThread;
   mozilla::TimeStamp mExpirationTime;
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -620,16 +620,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsresult
   OpenWindow(nsPIDOMWindowOuter** aWindow)
   {
+    MOZ_DIAGNOSTIC_ASSERT(aWindow);
     WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
 
     // [[1. Let url be the result of parsing url with entry settings object's API
     //   base URL.]]
     nsCOMPtr<nsIURI> uri;
     WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
 
     nsCOMPtr<nsIURI> baseURI;
@@ -656,34 +657,41 @@ private:
         do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
       NS_ENSURE_STATE(pwwatch);
 
       nsCString spec;
-      uri->GetSpec(spec);
+      rv = uri->GetSpec(spec);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       nsCOMPtr<mozIDOMWindowProxy> newWindow;
-      pwwatch->OpenWindow2(nullptr,
-                           spec.get(),
-                           nullptr,
-                           nullptr,
-                           false, false, true, nullptr,
-                           // Not a spammy popup; we got permission, we swear!
-                           /* aIsPopupSpam = */ false,
-                           // Don't force noopener.  We're not passing in an
-                           // opener anyway, and we _do_ want the returned
-                           // window.
-                           /* aForceNoOpener = */ false,
-                           /* aLoadInfp = */ nullptr,
-                           getter_AddRefs(newWindow));
+      rv = pwwatch->OpenWindow2(nullptr,
+                                spec.get(),
+                                nullptr,
+                                nullptr,
+                                false, false, true, nullptr,
+                                // Not a spammy popup; we got permission, we swear!
+                                /* aIsPopupSpam = */ false,
+                                // Don't force noopener.  We're not passing in an
+                                // opener anyway, and we _do_ want the returned
+                                // window.
+                                /* aForceNoOpener = */ false,
+                                /* aLoadInfp = */ nullptr,
+                                getter_AddRefs(newWindow));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
       pwindow.forget(aWindow);
+      MOZ_DIAGNOSTIC_ASSERT(*aWindow);
       return NS_OK;
     }
 
     // Find the most recent browser window and open a new tab in it.
     nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
       nsContentUtils::GetMostRecentNonPBWindow();
     if (!browserWindow) {
       // It is possible to be running without a browser window on Mac OS, so
@@ -711,16 +719,17 @@ private:
                        getter_AddRefs(win));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     NS_ENSURE_STATE(win);
 
     nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
     pWin.forget(aWindow);
+    MOZ_DIAGNOSTIC_ASSERT(*aWindow);
 
     return NS_OK;
   }
 };
 
 } // namespace
 
 already_AddRefed<Promise>
--- a/dom/xbl/nsXBLContentSink.h
+++ b/dom/xbl/nsXBLContentSink.h
@@ -55,18 +55,16 @@ class nsXBLPrototypeBinding;
 // builds its own lightweight data structures for the <resources>,
 // <handlers>, <implementation>, and 
 
 class nsXBLContentSink : public nsXMLContentSink {
 public:
   nsXBLContentSink();
   ~nsXBLContentSink();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   nsresult Init(nsIDocument* aDoc,
                 nsIURI* aURL,
                 nsISupports* aContainer);
 
   // nsIContentSink overrides
   NS_IMETHOD HandleStartElement(const char16_t *aName, 
                                 const char16_t **aAtts, 
                                 uint32_t aAttsCount, 
--- a/dom/xml/XMLDocument.cpp
+++ b/dom/xml/XMLDocument.cpp
@@ -224,21 +224,23 @@ NS_NewXBLDocument(nsIDOMDocument** aInst
   return NS_OK;
 }
 
 namespace mozilla {
 namespace dom {
 
 XMLDocument::XMLDocument(const char* aContentType)
   : nsDocument(aContentType),
-    mAsync(true)
+    mChannelIsPending(false),
+    mAsync(true),
+    mLoopingForSyncLoad(false),
+    mIsPlainDocument(false),
+    mSuppressParserErrorElement(false),
+    mSuppressParserErrorConsoleMessages(false)
 {
-  // NOTE! nsDocument::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
-
   mType = eGenericXML;
 }
 
 XMLDocument::~XMLDocument()
 {
   // XXX We rather crash than hang
   mLoopingForSyncLoad = false;
 }
--- a/dom/xml/nsXMLFragmentContentSink.cpp
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -32,18 +32,16 @@
 using namespace mozilla::dom;
 
 class nsXMLFragmentContentSink : public nsXMLContentSink,
                                  public nsIFragmentContentSink
 {
 public:
   nsXMLFragmentContentSink();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLFragmentContentSink,
                                                      nsXMLContentSink)
 
   // nsIExpatSink
   NS_IMETHOD HandleDoctypeDecl(const nsAString& aSubset,
                                const nsAString& aName,
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -185,23 +185,36 @@ nsRefMapEntry::RemoveElement(Element* aE
 // ctors & dtors
 //
 
 namespace mozilla {
 namespace dom {
 
 XULDocument::XULDocument(void)
     : XMLDocument("application/vnd.mozilla.xul+xml"),
+      mNextSrcLoadWaiter(nullptr),
+      mApplyingPersistedAttrs(false),
+      mIsWritingFastLoad(false),
+      mDocumentLoaded(false),
+      mStillWalking(false),
+      mRestrictPersistence(false),
+      mTemplateBuilderTable(nullptr),
+      mPendingSheets(0),
       mDocLWTheme(Doc_Theme_Uninitialized),
       mState(eState_Master),
-      mResolutionPhase(nsForwardReference::eStart)
+      mCurrentScriptProto(nullptr),
+      mOffThreadCompiling(false),
+      mOffThreadCompileStringBuf(nullptr),
+      mOffThreadCompileStringLength(0),
+      mResolutionPhase(nsForwardReference::eStart),
+      mBroadcasterMap(nullptr),
+      mInitialLayoutComplete(false),
+      mHandlingDelayedAttrChange(false),
+      mHandlingDelayedBroadcasters(false)
 {
-    // NOTE! nsDocument::operator new() zeroes out all members, so don't
-    // bother initializing members to 0.
-
     // Override the default in nsDocument
     mCharacterSet.AssignLiteral("UTF-8");
 
     mDefaultElementType = kNameSpaceID_XUL;
     mType = eXUL;
 
     mDelayFrameLoaderInitialization = true;
 
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -95,21 +95,25 @@ ClientLayerManager::ClientLayerManager(n
   , mLastPaintTime(TimeDuration::Forever())
   , mTargetRotation(ROTATION_0)
   , mRepeatTransaction(false)
   , mIsRepeatTransaction(false)
   , mTransactionIncomplete(false)
   , mCompositorMightResample(false)
   , mNeedsComposite(false)
   , mPaintSequenceNumber(0)
+  , mDeviceResetSequenceNumber(0)
   , mForwarder(new ShadowLayerForwarder(this))
-  , mDeviceCounter(gfxPlatform::GetPlatform()->GetDeviceCounter())
 {
   MOZ_COUNT_CTOR(ClientLayerManager);
   mMemoryPressureObserver = new MemoryPressureObserver(this);
+
+  if (XRE_IsContentProcess()) {
+    mDeviceResetSequenceNumber = CompositorBridgeChild::Get()->DeviceResetSequenceNumber();
+  }
 }
 
 
 ClientLayerManager::~ClientLayerManager()
 {
   mMemoryPressureObserver->Destroy();
   ClearCachedResources();
   // Stop receiveing AsyncParentMessage at Forwarder.
@@ -201,32 +205,44 @@ bool
 ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
 {
   MOZ_ASSERT(mForwarder, "ClientLayerManager::BeginTransaction without forwarder");
   if (!mForwarder->IPCOpen()) {
     gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel down. GPU process may have died.";
     return false;
   }
 
+  if (XRE_IsContentProcess() &&
+      mForwarder->DeviceCanReset() &&
+      mDeviceResetSequenceNumber != CompositorBridgeChild::Get()->DeviceResetSequenceNumber())
+  {
+    // The compositor has informed this process that a device reset occurred,
+    // but it has not finished informing each TabChild of its new
+    // TextureFactoryIdentifier. Until then, it's illegal to paint. Note that
+    // it is also illegal to request a new TIF synchronously, because we're
+    // not guaranteed the UI process has finished acquiring new compositors
+    // for each widget.
+    //
+    // Note that we only do this for accelerated backends, since we do not
+    // perform resets on basic compositors.
+    gfxCriticalNote << "Discarding a paint since a device reset has not yet been acknowledged.";
+    return false;
+  }
+
   mInTransaction = true;
   mTransactionStart = TimeStamp::Now();
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
   Log();
 #endif
 
   NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
   mPhase = PHASE_CONSTRUCTION;
 
-  if (DependsOnStaleDevice()) {
-    FrameLayerBuilder::InvalidateAllLayers(this);
-    mDeviceCounter = gfxPlatform::GetPlatform()->GetDeviceCounter();
-  }
-
   MOZ_ASSERT(mKeepAlive.IsEmpty(), "uncommitted txn?");
 
   // If the last transaction was incomplete (a failed DoEmptyTransaction),
   // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
   // to the previous transaction.
   dom::ScreenOrientationInternal orientation;
   if (dom::TabChild* window = mWidget->GetOwningTabChild()) {
     orientation = window->GetOrientation();
@@ -609,19 +625,24 @@ ClientLayerManager::FlushRendering()
   if (mWidget) {
     if (CompositorBridgeChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
       remoteRenderer->SendFlushRendering();
     }
   }
 }
 
 void
-ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier)
+ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
+                                                   uint64_t aDeviceResetSeqNo)
 {
+  MOZ_ASSERT_IF(XRE_IsContentProcess(),
+                aDeviceResetSeqNo == CompositorBridgeChild::Get()->DeviceResetSequenceNumber());
+
   mForwarder->IdentifyTextureHost(aNewIdentifier);
+  mDeviceResetSequenceNumber = aDeviceResetSeqNo;
 }
 
 void
 ClientLayerManager::SendInvalidRegion(const nsIntRegion& aRegion)
 {
   if (mWidget) {
     if (CompositorBridgeChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
       remoteRenderer->SendNotifyRegionInvalidated(aRegion);
@@ -845,23 +866,16 @@ ClientLayerManager::AddDidCompositeObser
 }
 
 void
 ClientLayerManager::RemoveDidCompositeObserver(DidCompositeObserver* aObserver)
 {
   mDidCompositeObservers.RemoveElement(aObserver);
 }
 
-bool
-ClientLayerManager::DependsOnStaleDevice() const
-{
-  return gfxPlatform::GetPlatform()->GetDeviceCounter() != mDeviceCounter;
-}
-
-
 already_AddRefed<PersistentBufferProvider>
 ClientLayerManager::CreatePersistentBufferProvider(const gfx::IntSize& aSize,
                                                    gfx::SurfaceFormat aFormat)
 {
   // Don't use a shared buffer provider if compositing is considered "not cheap"
   // because the canvas will most likely be flattened into a thebes layer instead
   // of being sent to the compositor, in which case rendering into shared memory
   // is wasteful.
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -86,17 +86,18 @@ public:
   virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
   virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() override;
   virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
   virtual already_AddRefed<TextLayer> CreateTextLayer() override;
   virtual already_AddRefed<BorderLayer> CreateBorderLayer() override;
   virtual already_AddRefed<RefLayer> CreateRefLayer() override;
 
-  void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier);
+  void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
+                                      uint64_t aDeviceResetSeqNo);
   TextureFactoryIdentifier GetTextureFactoryIdentifier()
   {
     return AsShadowForwarder()->GetTextureFactoryIdentifier();
   }
 
   virtual void FlushRendering() override;
   void SendInvalidRegion(const nsIntRegion& aRegion);
 
@@ -281,18 +282,16 @@ private:
   void ClearLayer(Layer* aLayer);
 
   void HandleMemoryPressureLayer(Layer* aLayer);
 
   bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags);
 
-  bool DependsOnStaleDevice() const;
-
   LayerRefArray mKeepAlive;
 
   nsIWidget* mWidget;
 
   /* PaintedLayer callbacks; valid at the end of a transaciton,
    * while rendering */
   DrawPaintedLayerCallback mPaintedLayerCallback;
   void *mPaintedLayerCallbackData;
@@ -324,16 +323,20 @@ private:
   bool mTransactionIncomplete;
   bool mCompositorMightResample;
   bool mNeedsComposite;
 
   // An incrementing sequence number for paints.
   // Incremented in BeginTransaction(), but not for repeat transactions.
   uint32_t mPaintSequenceNumber;
 
+  // A sequence number for checking whether we have not yet acknowledged
+  // a device reset.
+  uint64_t mDeviceResetSequenceNumber;
+
   APZTestData mApzTestData;
 
   RefPtr<ShadowLayerForwarder> mForwarder;
   AutoTArray<dom::OverfillCallback*,0> mOverfillCallbacks;
   mozilla::TimeStamp mTransactionStart;
 
   nsTArray<DidCompositeObserver*> mDidCompositeObservers;
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -73,16 +73,17 @@ static void ShmemAllocated(CompositorBri
 static StaticRefPtr<CompositorBridgeChild> sCompositorBridge;
 
 Atomic<int32_t> KnowsCompositor::sSerialCounter(0);
 
 CompositorBridgeChild::CompositorBridgeChild(LayerManager *aLayerManager)
   : mLayerManager(aLayerManager)
   , mCanSend(false)
   , mFwdTransactionId(0)
+  , mDeviceResetSequenceNumber(0)
   , mMessageLoop(MessageLoop::current())
   , mSectionAllocator(nullptr)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 CompositorBridgeChild::~CompositorBridgeChild()
 {
@@ -360,36 +361,35 @@ CompositorBridgeChild::RecvCompositorUpd
                                              const uint64_t& aSeqNo)
 {
   if (mLayerManager) {
     // This case is handled directly by nsBaseWidget.
     MOZ_ASSERT(aLayersId == 0);
   } else if (aLayersId != 0) {
     // Update gfxPlatform if this is the first time we're seeing this compositor
     // update (we will get an update for each connected tab).
-    static uint64_t sLastSeqNo = 0;
-    if (sLastSeqNo != aSeqNo) {
+    if (mDeviceResetSequenceNumber != aSeqNo) {
       gfxPlatform::GetPlatform()->CompositorUpdated();
-      sLastSeqNo = aSeqNo;
+      mDeviceResetSequenceNumber = aSeqNo;
 
       // If we still get device reset here, something must wrong when creating
       // d3d11 devices.
       if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
         gfxCriticalError() << "Unexpected reset device processing when \
                                updating compositor.";
       }
     }
 
     if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) {
-      child->CompositorUpdated(aNewIdentifier);
+      child->CompositorUpdated(aNewIdentifier, aSeqNo);
     }
     if (!mCanSend) {
       return IPC_OK();
     }
-    SendAcknowledgeCompositorUpdate(aLayersId);
+    SendAcknowledgeCompositorUpdate(aLayersId, aSeqNo);
   }
   return IPC_OK();
 }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
 static void CalculatePluginClip(const LayoutDeviceIntRect& aBounds,
                                 const nsTArray<LayoutDeviceIntRect>& aPluginClipRects,
                                 const LayoutDeviceIntPoint& aContentOffset,
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -104,17 +104,17 @@ public:
                    const TimeStamp& aCompositeEnd) override;
 
   virtual mozilla::ipc::IPCResult
   RecvInvalidateLayers(const uint64_t& aLayersId) override;
 
   virtual mozilla::ipc::IPCResult
   RecvCompositorUpdated(const uint64_t& aLayersId,
                         const TextureFactoryIdentifier& aNewIdentifier,
-                        const uint64_t& aSeqNo) override;
+                        const uint64_t& aSequenceNumber) override;
 
   virtual mozilla::ipc::IPCResult
   RecvOverfill(const uint32_t &aOverfill) override;
 
   virtual mozilla::ipc::IPCResult
   RecvUpdatePluginConfigurations(const LayoutDeviceIntPoint& aContentOffset,
                                  const LayoutDeviceIntRegion& aVisibleRegion,
                                  nsTArray<PluginWindowData>&& aPlugins) override;
@@ -226,16 +226,20 @@ public:
 
   PAPZChild* AllocPAPZChild(const uint64_t& aLayersId) override;
   bool DeallocPAPZChild(PAPZChild* aActor) override;
 
   void ProcessingError(Result aCode, const char* aReason) override;
 
   void WillEndTransaction();
 
+  uint64_t DeviceResetSequenceNumber() const {
+    return mDeviceResetSequenceNumber;
+  }
+
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CompositorBridgeChild();
 
   void InitIPDL();
   void DeallocPCompositorBridgeChild() override;
 
   virtual PLayerTransactionChild*
@@ -312,16 +316,21 @@ private:
 
   /**
    * Transaction id of ShadowLayerForwarder.
    * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
    */
   uint64_t mFwdTransactionId;
 
   /**
+   * Last sequence number recognized for a device reset.
+   */
+  uint64_t mDeviceResetSequenceNumber;
+
+  /**
    * Hold TextureClients refs until end of their usages on host side.
    * It defer calling of TextureClient recycle callback.
    */
   nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
 
   MessageLoop* mMessageLoop;
 
   AutoTArray<RefPtr<TextureClientPool>,2> mTexturePools;
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -177,17 +177,16 @@ CompositorBridgeParentBase::StopSharingM
 
 CompositorBridgeParent::LayerTreeState::LayerTreeState()
   : mApzcTreeManagerParent(nullptr)
   , mParent(nullptr)
   , mLayerManager(nullptr)
   , mCrossProcessParent(nullptr)
   , mLayerTree(nullptr)
   , mUpdatedPluginDataAvailable(false)
-  , mPendingCompositorUpdates(0)
 {
 }
 
 CompositorBridgeParent::LayerTreeState::~LayerTreeState()
 {
   if (mController) {
     mController->Destroy();
   }
@@ -1819,19 +1818,19 @@ CompositorBridgeParent::ResetCompositorT
   }
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, uint64_t layersId) -> void {
     if (CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent) {
       Unused << cpcp->SendCompositorUpdated(layersId, newIdentifier.value(), aSeqNo);
 
       if (LayerTransactionParent* ltp = lts->mLayerTree) {
-        ltp->AddPendingCompositorUpdate();
+        ltp->SetPendingCompositorUpdate(aSeqNo);
       }
-      lts->mPendingCompositorUpdates++;
+      lts->mPendingCompositorUpdate = Some(aSeqNo);
     }
   });
 }
 
 Maybe<TextureFactoryIdentifier>
 CompositorBridgeParent::ResetCompositorImpl(const nsTArray<LayersBackend>& aBackendHints)
 {
   if (!mLayerManager) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -184,17 +184,17 @@ public:
   virtual mozilla::ipc::IPCResult RecvNotifyChildCreated(const uint64_t& child) override;
   virtual mozilla::ipc::IPCResult RecvNotifyChildRecreated(const uint64_t& child) override;
   virtual mozilla::ipc::IPCResult RecvAdoptChild(const uint64_t& child) override;
   virtual mozilla::ipc::IPCResult RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                 const gfx::IntRect& aRect) override;
   virtual mozilla::ipc::IPCResult RecvFlushRendering() override;
   virtual mozilla::ipc::IPCResult RecvForcePresent() override;
 
-  virtual mozilla::ipc::IPCResult RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId) override {
+  virtual mozilla::ipc::IPCResult RecvAcknowledgeCompositorUpdate(const uint64_t&, const uint64_t&) override {
     MOZ_ASSERT_UNREACHABLE("This message is only sent cross-process");
     return IPC_OK();
   }
 
   virtual mozilla::ipc::IPCResult RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override;
   virtual mozilla::ipc::IPCResult RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override;
   virtual mozilla::ipc::IPCResult RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) override;
 
@@ -352,19 +352,21 @@ public:
     // the PCompositorBridgeChild
     CrossProcessCompositorBridgeParent* mCrossProcessParent;
     TargetConfig mTargetConfig;
     APZTestData mApzTestData;
     LayerTransactionParent* mLayerTree;
     nsTArray<PluginWindowData> mPluginData;
     bool mUpdatedPluginDataAvailable;
 
-    // Number of times the compositor has been reset without having been
-    // acknowledged by the child.
-    uint32_t mPendingCompositorUpdates;
+    // Most recent device reset sequence number that has not been acknowledged;
+    // this is needed in case a device reset occurs in between allocating a
+    // RefLayer id on the parent, and allocating a PLayerTransaction on the
+    // child.
+    Maybe<uint64_t> mPendingCompositorUpdate;
 
     CompositorController* GetCompositorController() const;
     MetricsSharingController* CrossProcessSharingController() const;
     MetricsSharingController* InProcessSharingController() const;
   };
 
   /**
    * Lookup the indirect shadow tree for |aId| and return it if it
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -82,17 +82,19 @@ CrossProcessCompositorBridgeParent::Allo
   if (state && state->mLayerManager) {
     state->mCrossProcessParent = this;
     HostLayerManager* lm = state->mLayerManager;
     *aTextureFactoryIdentifier = lm->GetCompositor()->GetTextureFactoryIdentifier();
     *aSuccess = true;
     LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId);
     p->AddIPDLReference();
     sIndirectLayerTrees[aId].mLayerTree = p;
-    p->SetPendingCompositorUpdates(state->mPendingCompositorUpdates);
+    if (state->mPendingCompositorUpdate) {
+      p->SetPendingCompositorUpdate(state->mPendingCompositorUpdate.value());
+    }
     return p;
   }
 
   NS_WARNING("Created child without a matching parent?");
   // XXX: should be false, but that causes us to fail some tests on Mac w/ OMTC.
   // Bug 900745. change *aSuccess to false to see test failures.
   *aSuccess = true;
   LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId);
@@ -405,26 +407,28 @@ CrossProcessCompositorBridgeParent::GetC
     return nullptr;
   }
 
   MOZ_ASSERT(state->mParent);
   return state->mParent->GetCompositionManager(aLayerTree);
 }
 
 mozilla::ipc::IPCResult
-CrossProcessCompositorBridgeParent::RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId)
+CrossProcessCompositorBridgeParent::RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId,
+                                                                    const uint64_t& aSeqNo)
 {
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
 
   if (LayerTransactionParent* ltp = state.mLayerTree) {
-    ltp->AcknowledgeCompositorUpdate();
+    ltp->AcknowledgeCompositorUpdate(aSeqNo);
   }
-  MOZ_ASSERT(state.mPendingCompositorUpdates > 0);
-  state.mPendingCompositorUpdates--;
+  if (state.mPendingCompositorUpdate == Some(aSeqNo)) {
+    state.mPendingCompositorUpdate = Nothing();
+  }
   return IPC_OK();
 }
 
 void
 CrossProcessCompositorBridgeParent::DeferredDestroy()
 {
   mCompositorThreadHolder = nullptr;
   mSelfRef = nullptr;
@@ -447,17 +451,17 @@ CrossProcessCompositorBridgeParent::Allo
 
   LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId);
   if (sIndirectLayerTrees.end() != itr) {
     state = &itr->second;
   }
 
   TextureFlags flags = aFlags;
 
-  if (!state || state->mPendingCompositorUpdates) {
+  if (!state || state->mPendingCompositorUpdate) {
     // The compositor was recreated, and we're receiving layers updates for a
     // a layer manager that will soon be discarded or invalidated. We can't
     // return null because this will mess up deserialization later and we'll
     // kill the content process. Instead, we signal that the underlying
     // TextureHost should not attempt to access the compositor.
     flags |= TextureFlags::INVALID_COMPOSITOR;
   } else if (state->mLayerManager && state->mLayerManager->GetCompositor() &&
              aLayersBackend != state->mLayerManager->GetCompositor()->GetBackendType()) {
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
@@ -110,17 +110,19 @@ public:
   virtual void GetAPZTestData(const LayerTransactionParent* aLayerTree,
                               APZTestData* aOutData) override;
   virtual void SetConfirmedTargetAPZC(const LayerTransactionParent* aLayerTree,
                                       const uint64_t& aInputBlockId,
                                       const nsTArray<ScrollableLayerGuid>& aTargets) override;
 
   virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
   virtual mozilla::ipc::IPCResult RecvRemotePluginsReady()  override { return IPC_FAIL_NO_REASON(this); }
-  virtual mozilla::ipc::IPCResult RecvAcknowledgeCompositorUpdate(const uint64_t& aLayersId) override;
+  virtual mozilla::ipc::IPCResult RecvAcknowledgeCompositorUpdate(
+    const uint64_t& aLayersId,
+    const uint64_t& aSeqNo) override;
 
   void DidComposite(uint64_t aId,
                     TimeStamp& aCompositeStart,
                     TimeStamp& aCompositeEnd);
 
   virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                               const LayersBackend& aLayersBackend,
                                               const TextureFlags& aFlags,
--- a/gfx/layers/ipc/KnowsCompositor.h
+++ b/gfx/layers/ipc/KnowsCompositor.h
@@ -63,16 +63,20 @@ public:
     return mTextureFactoryIdentifier.mSupportsComponentAlpha;
   }
 
   const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const
   {
     return mTextureFactoryIdentifier;
   }
 
+  bool DeviceCanReset() const {
+    return GetCompositorBackendType() != LayersBackend::LAYERS_BASIC;
+  }
+
   int32_t GetSerial() { return mSerial; }
 
   /**
    * Helpers for finding other related interface. These are infallible.
    */
   virtual TextureForwarder* GetTextureForwarder() = 0;
   virtual LayersIPCActor* GetLayersIPCActor() = 0;
 
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -54,17 +54,16 @@ LayerTransactionParent::LayerTransaction
                                                CompositorBridgeParentBase* aBridge,
                                                uint64_t aId)
   : mLayerManager(aManager)
   , mCompositorBridge(aBridge)
   , mId(aId)
   , mChildEpoch(0)
   , mParentEpoch(0)
   , mPendingTransaction(0)
-  , mPendingCompositorUpdates(0)
   , mDestroyed(false)
   , mIPCOpen(false)
 {
 }
 
 LayerTransactionParent::~LayerTransactionParent()
 {
 }
@@ -570,32 +569,32 @@ LayerTransactionParent::RecvUpdate(const
                                 replyv)) {
         return IPC_FAIL_NO_REASON(this);
       }
       break;
     }
     case Edit::TOpAttachCompositable: {
       const OpAttachCompositable& op = edit.get_OpAttachCompositable();
       RefPtr<CompositableHost> host = FindCompositable(op.compositable());
-      if (mPendingCompositorUpdates) {
+      if (mPendingCompositorUpdate) {
         // Do not attach compositables from old layer trees. Return true since
         // content cannot handle errors.
         return IPC_OK();
       }
       if (!Attach(AsLayer(op.layer()), host, false)) {
         return IPC_FAIL_NO_REASON(this);
       }
       if (mLayerManager->GetCompositor()) {
         host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
       }
       break;
     }
     case Edit::TOpAttachAsyncCompositable: {
       const OpAttachAsyncCompositable& op = edit.get_OpAttachAsyncCompositable();
-      if (mPendingCompositorUpdates) {
+      if (mPendingCompositorUpdate) {
         // Do not attach compositables from old layer trees. Return true since
         // content cannot handle errors.
         return IPC_OK();
       }
       ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(OtherPid());
       if (!imageBridge) {
         return IPC_FAIL_NO_REASON(this);
       }
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -92,27 +92,23 @@ public:
 
   virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
 
   virtual base::ProcessId GetChildProcessId() override
   {
     return OtherPid();
   }
 
-  void AddPendingCompositorUpdate() {
-    mPendingCompositorUpdates++;
+  void SetPendingCompositorUpdate(uint64_t aNumber) {
+    mPendingCompositorUpdate = Some(aNumber);
   }
-  void SetPendingCompositorUpdates(uint32_t aCount) {
-    // Only called after construction.
-    MOZ_ASSERT(mPendingCompositorUpdates == 0);
-    mPendingCompositorUpdates = aCount;
-  }
-  void AcknowledgeCompositorUpdate() {
-    MOZ_ASSERT(mPendingCompositorUpdates > 0);
-    mPendingCompositorUpdates--;
+  void AcknowledgeCompositorUpdate(uint64_t aNumber) {
+    if (mPendingCompositorUpdate == Some(aNumber)) {
+      mPendingCompositorUpdate = Nothing();
+    }
   }
 
 protected:
   virtual mozilla::ipc::IPCResult RecvShutdown() override;
 
   virtual mozilla::ipc::IPCResult RecvPaintTime(const uint64_t& aTransactionId,
                                                 const TimeDuration& aPaintTime) override;
 
@@ -195,19 +191,19 @@ private:
   // parent. mChildEpoch is the latest epoch value received from the child.
   // mParentEpoch is the latest epoch value that we have told TabParent about
   // (via ObserveLayerUpdate).
   uint64_t mChildEpoch;
   uint64_t mParentEpoch;
 
   uint64_t mPendingTransaction;
 
-  // Number of compositor updates we're waiting for the child to
-  // acknowledge.
-  uint32_t mPendingCompositorUpdates;
+  // Not accepting layers updates until we receive an acknowledgement with this
+  // generation number.
+  Maybe<uint64_t> mPendingCompositorUpdate;
 
   // When the widget/frame/browser stuff in this process begins its
   // destruction process, we need to Disconnect() all the currently
   // live shadow layers, because some of them might be orphaned from
   // the layer tree.  This happens in Destroy() above.  After we
   // Destroy() ourself, there's a window in which that information
   // hasn't yet propagated back to the child side and it might still
   // send us layer transactions.  We want to ignore those transactions
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -157,17 +157,17 @@ parent:
 
   /**
    * Confirmation callback for UpdatePluginConfigurations and HideAllPlugins.
    */
   async RemotePluginsReady();
 
   // Confirmation that the child has invalidated all its layers, and will not
   // request layers against an old compositor.
-  async AcknowledgeCompositorUpdate(uint64_t id);
+  async AcknowledgeCompositorUpdate(uint64_t aLayersId, uint64_t aSeqNo);
 
   // Child sends the parent a request for fill ratio numbers.
   async RequestOverfill();
 
   // Child requests frame uniformity measurements
   sync GetFrameUniformity() returns (FrameUniformityData data);
 
   // The child is about to be destroyed, so perform any necessary cleanup.
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -496,17 +496,16 @@ MemoryPressureObserver::Observe(nsISuppo
 }
 
 gfxPlatform::gfxPlatform()
   : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
   , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
   , mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo)
   , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
   , mScreenDepth(0)
-  , mDeviceCounter(0)
 {
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
     mWordCacheCharLimit = UNINITIALIZED_VALUE;
     mWordCacheMaxEntries = UNINITIALIZED_VALUE;
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
     mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
@@ -2567,22 +2566,16 @@ gfxPlatform::ImportGPUDeviceData(const m
 
 bool
 gfxPlatform::SupportsApzDragInput() const
 {
   return gfxPrefs::APZDragEnabled();
 }
 
 void
-gfxPlatform::BumpDeviceCounter()
-{
-  mDeviceCounter++;
-}
-
-void
 gfxPlatform::InitOpenGLConfig()
 {
   #ifdef XP_WIN
   // Don't enable by default on Windows, since it could show up in about:support even
   // though it'll never get used. Only attempt if user enables the pref
   if (!Preferences::GetBool("layers.prefer-opengl")){
     return;
   }
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -670,20 +670,16 @@ public:
     }
 
     // Some platforms don't support CompositorOGL in an unaccelerated OpenGL
     // context. These platforms should return true here.
     virtual bool RequiresAcceleratedGLContextForCompositorOGL() const {
       return false;
     }
 
-    uint64_t GetDeviceCounter() const {
-      return mDeviceCounter;
-    }
-
     /**
      * Check the blocklist for a feature. Returns false if the feature is blocked
      * with an appropriate message and failure ID.
      * */
     static bool IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage,
                                     nsCString& aFailureId);
 
     const gfxSkipChars& EmptySkipChars() const { return kEmptySkipChars; }
@@ -857,17 +853,14 @@ private:
 
     // Backend that we are compositing with. NONE, if no compositor has been
     // created yet.
     mozilla::layers::LayersBackend mCompositorBackend;
 
     int32_t mScreenDepth;
     mozilla::gfx::IntSize mScreenSize;
 
-    // Generation number for devices that ClientLayerManagers might depend on.
-    uint64_t mDeviceCounter;
-
     // An instance of gfxSkipChars which is empty. It is used as the
     // basis for error-case iterators.
     const gfxSkipChars kEmptySkipChars;
 };
 
 #endif /* GFX_PLATFORM_H */
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -453,17 +453,16 @@ gfxWindowsPlatform::HandleDeviceReset()
   if (XRE_IsContentProcess()) {
     // Fetch updated device parameters.
     FetchAndImportContentDeviceData();
     UpdateANGLEConfig();
   }
 
   InitializeDevices();
   UpdateANGLEConfig();
-  BumpDeviceCounter();
   return true;
 }
 
 void
 gfxWindowsPlatform::UpdateBackendPrefs()
 {
   uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) |
                         BackendTypeBit(BackendType::SKIA);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/cacheir/function-length.js
@@ -0,0 +1,48 @@
+function interpreted() {
+    for (var i = 0; i < 50; i++) {
+        var f = function () {};
+        assertEq(f.length, 0);
+    }
+
+    for (var i = 0; i < 50; i++) {
+        var f = function (a, b) {};
+        assertEq(f.length, 2);
+    }
+}
+
+function bound() {
+    for (var i = 0; i < 50; i++) {
+        var f = (function () {}).bind({});
+        assertEq(f.length, 0);
+    }
+
+    for (var i = 0; i < 50; i++) {
+        var f = (function (a, b) {}).bind({});
+        assertEq(f.length, 2);
+    }
+}
+
+function native() {
+    for (var i = 0; i < 50; i++) {
+        // Use the interpreted function for getting the IC generated in the first place.
+        var f = function (a) {};
+
+        if (i == 15) {
+            f = Math.sin;
+        } else if (i == 20) {
+            f = Math.cos;
+        } else if (i == 25) {
+            f = Math.ceil;
+        } else if (i == 30) {
+            f = Math.tan;
+        } else if (i == 35) {
+            f = Math.tanh;
+        }
+
+        assertEq(f.length, 1);
+    }
+}
+
+interpreted();
+bound();
+native();
\ No newline at end of file
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -144,16 +144,18 @@ GetPropIRGenerator::tryAttachStub()
             if (tryAttachUnboxedExpando(obj, objId, id))
                 return true;
             if (tryAttachTypedObject(obj, objId, id))
                 return true;
             if (tryAttachModuleNamespace(obj, objId, id))
                 return true;
             if (tryAttachWindowProxy(obj, objId, id))
                 return true;
+            if (tryAttachFunction(obj, objId, id))
+                return true;
             if (tryAttachProxy(obj, objId, id))
                 return true;
             return false;
         }
 
         MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
 
         if (tryAttachProxyElement(obj, objId))
@@ -907,16 +909,52 @@ GetPropIRGenerator::tryAttachObjectLengt
         writer.returnFromIC();
         return true;
     }
 
     return false;
 }
 
 bool
+GetPropIRGenerator::tryAttachFunction(HandleObject obj, ObjOperandId objId, HandleId id)
+{
+    // Function properties are lazily resolved so they might not be defined yet.
+    // And we might end up in a situation where we always have a fresh function
+    // object during the IC generation.
+    if (!obj->is<JSFunction>())
+        return false;
+
+    JSObject* holder = nullptr;
+    PropertyResult prop;
+    // This property exists already, don't attach the stub.
+    if (LookupPropertyPure(cx_, obj, id, &holder, &prop))
+        return false;
+
+    JSFunction* fun = &obj->as<JSFunction>();
+
+    if (JSID_IS_ATOM(id, cx_->names().length)) {
+        // length was probably deleted from the function.
+        if (fun->hasResolvedLength())
+            return false;
+
+        // Lazy functions don't store the length.
+        if (fun->isInterpretedLazy())
+            return false;
+
+        maybeEmitIdGuard(id);
+        writer.guardClass(objId, GuardClassKind::JSFunction);
+        writer.loadFunctionLengthResult(objId);
+        writer.returnFromIC();
+        return true;
+    }
+
+    return false;
+}
+
+bool
 GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, HandleId id)
 {
     if (!obj->is<ModuleNamespaceObject>())
         return false;
 
     Rooted<ModuleNamespaceObject*> ns(cx_, &obj->as<ModuleNamespaceObject>());
     RootedModuleEnvironmentObject env(cx_);
     RootedShape shape(cx_);
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -184,16 +184,17 @@ enum class CacheKind : uint8_t
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \
     _(LoadUnboxedArrayElementResult)      \
     _(LoadTypedElementResult)             \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadArgumentsObjectLengthResult)    \
+    _(LoadFunctionLengthResult)           \
     _(LoadStringCharResult)               \
     _(LoadStringLengthResult)             \
     _(LoadFrameCalleeResult)              \
     _(LoadFrameNumActualArgsResult)       \
     _(LoadFrameArgumentResult)            \
     _(LoadEnvironmentFixedSlotResult)     \
     _(LoadEnvironmentDynamicSlotResult)   \
     _(CallScriptedGetterResult)           \
@@ -275,16 +276,17 @@ class StubField
 // in the IR, to keep the IR compact and the same size on all platforms.
 enum class GuardClassKind : uint8_t
 {
     Array,
     UnboxedArray,
     MappedArguments,
     UnmappedArguments,
     WindowProxy,
+    JSFunction,
 };
 
 // Class to record CacheIR + some additional metadata for code generation.
 class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
 {
     CompactBufferWriter buffer_;
 
     uint32_t nextOperandId_;
@@ -623,16 +625,22 @@ class MOZ_RAII CacheIRWriter : public JS
         addStubField(offset, StubField::Type::RawWord);
     }
     void loadInt32ArrayLengthResult(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj);
     }
     void loadUnboxedArrayLengthResult(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
     }
+    void loadArgumentsObjectLengthResult(ObjOperandId obj) {
+        writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
+    }
+    void loadFunctionLengthResult(ObjOperandId obj) {
+        writeOpWithOperandId(CacheOp::LoadFunctionLengthResult, obj);
+    }
     void loadArgumentsObjectArgResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadArgumentsObjectArgResult, obj);
         writeOperandId(index);
     }
     void loadDenseElementResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementResult, obj);
         writeOperandId(index);
     }
@@ -647,19 +655,16 @@ class MOZ_RAII CacheIRWriter : public JS
     }
     void loadTypedElementResult(ObjOperandId obj, Int32OperandId index, TypedThingLayout layout,
                                 Scalar::Type elementType) {
         writeOpWithOperandId(CacheOp::LoadTypedElementResult, obj);
         writeOperandId(index);
         buffer_.writeByte(uint32_t(layout));
         buffer_.writeByte(uint32_t(elementType));
     }
-    void loadArgumentsObjectLengthResult(ObjOperandId obj) {
-        writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
-    }
     void loadStringLengthResult(StringOperandId str) {
         writeOpWithOperandId(CacheOp::LoadStringLengthResult, str);
     }
     void loadStringCharResult(StringOperandId str, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadStringCharResult, str);
         writeOperandId(index);
     }
     void callScriptedGetterResult(ObjOperandId obj, JSFunction* getter) {
@@ -799,16 +804,17 @@ class MOZ_RAII GetPropIRGenerator : publ
 
     bool tryAttachNative(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id);
+    bool tryAttachFunction(HandleObject obj, ObjOperandId objId, HandleId id);
 
     bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
 
     bool tryAttachPrimitive(ValOperandId valId, HandleId id);
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -1223,16 +1223,19 @@ CacheIRCompiler::emitGuardClass()
         clasp = &MappedArgumentsObject::class_;
         break;
       case GuardClassKind::UnmappedArguments:
         clasp = &UnmappedArgumentsObject::class_;
         break;
       case GuardClassKind::WindowProxy:
         clasp = cx_->maybeWindowProxyClass();
         break;
+      case GuardClassKind::JSFunction:
+        clasp = &JSFunction::class_;
+        break;
     }
 
     MOZ_ASSERT(clasp);
     masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, clasp, failure->label());
     return true;
 }
 
 bool
@@ -1510,16 +1513,65 @@ CacheIRCompiler::emitLoadArgumentsObject
     // Shift out arguments length and return it. No need to type monitor
     // because this stub always returns int32.
     masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch);
     EmitStoreResult(masm, scratch, JSVAL_TYPE_INT32, output);
     return true;
 }
 
 bool
+CacheIRCompiler::emitLoadFunctionLengthResult()
+{
+    AutoOutputRegister output(*this);
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    // Get the JSFunction flags.
+    masm.load16ZeroExtend(Address(obj, JSFunction::offsetOfFlags()), scratch);
+
+    // Functions with lazy scripts don't store their length.
+    // If the length was resolved before the length property might be shadowed.
+    masm.branchTest32(Assembler::NonZero,
+                      scratch,
+                      Imm32(JSFunction::INTERPRETED_LAZY |
+                            JSFunction::RESOLVED_LENGTH),
+                      failure->label());
+
+    Label boundFunction;
+    masm.branchTest32(Assembler::NonZero, scratch, Imm32(JSFunction::BOUND_FUN), &boundFunction);
+    Label interpreted;
+    masm.branchTest32(Assembler::NonZero, scratch, Imm32(JSFunction::INTERPRETED), &interpreted);
+
+    // Load the length of the native function.
+    masm.load16ZeroExtend(Address(obj, JSFunction::offsetOfNargs()), scratch);
+    Label done;
+    masm.jump(&done);
+
+    masm.bind(&boundFunction);
+    // Bound functions might have a non-int32 length.
+    Address boundLength(obj, FunctionExtended::offsetOfExtendedSlot(BOUND_FUN_LENGTH_SLOT));
+    masm.branchTestInt32(Assembler::NotEqual, boundLength, failure->label());
+    masm.unboxInt32(boundLength, scratch);
+    masm.jump(&done);
+
+    masm.bind(&interpreted);
+    // Load the length from the function's script.
+    masm.loadPtr(Address(obj, JSFunction::offsetOfNativeOrScript()), scratch);
+    masm.load16ZeroExtend(Address(scratch, JSScript::offsetOfFunLength()), scratch);
+
+    masm.bind(&done);
+    EmitStoreResult(masm, scratch, JSVAL_TYPE_INT32, output);
+    return true;
+}
+
+bool
 CacheIRCompiler::emitLoadStringLengthResult()
 {
     AutoOutputRegister output(*this);
     Register str = allocator.useRegister(masm, reader.stringOperandId());
     AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
     masm.loadStringLength(str, scratch);
     EmitStoreResult(masm, scratch, JSVAL_TYPE_INT32, output);
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -33,16 +33,17 @@ namespace jit {
     _(LoadProto)                          \
     _(LoadEnclosingEnvironment)           \
     _(LoadDOMExpandoValue)                \
     _(LoadDOMExpandoValueIgnoreGeneration)\
     _(LoadUndefinedResult)                \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectLengthResult)    \
+    _(LoadFunctionLengthResult)           \
     _(LoadStringLengthResult)             \
     _(LoadStringCharResult)               \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \
     _(LoadUnboxedArrayElementResult)      \
     _(LoadTypedElementResult)
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1166,16 +1166,20 @@ class JSScript : public js::gc::TenuredC
     size_t nTypeSets() const {
         return nTypeSets_;
     }
 
     size_t funLength() const {
         return funLength_;
     }
 
+    static size_t offsetOfFunLength() {
+        return offsetof(JSScript, funLength_);
+    }
+
     size_t sourceStart() const {
         return sourceStart_;
     }
 
     size_t sourceEnd() const {
         return sourceEnd_;
     }
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -763,18 +763,90 @@ PresShell::AccessibleCaretEnabled(nsIDoc
   // on the specific device running), then enable it.
   if (sAccessibleCaretOnTouch && dom::TouchEvent::PrefEnabled(aDocShell)) {
     return true;
   }
   // Otherwise, disabled.
   return false;
 }
 
+nsIPresShell::nsIPresShell()
+    : mFrameConstructor(nullptr)
+    , mViewManager(nullptr)
+    , mFrameManager(nullptr)
+    , mHiddenInvalidationObserverRefreshDriver(nullptr)
+#ifdef ACCESSIBILITY
+    , mDocAccessible(nullptr)
+#endif
+#ifdef DEBUG
+    , mDrawEventTargetFrame(nullptr)
+#endif
+    , mPaintCount(0)
+    , mWeakFrames(nullptr)
+    , mCanvasBackgroundColor(NS_RGBA(0,0,0,0))
+    , mSelectionFlags(0)
+    , mRenderFlags(0)
+    , mStylesHaveChanged(false)
+    , mDidInitialize(false)
+    , mIsDestroying(false)
+    , mIsReflowing(false)
+    , mPaintingSuppressed(false)
+    , mIsThemeSupportDisabled(false)
+    , mIsActive(false)
+    , mFrozen(false)
+    , mIsFirstPaint(false)
+    , mObservesMutationsForPrint(false)
+    , mReflowScheduled(false)
+    , mSuppressInterruptibleReflows(false)
+    , mScrollPositionClampingScrollPortSizeSet(false)
+    , mPresShellId(0)
+    , mFontSizeInflationEmPerLine(0)
+    , mFontSizeInflationMinTwips(0)
+    , mFontSizeInflationLineThreshold(0)
+    , mFontSizeInflationForceEnabled(false)
+    , mFontSizeInflationDisabledInMasterProcess(false)
+    , mFontSizeInflationEnabled(false)
+    , mPaintingIsFrozen(false)
+    , mFontSizeInflationEnabledIsDirty(false)
+    , mIsNeverPainting(false)
+  {}
+
 PresShell::PresShell()
-  : mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
+  : mCaretEnabled(false)
+#ifdef DEBUG
+  , mInVerifyReflow(false)
+  , mCurrentReflowRoot(nullptr)
+  , mUpdateCount(0)
+#endif
+#ifdef MOZ_REFLOW_PERF
+  , mReflowCountMgr(nullptr)
+#endif
+  , mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
+  , mCurrentEventFrame(nullptr)
+  , mFirstCallbackEventRequest(nullptr)
+  , mLastCallbackEventRequest(nullptr)
+  , mLastReflowStart(0.0)
+  , mLastAnchorScrollPositionY(0)
+  , mChangeNestCount(0)
+  , mDocumentLoading(false)
+  , mIgnoreFrameDestruction(false)
+  , mHaveShutDown(false)
+  , mLastRootReflowHadUnconstrainedBSize(false)
+  , mNoDelayedMouseEvents(false)
+  , mNoDelayedKeyEvents(false)
+  , mIsDocumentGone(false)
+  , mShouldUnsuppressPainting(false)
+  , mAsyncResizeTimerIsActive(false)
+  , mInResize(false)
+  , mApproximateFrameVisibilityVisited(false)
+  , mNextPaintCompressed(false)
+  , mHasCSSBackgroundColor(false)
+  , mScaleToResolution(false)
+  , mIsLastChromeOnlyEscapeKeyConsumed(false)
+  , mHasReceivedPaintMessage(false)
 {
 #ifdef MOZ_REFLOW_PERF
   mReflowCountMgr = new ReflowCountMgr();
   mReflowCountMgr->SetPresContext(mPresContext);
   mReflowCountMgr->SetPresShell(this);
 #endif
   mLoadBegin = TimeStamp::Now();
 
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -79,18 +79,16 @@ class PresShell final : public nsIPresSh
                         public nsStubDocumentObserver,
                         public nsISelectionController,
                         public nsIObserver,
                         public nsSupportsWeakReference
 {
 public:
   PresShell();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   // nsISupports
   NS_DECL_ISUPPORTS
 
   static bool AccessibleCaretEnabled(nsIDocShell* aDocShell);
 
   void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
             nsViewManager* aViewManager, mozilla::StyleSetHandle aStyleSet);
   virtual void Destroy() override;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -220,18 +220,16 @@ class nsDocumentViewer final : public ns
 {
   friend class nsDocViewerSelectionListener;
   friend class nsPagePrintTimer;
   friend class nsPrintEngine;
 
 public:
   nsDocumentViewer();
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   // nsISupports interface...
   NS_DECL_ISUPPORTS
 
   // nsIContentViewer interface...
   NS_DECL_NSICONTENTVIEWER
 
   // nsIContentViewerEdit
   NS_DECL_NSICONTENTVIEWEREDIT
@@ -501,24 +499,46 @@ void nsDocumentViewer::PrepareToStartLoa
 
 #ifdef DEBUG
   mDebugFile = nullptr;
 #endif
 
 #endif // NS_PRINTING
 }
 
-// Note: operator new zeros our memory, so no need to init things to null.
 nsDocumentViewer::nsDocumentViewer()
-  : mTextZoom(1.0), mPageZoom(1.0), mOverrideDPPX(0.0), mMinFontSize(0),
+  : mParentWidget(nullptr),
+    mAttachedToParent(false),
+    mTextZoom(1.0),
+    mPageZoom(1.0),
+    mOverrideDPPX(0.0),
+    mMinFontSize(0),
+    mNumURLStarts(0),
+    mDestroyRefCount(0),
+    mStopped(false),
+    mLoaded(false),
+    mDeferredWindowClose(false),
     mIsSticky(true),
-#ifdef NS_PRINT_PREVIEW
+    mInPermitUnload(false),
+    mInPermitUnloadPrompt(false),
+#ifdef NS_PRINTING
+    mClosingWhilePrinting(false),
+#if NS_PRINT_PREVIEW
+    mPrintPreviewZoomed(false),
+    mPrintIsPending(false),
+    mPrintDocIsFullyLoaded(false),
+    mOriginalPrintPreviewScale(0.0),
     mPrintPreviewZoom(1.0),
-#endif
+#endif // NS_PRINT_PREVIEW
+#ifdef DEBUG
+    mDebugFile(nullptr),
+#endif // DEBUG
+#endif // NS_PRINTING
     mHintCharsetSource(kCharsetUninitialized),
+    mIsPageMode(false),
     mInitializedForPrintPreview(false),
     mHidden(false)
 {
   PrepareToStartLoad();
 }
 
 NS_IMPL_ADDREF(nsDocumentViewer)
 NS_IMPL_RELEASE(nsDocumentViewer)
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -189,16 +189,18 @@ protected:
 
   enum eRenderFlag {
     STATE_IGNORING_VIEWPORT_SCROLLING = 0x1,
     STATE_DRAWWINDOW_NOT_FLUSHING = 0x2
   };
   typedef uint8_t RenderFlags; // for storing the above flags
 
 public:
+  nsIPresShell();
+
   /**
    * All callers are responsible for calling |Destroy| after calling
    * |EndObservingDocument|.  It needs to be separate only because form
    * controls incorrectly store their data in the frames rather than the
    * content model and printing calls |EndObservingDocument| multiple
    * times to make form controls behave nicely when printed.
    */
   virtual void Destroy() = 0;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -197,31 +197,108 @@ IsVisualCharset(const nsCString& aCharse
       || aCharset.LowerCaseEqualsLiteral("iso-8859-8") ) {  // Hebrew
     return true; // visual text type
   }
   else {
     return false; // logical text type
   }
 }
 
-  // NOTE! nsPresContext::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
-
 nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
-  : mType(aType), mDocument(aDocument), mBaseMinFontSize(0),
-    mTextZoom(1.0), mFullZoom(1.0), mOverrideDPPX(0.0),
+  : mType(aType),
+    mShell(nullptr),
+    mDocument(aDocument),
+    mMedium(nullptr),
+    mLinkHandler(nullptr),
+    mInflationDisabledForShrinkWrap(false),
+    mBaseMinFontSize(0),
+    mTextZoom(1.0),
+    mFullZoom(1.0),
+    mOverrideDPPX(0.0),
     mLastFontInflationScreenSize(gfxSize(-1.0, -1.0)),
-    mPageSize(-1, -1), mPPScale(1.0f),
+    mCurAppUnitsPerDevPixel(0),
+    mAutoQualityMinFontSizePixelsPref(0),
+    mPageSize(-1, -1),
+    mPageScale(0.0),
+    mPPScale(1.0f),
+    mDefaultColor(NS_RGBA(0,0,0,0)),
+    mBackgroundColor(NS_RGBA(0,0,0,0)),
+    mLinkColor(NS_RGBA(0,0,0,0)),
+    mActiveLinkColor(NS_RGBA(0,0,0,0)),
+    mVisitedLinkColor(NS_RGBA(0,0,0,0)),
+    mFocusBackgroundColor(NS_RGBA(0,0,0,0)),
+    mFocusTextColor(NS_RGBA(0,0,0,0)),
+    mBodyTextColor(NS_RGBA(0,0,0,0)),
     mViewportStyleScrollbar(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
+    mFocusRingWidth(0),
+    mExistThrottledUpdates(false),
+    mImageAnimationMode(0),
     mImageAnimationModePref(imgIContainer::kNormalAnimMode),
+    mInterruptChecksToSkip(0),
+    mElementsRestyled(0),
+    mFramesConstructed(0),
+    mFramesReflowed(0),
+    mInteractionTimeEnabled(false),
+    mHasPendingInterrupt(false),
+    mPendingInterruptFromTest(false),
+    mInterruptsEnabled(false),
+    mUseDocumentFonts(false),
+    mUseDocumentColors(false),
+    mUnderlineLinks(false),
+    mSendAfterPaintToContent(false),
+    mUseFocusColors(false),
+    mFocusRingOnAnything(false),
+    mFocusRingStyle(false),
+    mDrawImageBackground(false),
+    mDrawColorBackground(false),
+    mNeverAnimate(false),
+    mIsRenderingOnlySelection(false),
+    mPaginated(false),
+    mCanPaginatedScroll(false),
+    mDoScaledTwips(false),
+    mIsRootPaginatedDocument(false),
+    mPrefBidiDirection(false),
+    mPrefScrollbarSide(0),
+    mPendingSysColorChanged(false),
+    mPendingThemeChanged(false),
+    mPendingUIResolutionChanged(false),
+    mPendingMediaFeatureValuesChanged(false),
+    mPrefChangePendingNeedsReflow(false),
+    mIsEmulatingMedia(false),
     mAllInvalidated(false),
-    mPaintFlashing(false), mPaintFlashingInitialized(false)
+    mIsGlyph(false),
+    mUsesRootEMUnits(false),
+    mUsesExChUnits(false),
+    mUsesViewportUnits(false),
+    mPendingViewportChange(false),
+    mCounterStylesDirty(false),
+    mPostedFlushCounterStyles(false),
+    mSuppressResizeReflow(false),
+    mIsVisual(false),
+    mFireAfterPaintEvents(false),
+    mIsChrome(false),
+    mIsChromeOriginImage(false),
+    mPaintFlashing(false),
+    mPaintFlashingInitialized(false),
+    mHasWarnedAboutPositionedTableParts(false),
+    mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
+    mQuirkSheetAdded(false),
+    mNeedsPrefUpdate(false),
+    mHadNonBlankPaint(false)
+#ifdef RESTYLE_LOGGING
+    , mRestyleLoggingEnabled(false)
+#endif
+#ifdef DEBUG
+    , mInitialized(false)
+#endif
 {
-  // NOTE! nsPresContext::operator new() zeroes out all members, so don't
-  // bother initializing members to 0.
+  PodZero(&mBorderWidthTable);
+#ifdef DEBUG
+  PodZero(&mLayoutPhaseCount);
+#endif
 
   mDoScaledTwips = true;
 
   SetBackgroundImageDraw(true);		// always draw the background
   SetBackgroundColorDraw(true);
 
   mBackgroundColor = NS_RGB(0xFF, 0xFF, 0xFF);
 
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -142,17 +142,16 @@ class nsPresContext : public nsIObserver
 public:
   typedef mozilla::FramePropertyTable FramePropertyTable;
   typedef mozilla::LangGroupFontPrefs LangGroupFontPrefs;
   typedef mozilla::ScrollbarStyles ScrollbarStyles;
   typedef mozilla::StaticPresData StaticPresData;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIOBSERVER
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
   NS_DECL_CYCLE_COLLECTION_CLASS(nsPresContext)
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsPresContext)
 
   enum nsPresContextType {
     eContext_Galley,       // unpaginated screen presentation
     eContext_PrintPreview, // paginated screen presentation
     eContext_Print,        // paginated printer presentation
     eContext_PageLayout    // paginated & editable.
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1333001-1.css
@@ -0,0 +1,1 @@
+@import url(chrome://foo);
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1333001-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<link rel=stylesheet href=1333001-1.css type=text/css>
+<link rel=stylesheet href=1333001-1.css type=text/css>
+<body onload="f()">
+<script>
+function f() {
+  document.styleSheets[1].cssRules[0].media;
+}
+</script>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -163,8 +163,9 @@ load 1290994-4.html
 load 1314531.html
 load 1315889-1.html
 load 1315894-1.html
 skip-if(stylo) load 1319072-1.html # bug 1323733
 HTTP load 1320423-1.html
 asserts-if(stylo,5-28) load 1321357-1.html # bug 1324669
 load 1328535-1.html
 load 1331272.html
+HTTP load 1333001-1.html
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -266,16 +266,20 @@ ImportRule::ImportRule(const ImportRule&
   // Whether or not an @import rule has a null sheet is a permanent
   // property of that @import rule, since it is null only if the target
   // sheet failed security checks.
   if (aCopy.mChildSheet) {
     RefPtr<CSSStyleSheet> sheet =
       aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
     SetSheet(sheet);
     // SetSheet sets mMedia appropriately
+  } else {
+    // We better just copy mMedia from aCopy, since we have nowhere else to get
+    // one.
+    mMedia = aCopy.mMedia;
   }
 }
 
 ImportRule::~ImportRule()
 {
   if (mChildSheet) {
     mChildSheet->SetOwnerRule(nullptr);
   }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoScreenOrientation.java
@@ -66,16 +66,20 @@ public class GeckoScreenOrientation {
 
     public static GeckoScreenOrientation getInstance() {
         if (sInstance == null) {
             sInstance = new GeckoScreenOrientation();
         }
         return sInstance;
     }
 
+    private GeckoScreenOrientation() {
+        update();
+    }
+
     /*
      * Enable Gecko screen orientation events on update.
      */
     public void enableNotifications() {
         update();
         mShouldNotify = true;
     }
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -929,21 +929,16 @@ pref("toolkit.telemetry.server", "https:
 pref("toolkit.telemetry.server_owner", "Mozilla");
 // Information page about telemetry (temporary ; will be about:telemetry in the end)
 pref("toolkit.telemetry.infoURL", "https://www.mozilla.org/legal/privacy/firefox.html#telemetry");
 // Determines whether full SQL strings are returned when they might contain sensitive info
 // i.e. dynamically constructed SQL strings or SQL executed by addons against addon DBs
 pref("toolkit.telemetry.debugSlowSql", false);
 // Whether to use the unified telemetry behavior, requires a restart.
 pref("toolkit.telemetry.unified", true);
-
-// Identity module
-pref("toolkit.identity.enabled", false);
-pref("toolkit.identity.debug", false);
-
 // AsyncShutdown delay before crashing in case of shutdown freeze
 pref("toolkit.asyncshutdown.crash_timeout", 60000);
 // Extra logging for AsyncShutdown barriers and phases
 pref("toolkit.asyncshutdown.log", false);
 
 // Enable deprecation warnings.
 pref("devtools.errorconsole.deprecation_warnings", true);
 
--- a/netwerk/base/CaptivePortalService.cpp
+++ b/netwerk/base/CaptivePortalService.cpp
@@ -40,16 +40,18 @@ CaptivePortalService::CaptivePortalServi
   , mMaxInterval(25*kDefaultInterval)
   , mBackoffFactor(5.0)
 {
   mLastChecked = TimeStamp::Now();
 }
 
 CaptivePortalService::~CaptivePortalService()
 {
+  LOG(("CaptivePortalService::~CaptivePortalService isParentProcess:%d\n",
+       XRE_GetProcessType() == GeckoProcessType_Default));
 }
 
 nsresult
 CaptivePortalService::PerformCheck()
 {
   LOG(("CaptivePortalService::PerformCheck mRequestInProgress:%d mInitialized:%d mStarted:%d\n",
         mRequestInProgress, mInitialized, mStarted));
   // Don't issue another request if last one didn't complete
@@ -71,16 +73,17 @@ CaptivePortalService::PerformCheck()
   mRequestInProgress = true;
   mCaptivePortalDetector->CheckCaptivePortal(kInterfaceName, this);
   return NS_OK;
 }
 
 nsresult
 CaptivePortalService::RearmTimer()
 {
+  LOG(("CaptivePortalService::RearmTimer\n"));
   // Start a timer to recheck
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
   if (mTimer) {
     mTimer->Cancel();
   }
 
   if (!mTimer) {
     mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
@@ -287,23 +290,22 @@ CaptivePortalService::Observe(nsISupport
     // The user needs to log in. We are in a captive portal.
     mState = LOCKED_PORTAL;
     mLastChecked = TimeStamp::Now();
     mEverBeenCaptive = true;
   } else if (!strcmp(aTopic, kCaptivePortalLoginSuccessEvent)) {
     // The user has successfully logged in. We have connectivity.
     mState = UNLOCKED_PORTAL;
     mLastChecked = TimeStamp::Now();
-    mRequestInProgress = false;
     mSlackCount = 0;
     mDelay = mMinInterval;
+
     RearmTimer();
   } else if (!strcmp(aTopic, kAbortCaptivePortalLoginEvent)) {
     // The login has been aborted
-    mRequestInProgress = false;
     mState = UNKNOWN;
     mLastChecked = TimeStamp::Now();
     mSlackCount = 0;
   }
 
   // Send notification so that the captive portal state is mirrored in the
   // content process.
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
@@ -331,25 +333,26 @@ CaptivePortalService::Prepare()
 }
 
 NS_IMETHODIMP
 CaptivePortalService::Complete(bool success)
 {
   LOG(("CaptivePortalService::Complete(success=%d) mState=%d\n", success, mState));
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
   mLastChecked = TimeStamp::Now();
-  if ((mState == UNKNOWN || mState == NOT_CAPTIVE) && success) {
-    mState = NOT_CAPTIVE;
-    // If this check succeeded and we have never been in a captive portal
-    // since the service was started, there is no need to keep polling
-    if (!mEverBeenCaptive) {
-      mDelay = 0;
-      if (mTimer) {
-        mTimer->Cancel();
-      }
+
+  // Note: this callback gets called when:
+  // 1. the request is completed, and content is valid (success == true)
+  // 2. when the request is aborted or times out (success == false)
+
+  if (success) {
+    if (mEverBeenCaptive) {
+      mState = UNLOCKED_PORTAL;
+    } else {
+      mState = NOT_CAPTIVE;
     }
   }
 
   mRequestInProgress = false;
   return NS_OK;
 }
 
 } // namespace net
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -655,18 +655,17 @@ nsSimpleURI::Resolve(const nsACString &r
 }
 
 NS_IMETHODIMP
 nsSimpleURI::GetAsciiSpec(nsACString &result)
 {
     nsAutoCString buf;
     nsresult rv = GetSpec(buf);
     if (NS_FAILED(rv)) return rv;
-    NS_EscapeURL(buf, esc_OnlyNonASCII|esc_AlwaysCopy, result);
-    return NS_OK;
+    return NS_EscapeURL(buf, esc_OnlyNonASCII|esc_AlwaysCopy, result, fallible);
 }
 
 NS_IMETHODIMP
 nsSimpleURI::GetAsciiHostPort(nsACString &result)
 {
     // XXX This behavior mimics GetHostPort.
     return NS_ERROR_FAILURE;
 }
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -1386,23 +1386,27 @@ nsStandardURL::GetAsciiSpec(nsACString &
         return NS_OK;
     }
 
     // try to guess the capacity required for result...
     result.SetCapacity(mSpec.Length() + std::min<uint32_t>(32, mSpec.Length()/10));
 
     result = Substring(mSpec, 0, mScheme.mLen + 3);
 
+    // This is left fallible as this entire function is expected to be
+    // infallible.
     NS_EscapeURL(Userpass(true), esc_OnlyNonASCII | esc_AlwaysCopy, result);
 
     // get the hostport
     nsAutoCString hostport;
     MOZ_ALWAYS_SUCCEEDS(GetAsciiHostPort(hostport));
     result += hostport;
 
+    // This is left fallible as this entire function is expected to be
+    // infallible.
     NS_EscapeURL(Path(), esc_OnlyNonASCII | esc_AlwaysCopy, result);
     CALL_RUST_GETTER_STR(result, GetAsciiSpec, result);
     return NS_OK;
 }
 
 // result is ASCII
 NS_IMETHODIMP
 nsStandardURL::GetAsciiHostPort(nsACString &result)
--- a/netwerk/base/nsTemporaryFileInputStream.cpp
+++ b/netwerk/base/nsTemporaryFileInputStream.cpp
@@ -79,16 +79,21 @@ nsTemporaryFileInputStream::ReadSegments
 
   // Limit requested count to the amount remaining in our section of the file.
   count = std::min(count, uint32_t(mEndPos - mCurPos));
 
   char buf[4096];
   while (*result < count) {
     uint32_t bufCount = std::min(count - *result, (uint32_t) sizeof(buf));
     int32_t bytesRead = PR_Read(mFileDescOwner->mFD, buf, bufCount);
+    if (bytesRead == 0) {
+      mClosed = true;
+      return NS_OK;
+    }
+
     if (bytesRead < 0) {
       return NS_ErrorAccordingToNSPR();
     }
 
     int32_t bytesWritten = 0;
     while (bytesWritten < bytesRead) {
       uint32_t writerCount = 0;
       nsresult rv = writer(this, closure, buf + bytesWritten, *result,
--- a/netwerk/base/nsURLHelperUnix.cpp
+++ b/netwerk/base/nsURLHelperUnix.cpp
@@ -60,23 +60,34 @@ net_GetFileFromURLSpec(const nsACString 
     if (NS_FAILED(rv))
       return rv;
     
     nsAutoCString directory, fileBaseName, fileExtension, path;
 
     rv = net_ParseFileURL(aURL, directory, fileBaseName, fileExtension);
     if (NS_FAILED(rv)) return rv;
 
-    if (!directory.IsEmpty())
-        NS_EscapeURL(directory, esc_Directory|esc_AlwaysCopy, path);
-    if (!fileBaseName.IsEmpty())
-        NS_EscapeURL(fileBaseName, esc_FileBaseName|esc_AlwaysCopy, path);
+    if (!directory.IsEmpty()) {
+        rv = NS_EscapeURL(directory, esc_Directory|esc_AlwaysCopy, path,
+                         mozilla::fallible);
+        if (NS_FAILED(rv))
+          return rv;
+    }
+    if (!fileBaseName.IsEmpty()) {
+        rv = NS_EscapeURL(fileBaseName, esc_FileBaseName|esc_AlwaysCopy, path,
+                          mozilla::fallible);
+        if (NS_FAILED(rv))
+          return rv;
+    }
     if (!fileExtension.IsEmpty()) {
         path += '.';
-        NS_EscapeURL(fileExtension, esc_FileExtension|esc_AlwaysCopy, path);
+        rv = NS_EscapeURL(fileExtension, esc_FileExtension|esc_AlwaysCopy, path,
+                          mozilla::fallible);
+        if (NS_FAILED(rv))
+          return rv;
     }
     
     NS_UnescapeURL(path);
     if (path.Length() != strlen(path.get()))
         return NS_ERROR_FILE_INVALID_PATH;
 
     if (IsUTF8(path)) {
         // speed up the start-up where UTF-8 is the native charset
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5750,16 +5750,17 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
     NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
     nsresult rv;
 
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!gHttpHandler->Active()) {
         LOG(("  after HTTP shutdown..."));
+        ReleaseListeners();
         return NS_ERROR_NOT_AVAILABLE;
     }
 
     rv = NS_CheckPortSafety(mURI);
     if (NS_FAILED(rv)) {
         ReleaseListeners();
         return rv;
     }
@@ -5828,17 +5829,20 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHttpChannel::AsyncOpen2(nsIStreamListener *aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+      ReleaseListeners();
+      return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 // BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
 // functions that called BeginConnect if needed. Only AsyncOpen and
 // OnProxyAvailable ever call BeginConnect.
 nsresult
 nsHttpChannel::BeginConnect()
--- a/netwerk/protocol/http/nsHttpDigestAuth.cpp
+++ b/netwerk/protocol/http/nsHttpDigestAuth.cpp
@@ -116,17 +116,20 @@ nsHttpDigestAuth::GetMethodAndPath(nsIHt
           //
           // make sure we escape any UTF-8 characters in the URI path.  the
           // digest auth uri attribute needs to match the request-URI.
           //
           // XXX we should really ask the HTTP channel for this string
           // instead of regenerating it here.
           //
           nsAutoCString buf;
-          path = NS_EscapeURL(path, esc_OnlyNonASCII, buf);
+          rv = NS_EscapeURL(path, esc_OnlyNonASCII, buf, mozilla::fallible);
+          if (NS_SUCCEEDED(rv)) {
+            path = buf;
+          }
         }
       }
     }
   }
   return rv;
 }
 
 //-----------------------------------------------------------------------------
--- a/parser/html/nsHtml5DocumentBuilder.cpp
+++ b/parser/html/nsHtml5DocumentBuilder.cpp
@@ -17,16 +17,18 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHtm
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder)
 NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
 
 NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
 NS_IMPL_RELEASE_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
 
 nsHtml5DocumentBuilder::nsHtml5DocumentBuilder(bool aRunsToCompletion)
+  : mBroken(NS_OK)
+  , mFlushState(eHtml5FlushState::eNotFlushing)
 {
   mRunsToCompletion = aRunsToCompletion;
 }
 
 nsresult
 nsHtml5DocumentBuilder::Init(nsIDocument* aDoc,
                             nsIURI* aURI,
                             nsISupports* aContainer,
--- a/parser/html/nsHtml5DocumentBuilder.h
+++ b/parser/html/nsHtml5DocumentBuilder.h
@@ -114,17 +114,14 @@ protected:
   AutoTArray<nsCOMPtr<nsIContent>, 32> mOwnedElements;
   /**
    * Non-NS_OK if this parser should refuse to process any more input.
    * For example, the parser needs to be marked as broken if it drops some
    * input due to a memory allocation failure. In such a case, the whole
    * parser needs to be marked as broken, because some input has been lost
    * and parsing more input could lead to a DOM where pieces of HTML source
    * that weren't supposed to become scripts become scripts.
-   *
-   * Since NS_OK is actually 0, zeroing operator new takes care of
-   * initializing this.
    */
   nsresult                             mBroken;
   eHtml5FlushState                     mFlushState;
 };
 
 #endif // nsHtml5DocumentBuilder_h
--- a/parser/html/nsHtml5OplessBuilder.h
+++ b/parser/html/nsHtml5OplessBuilder.h
@@ -18,18 +18,16 @@ class nsParserBase;
  * not used.
  *
  * This class is mostly responsible for wrapping tree building in an update
  * batch and resetting various fields in nsContentSink upon finishing.
  */
 class nsHtml5OplessBuilder : public nsHtml5DocumentBuilder
 {
 public:
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   nsHtml5OplessBuilder();
   ~nsHtml5OplessBuilder();
   void Start();
   void Finish();
   void SetParser(nsParserBase* aParser);
 };
 
 #endif // nsHtml5OplessBuilder_h
--- a/parser/html/nsHtml5Parser.cpp
+++ b/parser/html/nsHtml5Parser.cpp
@@ -30,25 +30,32 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExecutor)
   tmp->DropStreamParser();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 nsHtml5Parser::nsHtml5Parser()
-  : mFirstBuffer(new nsHtml5OwningUTF16Buffer((void*)nullptr))
+  : mLastWasCR(false)
+  , mDocWriteSpeculativeLastWasCR(false)
+  , mBlocked(false)
+  , mDocWriteSpeculatorActive(false)
+  , mInsertionPointPushLevel(0)
+  , mDocumentClosed(false)
+  , mInDocumentWrite(false)
+  , mFirstBuffer(new nsHtml5OwningUTF16Buffer((void*)nullptr))
   , mLastBuffer(mFirstBuffer)
   , mExecutor(new nsHtml5TreeOpExecutor())
   , mTreeBuilder(new nsHtml5TreeBuilder(mExecutor, nullptr))
   , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder, false))
   , mRootContextLineNumber(1)
+  , mReturnToStreamParserPermitted(false)
 {
   mTokenizer->setInterner(&mAtomTable);
-  // There's a zeroing operator new for everything else
 }
 
 nsHtml5Parser::~nsHtml5Parser()
 {
   mTokenizer->end();
   if (mDocWriteSpeculativeTokenizer) {
     mDocWriteSpeculativeTokenizer->end();
   }
--- a/parser/html/nsHtml5Parser.h
+++ b/parser/html/nsHtml5Parser.h
@@ -26,17 +26,16 @@
 #include "nsHtml5AtomTable.h"
 #include "nsWeakReference.h"
 #include "nsHtml5StreamListener.h"
 
 class nsHtml5Parser final : public nsIParser,
                             public nsSupportsWeakReference
 {
   public:
-    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHtml5Parser, nsIParser)
 
     nsHtml5Parser();
 
     /* Start nsIParser */
     /**
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -144,33 +144,47 @@ class nsHtml5LoadFlusher : public Runnab
       mExecutor->FlushSpeculativeLoads();
       return NS_OK;
     }
 };
 
 nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
                                          nsHtml5Parser* aOwner,
                                          eParserMode aMode)
-  : mFirstBuffer(nullptr) // Will be filled when starting
+  : mSniffingLength(0)
+  , mBomState(eBomState::BOM_SNIFFING_NOT_STARTED)
+  , mCharsetSource(kCharsetUninitialized)
+  , mReparseForbidden(false)
   , mLastBuffer(nullptr) // Will be filled when starting
   , mExecutor(aExecutor)
   , mTreeBuilder(new nsHtml5TreeBuilder((aMode == VIEW_SOURCE_HTML ||
                                          aMode == VIEW_SOURCE_XML) ?
                                              nullptr : mExecutor->GetStage(),
                                          aMode == NORMAL ?
                                              mExecutor->GetStage() : nullptr))
   , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder, aMode == VIEW_SOURCE_XML))
   , mTokenizerMutex("nsHtml5StreamParser mTokenizerMutex")
   , mOwner(aOwner)
+  , mLastWasCR(false)
+  , mStreamState(eHtml5StreamState::STREAM_NOT_STARTED)
+  , mSpeculating(false)
+  , mAtEOF(false)
   , mSpeculationMutex("nsHtml5StreamParser mSpeculationMutex")
+  , mSpeculationFailureCount(0)
+  , mTerminated(false)
+  , mInterrupted(false)
   , mTerminatedMutex("nsHtml5StreamParser mTerminatedMutex")
   , mThread(nsHtml5Module::GetStreamParserThread())
   , mExecutorFlusher(new nsHtml5ExecutorFlusher(aExecutor))
   , mLoadFlusher(new nsHtml5LoadFlusher(aExecutor))
+  , mFeedChardet(false)
+  , mInitialEncodingWasFromParentFrame(false)
   , mFlushTimer(do_CreateInstance("@mozilla.org/timer;1"))
+  , mFlushTimerArmed(false)
+  , mFlushTimerEverFired(false)
   , mMode(aMode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   mFlushTimer->SetTarget(mThread);
 #ifdef DEBUG
   mAtomTable.SetPermittedLookupThread(mThread);
 #endif
   mTokenizer->setInterner(&mAtomTable);
--- a/parser/html/nsHtml5StreamParser.h
+++ b/parser/html/nsHtml5StreamParser.h
@@ -103,17 +103,16 @@ enum eHtml5StreamState {
 class nsHtml5StreamParser : public nsICharsetDetectionObserver {
 
   friend class nsHtml5RequestStopper;
   friend class nsHtml5DataAvailable;
   friend class nsHtml5StreamParserContinuation;
   friend class nsHtml5TimerKungFu;
 
   public:
-    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHtml5StreamParser,
                                              nsICharsetDetectionObserver)
 
     static void InitializeStatics();
 
     nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
                         nsHtml5Parser* aOwner,
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -60,20 +60,26 @@ class nsHtml5ExecutorReflusher : public 
     }
 };
 
 static mozilla::LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
 static nsITimer* gFlushTimer = nullptr;
 
 nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
   : nsHtml5DocumentBuilder(false)
+  , mSuppressEOF(false)
+  , mReadingFromStage(false)
+  , mStreamParser(nullptr)
   , mPreloadedURLs(23)  // Mean # of preloadable resources per page on dmoz
   , mSpeculationReferrerPolicy(mozilla::net::RP_Unset)
+  , mStarted(false)
+  , mRunFlushLoopOnStack(false)
+  , mCallContinueInterruptedParsingIfEnabled(false)
+  , mAlreadyComplainedAboutCharset(false)
 {
-  // zeroing operator new for everything else
 }
 
 nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor()
 {
   if (gBackgroundFlushList && isInList()) {
     mOpQueue.Clear();
     removeFrom(*gBackgroundFlushList);
     if (gBackgroundFlushList->isEmpty()) {
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -33,17 +33,16 @@ class nsHtml5TreeOpExecutor final : publ
                                     public nsIContentSink,
                                     public nsAHtml5TreeOpSink,
                                     public mozilla::LinkedListElement<nsHtml5TreeOpExecutor>
 {
   friend class nsHtml5FlushLoopGuard;
   typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
 
   public:
-    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
     NS_DECL_ISUPPORTS_INHERITED
 
   private:
     static bool        sExternalViewSource;
 #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
     static uint32_t    sAppendBatchMaxSize;
     static uint32_t    sAppendBatchSlotsExamined;
     static uint32_t    sAppendBatchExaminations;
--- a/python/mozbuild/mozbuild/preprocessor.py
+++ b/python/mozbuild/mozbuild/preprocessor.py
@@ -749,17 +749,17 @@ class Preprocessor:
                     args = self.applyFilters(args)
                 if not os.path.isabs(args):
                     args = os.path.join(self.context['DIRECTORY'], args)
                 args = open(args, 'rU')
             except Preprocessor.Error:
                 raise
             except:
                 raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
-        self.checkLineNumbers = bool(re.search('\.(js|jsm|java)(?:\.in)?$', args.name))
+        self.checkLineNumbers = bool(re.search('\.(js|jsm|java|webidl)(?:\.in)?$', args.name))
         oldFile = self.context['FILE']
         oldLine = self.context['LINE']
         oldDir = self.context['DIRECTORY']
         self.noteLineInfo()
 
         if args.isatty():
             # we're stdin, use '-' and '' for file and dir
             self.context['FILE'] = '-'
rename from toolkit/identity/IdentityCryptoService.cpp
rename to services/crypto/component/IdentityCryptoService.cpp
--- a/services/crypto/component/moz.build
+++ b/services/crypto/component/moz.build
@@ -2,18 +2,20 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 XPIDL_SOURCES += [
+    'nsIIdentityCryptoService.idl',
     'nsISyncJPAKE.idl',
 ]
 
 XPIDL_MODULE = 'services-crypto-component'
 
 SOURCES += [
+    'IdentityCryptoService.cpp',
     'nsSyncJPAKE.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
rename from toolkit/identity/nsIIdentityCryptoService.idl
rename to services/crypto/component/nsIIdentityCryptoService.idl
rename from toolkit/identity/LogUtils.jsm
rename to services/crypto/modules/LogUtils.jsm
--- a/toolkit/identity/LogUtils.jsm
+++ b/services/crypto/modules/LogUtils.jsm
@@ -2,17 +2,17 @@
 /* vim: set ft=javascript ts=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/. */
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["Logger"];
-const PREF_DEBUG = "toolkit.identity.debug";
+const PREF_DEBUG = "services.sync.log.cryptoDebug";
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
@@ -64,17 +64,17 @@ IdentityLogger.prototype = {
       }
     });
     return "Identity " + aPrefix + ": " + strings.join(" ");
   },
 
   /**
    * log() - utility function to print a list of arbitrary things
    *
-   * Enable with about:config pref toolkit.identity.debug
+   * Enable with about:config pref services.sync.log.cryptoDebug
    */
   log: function log(aPrefix, ...args) {
     if (!this._debug) {
       return;
     }
     let output = this._generateLogMessage(aPrefix, args);
     dump(output + "\n");
 
rename from toolkit/identity/jwcrypto.jsm
rename to services/crypto/modules/jwcrypto.jsm
--- a/toolkit/identity/jwcrypto.jsm
+++ b/services/crypto/modules/jwcrypto.jsm
@@ -9,17 +9,17 @@
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
+Cu.import("resource://gre/modules/services-crypto/LogUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this,
                                    "IdentityCryptoService",
                                    "@mozilla.org/identity/crypto-service;1",
                                    "nsIIdentityCryptoService");
 
 this.EXPORTED_SYMBOLS = ["jwcrypto"];
 
--- a/services/crypto/moz.build
+++ b/services/crypto/moz.build
@@ -7,15 +7,17 @@
 with Files('**'):
     BUG_COMPONENT = ('Mozilla Services', 'Firefox Sync: Crypto')
 
 DIRS += ['component']
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 EXTRA_JS_MODULES['services-crypto'] += [
+    'modules/jwcrypto.jsm',
+    'modules/LogUtils.jsm',
     'modules/utils.js',
     'modules/WeaveCrypto.js',
 ]
 
 EXTRA_COMPONENTS += [
     'cryptoComponents.manifest',
 ]
--- a/services/crypto/tests/unit/head_helpers.js
+++ b/services/crypto/tests/unit/head_helpers.js
@@ -24,16 +24,39 @@ updateAppInfo({
   name: "XPCShell",
   ID: "{3e3ba16c-1675-4e88-b9c8-afef81b3d2ef}",
   version: "1",
   platformVersion: "",
   OS,
 });
 }
 
+function base64UrlDecode(s) {
+  s = s.replace(/-/g, "+");
+  s = s.replace(/_/g, "/");
+
+  // Replace padding if it was stripped by the sender.
+  // See http://tools.ietf.org/html/rfc4648#section-4
+  switch (s.length % 4) {
+    case 0:
+      break; // No pad chars in this case
+    case 2:
+      s += "==";
+      break; // Two pad chars
+    case 3:
+      s += "=";
+      break; // One pad char
+    default:
+      throw new InputException("Illegal base64url string!");
+  }
+
+  // With correct padding restored, apply the standard base64 decoder
+  return atob(s);
+}
+
 // Register resource alias. Normally done in SyncComponents.manifest.
 function addResourceAlias() {
   Cu.import("resource://gre/modules/Services.jsm");
   const resProt = Services.io.getProtocolHandler("resource")
                           .QueryInterface(Ci.nsIResProtocolHandler);
   let uri = Services.io.newURI("resource://gre/modules/services-crypto/");
   resProt.setSubstitution("services-crypto", uri);
 }
rename from toolkit/identity/tests/unit/test_crypto_service.js
rename to services/crypto/tests/unit/test_crypto_service.js
--- a/toolkit/identity/tests/unit/test_crypto_service.js
+++ b/services/crypto/tests/unit/test_crypto_service.js
@@ -1,16 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
+Cu.import("resource://gre/modules/services-crypto/LogUtils.jsm");
 
 const idService = Cc["@mozilla.org/identity/crypto-service;1"]
                     .getService(Ci.nsIIdentityCryptoService);
 
 const ALG_DSA = "DS160";
 const ALG_RSA = "RS256";
 
 const BASE64_URL_ENCODINGS = [
@@ -32,16 +30,20 @@ const BASE64_URL_ENCODINGS = [
    "z4DPjM67zrsnIM6_4by2zrQnIOG8gM67z47PgM63zr4sIOG8gM67zrsnIOG8kM-H4b-Wzr3Ov8-CIOG8k869IM68zq3Os86x"],
 ];
 
 // When the output of an operation is a
 function do_check_eq_or_slightly_less(x, y) {
   do_check_true(x >= y - (3 * 8));
 }
 
+function log(...aMessageArgs) {
+  Logger.log.apply(Logger, ["test"].concat(aMessageArgs));
+}
+
 function test_base64_roundtrip() {
   let message = "Attack at dawn!";
   let encoded = idService.base64UrlEncode(message);
   let decoded = base64UrlDecode(encoded);
   do_check_neq(message, encoded);
   do_check_eq(decoded, message);
   run_next_test();
 }
rename from toolkit/identity/tests/unit/test_jwcrypto.js
rename to services/crypto/tests/unit/test_jwcrypto.js
--- a/toolkit/identity/tests/unit/test_jwcrypto.js
+++ b/services/crypto/tests/unit/test_jwcrypto.js
@@ -1,21 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict"
 
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
 XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
+                                  "resource://gre/modules/services-crypto/jwcrypto.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this,
                                    "CryptoService",
                                    "@mozilla.org/identity/crypto-service;1",
                                    "nsIIdentityCryptoService");
 
 const RP_ORIGIN = "http://123done.org";
 const INTERNAL_ORIGIN = "browserid://";
--- a/services/crypto/tests/unit/xpcshell.ini
+++ b/services/crypto/tests/unit/xpcshell.ini
@@ -6,14 +6,18 @@ support-files =
 
 [test_load_modules.js]
 
 [test_crypto_crypt.js]
 [test_crypto_deriveKey.js]
 [test_crypto_random.js]
 # Bug 676977: test hangs consistently on Android
 skip-if = os == "android"
+[test_crypto_service.js]
+skip-if = os == "android"
+[test_jwcrypto.js]
+skip-if = os == "android"
 
 [test_utils_hawk.js]
 [test_utils_hkdfExpand.js]
 [test_utils_httpmac.js]
 [test_utils_pbkdf2.js]
 [test_utils_sha1.js]
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -21,17 +21,17 @@ Cu.import("resource://gre/modules/FxAcco
 
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsClient",
   "resource://gre/modules/FxAccountsClient.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsConfig",
   "resource://gre/modules/FxAccountsConfig.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
-  "resource://gre/modules/identity/jwcrypto.jsm");
+  "resource://gre/modules/services-crypto/jwcrypto.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsOAuthGrantClient",
   "resource://gre/modules/FxAccountsOAuthGrantClient.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfile",
   "resource://gre/modules/FxAccountsProfile.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Utils",
--- a/services/fxaccounts/tests/mochitest/test_invalidEmailCase.html
+++ b/services/fxaccounts/tests/mochitest/test_invalidEmailCase.html
@@ -113,17 +113,16 @@ function runTest() {
       ok(false, JSON.stringify(signInError));
     }
   );
 };
 
 SpecialPowers.pushPrefEnv({"set": [
     ["identity.fxaccounts.enabled", true],         // fx accounts
     ["identity.fxaccounts.auth.uri", TEST_SERVER], // our sjs server
-    ["toolkit.identity.debug", true],              // verbose identity logging
     ["browser.dom.window.dump.enabled", true],
   ]},
   function () { runTest(); }
 );
 
 </script>
 </pre>
 </body>
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -342,60 +342,8 @@ linux64-ccov/opt:
         config:
             - builds/releng_base_linux_64_builds.py
             - balrog/production.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage
         tooltool-downloads: public
         need-xvfb: true
-
-linux64-stylo/opt:
-    description: "Linux64-stylo Opt"
-    index:
-        product: firefox
-        job-name: linux64-stylo-opt
-    treeherder:
-        platform: linux64/stylo
-        symbol: tc(Bs)
-        tier: 2
-    run-on-projects: [ ]
-    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
-    worker:
-        implementation: docker-worker
-        max-run-time: 36000
-    run:
-        using: mozharness
-        actions: [get-secrets build check-test generate-build-stats update]
-        config:
-            - builds/releng_base_linux_64_builds.py
-            - balrog/production.py
-        script: "mozharness/scripts/fx_desktop_build.py"
-        secrets: true
-        custom-build-variant-cfg: stylo
-        tooltool-downloads: public
-        need-xvfb: true
-
-linux64-stylo/debug:
-    description: "Linux64-stylo Debug"
-    index:
-        product: firefox
-        job-name: linux64-stylo-debug
-    treeherder:
-        platform: linux64/stylo
-        symbol: tc(Bsd)
-        tier: 2
-    run-on-projects: [ ]
-    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
-    worker:
-        implementation: docker-worker
-        max-run-time: 36000
-    run:
-        using: mozharness
-        actions: [get-secrets build check-test generate-build-stats update]
-        config:
-            - builds/releng_base_linux_64_builds.py
-            - balrog/production.py
-        script: "mozharness/scripts/fx_desktop_build.py"
-        secrets: true
-        custom-build-variant-cfg: stylo-debug
-        tooltool-downloads: public
-        need-xvfb: true
--- a/testing/mozbase/mozrunner/mozrunner/base/runner.py
+++ b/testing/mozbase/mozrunner/mozrunner/base/runner.py
@@ -2,27 +2,33 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from abc import ABCMeta, abstractproperty
 import os
 import subprocess
 import traceback
+import sys
 
 from mozlog import get_default_logger
 from mozprocess import ProcessHandler
 try:
     import mozcrash
 except ImportError:
     mozcrash = None
 
 from ..application import DefaultContext
 from ..errors import RunnerNotStartedError
 
+if sys.version_info[0] < 3:
+    unicode_type = unicode
+else:
+    unicode_type = str
+
 
 class BaseRunner(object):
     """
     The base runner class for all mozrunner objects, both local and remote.
     """
     __metaclass__ = ABCMeta
     last_test = 'mozrunner-startup'
     process_handler = None
@@ -99,17 +105,26 @@ class BaseRunner(object):
 
         # attach a debugger, if specified
         if debug_args:
             cmd = list(debug_args) + cmd
 
         if self.logger:
             self.logger.info('Application command: %s' % ' '.join(cmd))
         if interactive:
-            self.process_handler = subprocess.Popen(cmd, env=self.env)
+            filtered_env = {}
+            for k in self.env:
+                v = self.env[k]
+                if isinstance(v, unicode_type):
+                    v = v.encode('utf-8')
+                if isinstance(k, unicode_type):
+                    k = k.encode('utf-8')
+                filtered_env[k] = v
+
+            self.process_handler = subprocess.Popen(cmd, env=filtered_env)
             # TODO: other arguments
         else:
             # this run uses the managed processhandler
             self.process_handler = self.process_class(cmd, env=self.env, **self.process_args)
             self.process_handler.run(self.timeout, self.output_timeout)
 
         self.crashed = 0
         return self.process_handler.pid
--- a/testing/mozharness/configs/merge_day/aurora_to_beta.py
+++ b/testing/mozharness/configs/merge_day/aurora_to_beta.py
@@ -33,19 +33,16 @@ config = {
         (f, "ac_add_options --with-branding=browser/branding/aurora",
          "ac_add_options --enable-official-branding")
         for f in ["browser/config/mozconfigs/linux32/l10n-mozconfig",
                   "browser/config/mozconfigs/linux64/l10n-mozconfig",
                   "browser/config/mozconfigs/win32/l10n-mozconfig",
                   "browser/config/mozconfigs/win64/l10n-mozconfig",
                   "browser/config/mozconfigs/macosx64/l10n-mozconfig"]
     ] + [
-        ("browser/config/mozconfigs/macosx64/nightly",
-         "ac_add_options --with-branding=browser/branding/aurora",
-         "ac_add_options --with-branding=browser/branding/nightly"),
         ("browser/confvars.sh",
          "ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-aurora",
          "ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-beta,firefox-mozilla-release"),
         ("browser/confvars.sh",
          "MAR_CHANNEL_ID=firefox-mozilla-aurora",
          "MAR_CHANNEL_ID=firefox-mozilla-beta"),
         ("browser/config/mozconfigs/whitelist",
          "ac_add_options --with-branding=browser/branding/aurora",
--- a/testing/mozharness/configs/merge_day/central_to_aurora.py
+++ b/testing/mozharness/configs/merge_day/central_to_aurora.py
@@ -47,22 +47,16 @@ config = {
     ] + [
         # File, from, to
         ("browser/confvars.sh",
          "ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central",
          "ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-aurora"),
         ("browser/confvars.sh",
          "MAR_CHANNEL_ID=firefox-mozilla-central",
          "MAR_CHANNEL_ID=firefox-mozilla-aurora"),
-        ("browser/config/mozconfigs/macosx64/nightly",
-         "ac_add_options --with-branding=browser/branding/nightly",
-         "ac_add_options --with-branding=browser/branding/aurora"),
-        ("browser/config/mozconfigs/macosx64/l10n-mozconfig",
-         "ac_add_options --with-branding=browser/branding/nightly",
-         "ac_add_options --with-branding=browser/branding/aurora"),
         ("browser/config/mozconfigs/whitelist",
          "ac_add_options --with-branding=browser/branding/nightly",
          "ac_add_options --with-branding=browser/branding/aurora"),
     ],
     "locale_files": [
         "browser/locales/shipped-locales",
         "browser/locales/all-locales",
         "mobile/android/locales/maemo-locales",
--- a/toolkit/components/captivedetect/captivedetect.js
+++ b/toolkit/components/captivedetect/captivedetect.js
@@ -348,17 +348,17 @@ CaptivePortalDetector.prototype = {
     gSysMsgr.broadcastMessage(kCaptivePortalSystemMessage, {});
   },
 
   _mayRetry: function _mayRetry() {
     if (this._runningRequest.retryCount++ < this._maxRetryCount) {
       debug("retry-Detection: " + this._runningRequest.retryCount + "/" + this._maxRetryCount);
       this._startDetection();
     } else {
-      this.executeCallback(true);
+      this.executeCallback(false);
     }
   },
 
   executeCallback: function executeCallback(success) {
     if (this._runningRequest) {
       debug("callback executed");
       if (this._runningRequest.hasOwnProperty("callback")) {
         this._runningRequest.callback.complete(success);
--- a/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
@@ -30,17 +30,17 @@ function test_portal_not_found() {
   let callback = {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 2);
-      do_check_true(success);
+      do_check_false(success);
       do_check_eq(attempt, 6);
       gServer.stop(do_test_finished);
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
--- a/toolkit/components/terminator/nsTerminator.cpp
+++ b/toolkit/components/terminator/nsTerminator.cpp
@@ -543,13 +543,13 @@ void
 nsTerminator::UpdateCrashReport(const char* aTopic)
 {
 #if defined(MOZ_CRASHREPORTER)
   // In case of crash, we wish to know where in shutdown we are
   nsAutoCString report(aTopic);
 
   Unused << CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ShutdownProgress"),
                                                report);
-#endif // defined(MOZ_CRASH_REPORTER)
+#endif // defined(MOZ_CRASHREPORTER)
 }
 
 
 } // namespace mozilla
deleted file mode 100644
--- a/toolkit/identity/FirefoxAccounts.jsm
+++ /dev/null
@@ -1,320 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["FirefoxAccounts"];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
-                                  "resource://gre/modules/identity/IdentityUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
-                                  "resource://gre/modules/identity/IdentityUtils.jsm");
-
-// loglevel preference should be one of: "FATAL", "ERROR", "WARN", "INFO",
-// "CONFIG", "DEBUG", "TRACE" or "ALL". We will be logging error messages by
-// default.
-const PREF_LOG_LEVEL = "identity.fxaccounts.loglevel";
-try {
-  this.LOG_LEVEL =
-    Services.prefs.getPrefType(PREF_LOG_LEVEL) == Ci.nsIPrefBranch.PREF_STRING
-    && Services.prefs.getCharPref(PREF_LOG_LEVEL);
-} catch (e) {
-  this.LOG_LEVEL = Log.Level.Error;
-}
-
-var log = Log.repository.getLogger("Identity.FxAccounts");
-log.level = LOG_LEVEL;
-log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
-
-#ifdef MOZ_B2G
-XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsManager",
-                                  "resource://gre/modules/FxAccountsManager.jsm",
-                                  "FxAccountsManager");
-Cu.import("resource://gre/modules/FxAccountsCommon.js");
-#else
-log.warn("The FxAccountsManager is only functional in B2G at this time.");
-var FxAccountsManager = null;
-var ONVERIFIED_NOTIFICATION = null;
-var ONLOGIN_NOTIFICATION = null;
-var ONLOGOUT_NOTIFICATION = null;
-#endif
-
-function FxAccountsService() {
-  Services.obs.addObserver(this, "quit-application-granted", false);
-  if (ONVERIFIED_NOTIFICATION) {
-    Services.obs.addObserver(this, ONVERIFIED_NOTIFICATION, false);
-    Services.obs.addObserver(this, ONLOGIN_NOTIFICATION, false);
-    Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION, false);
-  }
-
-  // Maintain interface parity with Identity.jsm and MinimalIdentity.jsm
-  this.RP = this;
-
-  this._rpFlows = new Map();
-
-  // Enable us to mock FxAccountsManager service in testing
-  this.fxAccountsManager = FxAccountsManager;
-}
-
-FxAccountsService.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case null:
-        // Guard against matching null ON*_NOTIFICATION
-        break;
-      case ONVERIFIED_NOTIFICATION:
-        log.debug("Received " + ONVERIFIED_NOTIFICATION + "; firing request()s");
-        for (let [rpId,] of this._rpFlows) {
-          this.request(rpId);
-        }
-        break;
-      case ONLOGIN_NOTIFICATION:
-        log.debug("Received " + ONLOGIN_NOTIFICATION + "; doLogin()s fired");
-        for (let [rpId,] of this._rpFlows) {
-          this.request(rpId);
-        }
-        break;
-      case ONLOGOUT_NOTIFICATION:
-        log.debug("Received " + ONLOGOUT_NOTIFICATION + "; doLogout()s fired");
-        for (let [rpId,] of this._rpFlows) {
-          this.doLogout(rpId);
-        }
-        break;
-      case "quit-application-granted":
-        Services.obs.removeObserver(this, "quit-application-granted");
-        if (ONVERIFIED_NOTIFICATION) {
-          Services.obs.removeObserver(this, ONVERIFIED_NOTIFICATION);
-          Services.obs.removeObserver(this, ONLOGIN_NOTIFICATION);
-          Services.obs.removeObserver(this, ONLOGOUT_NOTIFICATION);
-        }
-        break;
-    }
-  },
-
-  cleanupRPRequest: function(aRp) {
-    aRp.pendingRequest = false;
-    this._rpFlows.set(aRp.id, aRp);
-  },
-
-  /**
-   * Register a listener for a given windowID as a result of a call to
-   * navigator.id.watch().
-   *
-   * @param aRPCaller
-   *        (Object)  an object that represents the caller document, and
-   *                  is expected to have properties:
-   *                  - id (unique, e.g. uuid)
-   *                  - origin (string)
-   *
-   *                  and a bunch of callbacks
-   *                  - doReady()
-   *                  - doLogin()
-   *                  - doLogout()
-   *                  - doError()
-   *                  - doCancel()
-   *
-   */
-  watch: function watch(aRpCaller) {
-    this._rpFlows.set(aRpCaller.id, aRpCaller);
-    log.debug("watch: " + aRpCaller.id);
-    log.debug("Current rp flows: " + this._rpFlows.size);
-
-    // Log the user in, if possible, and then call ready().
-    let runnable = {
-      run: () => {
-        this.fxAccountsManager.getAssertion(aRpCaller.audience,
-                                            aRpCaller.principal,
-                                            { silent:true }).then(
-          data => {
-            if (data) {
-              this.doLogin(aRpCaller.id, data);
-            } else {
-              this.doLogout(aRpCaller.id);
-            }
-            this.doReady(aRpCaller.id);
-          },
-          error => {
-            log.error("get silent assertion failed: " + JSON.stringify(error));
-            this.doError(aRpCaller.id, error);
-          }
-        );
-      }
-    };
-    Services.tm.currentThread.dispatch(runnable,
-                                       Ci.nsIThread.DISPATCH_NORMAL);
-  },
-
-  /**
-   * Delete the flow when the screen is unloaded
-   */
-  unwatch: function(aRpCallerId, aTargetMM) {
-    log.debug("unwatching: " + aRpCallerId);
-    this._rpFlows.delete(aRpCallerId);
-  },
-
-  /**
-   * Initiate a login with user interaction as a result of a call to
-   * navigator.id.request().
-   *
-   * @param aRPId
-   *        (integer) the id of the doc object obtained in .watch()
-   *
-   * @param aOptions
-   *        (Object) options including privacyPolicy, termsOfService
-   */
-  request: function request(aRPId, aOptions) {
-    aOptions = aOptions || {};
-    let rp = this._rpFlows.get(aRPId);
-    if (!rp) {
-      log.error("request() called before watch()");
-      return;
-    }
-
-    // We check if we already have a pending request for this RP and in that
-    // case we just bail out. We don't want duplicated onlogin or oncancel
-    // events.
-    if (rp.pendingRequest) {
-      log.debug("request() already called");
-      return;
-    }
-
-    // Otherwise, we set the RP flow with the pending request flag.
-    rp.pendingRequest = true;
-    this._rpFlows.set(rp.id, rp);
-
-    let options = makeMessageObject(rp);
-    objectCopy(aOptions, options);
-
-    log.debug("get assertion for " + rp.audience);
-
-    this.fxAccountsManager.getAssertion(rp.audience, rp.principal, options)
-    .then(
-      data => {
-        log.debug("got assertion for " + rp.audience + ": " + data);
-        this.doLogin(aRPId, data);
-      },
-      error => {
-        log.debug("get assertion failed: " + JSON.stringify(error));
-        // Cancellation is passed through an error channel; here we reroute.
-        if ((error.error && (error.error.details == "DIALOG_CLOSED_BY_USER")) ||
-            (error.details == "DIALOG_CLOSED_BY_USER")) {
-          return this.doCancel(aRPId);
-        }
-        this.doError(aRPId, error);
-      }
-    )
-    .then(
-      () => {
-        this.cleanupRPRequest(rp);
-      }
-    )
-    .catch(
-      () => {
-        this.cleanupRPRequest(rp);
-      }
-    );
-  },
-
-  /**
-   * Invoked when a user wishes to logout of a site (for instance, when clicking
-   * on an in-content logout button).
-   *
-   * @param aRpCallerId
-   *        (integer)  the id of the doc object obtained in .watch()
-   *
-   */
-  logout: function logout(aRpCallerId) {
-    // XXX Bug 945363 - Resolve the SSO story for FXA and implement
-    // logout accordingly.
-    //
-    // For now, it makes no sense to logout from a specific RP in
-    // Firefox Accounts, so just directly call the logout callback.
-    if (!this._rpFlows.has(aRpCallerId)) {
-      log.error("logout() called before watch()");
-      return;
-    }
-
-    // Call logout() on the next tick
-    let runnable = {
-      run: () => {
-        this.fxAccountsManager.signOut().then(() => {
-          this.doLogout(aRpCallerId);
-        });
-      }
-    };
-    Services.tm.currentThread.dispatch(runnable,
-                                       Ci.nsIThread.DISPATCH_NORMAL);
-  },
-
-  childProcessShutdown: function childProcessShutdown(messageManager) {
-    for (let [key,] of this._rpFlows) {
-      if (this._rpFlows.get(key)._mm === messageManager) {
-        this._rpFlows.delete(key);
-      }
-    }
-  },
-
-  doLogin: function doLogin(aRpCallerId, aAssertion) {
-    let rp = this._rpFlows.get(aRpCallerId);
-    if (!rp) {
-      log.warn("doLogin found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doLogin(aAssertion);
-  },
-
-  doLogout: function doLogout(aRpCallerId) {
-    let rp = this._rpFlows.get(aRpCallerId);
-    if (!rp) {
-      log.warn("doLogout found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doLogout();
-  },
-
-  doReady: function doReady(aRpCallerId) {
-    let rp = this._rpFlows.get(aRpCallerId);
-    if (!rp) {
-      log.warn("doReady found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doReady();
-  },
-
-  doCancel: function doCancel(aRpCallerId) {
-    let rp = this._rpFlows.get(aRpCallerId);
-    if (!rp) {
-      log.warn("doCancel found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doCancel();
-  },
-
-  doError: function doError(aRpCallerId, aError) {
-    let rp = this._rpFlows.get(aRpCallerId);
-    if (!rp) {
-      log.warn("doError found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doError(aError);
-  }
-};
-
-this.FirefoxAccounts = new FxAccountsService();
-
deleted file mode 100644
--- a/toolkit/identity/Identity.jsm
+++ /dev/null
@@ -1,308 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["IdentityService"];
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-Cu.import("resource://gre/modules/identity/IdentityStore.jsm");
-Cu.import("resource://gre/modules/identity/RelyingParty.jsm");
-Cu.import("resource://gre/modules/identity/IdentityProvider.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["core"].concat(aMessageArgs));
-}
-function reportError(...aMessageArgs) {
-  Logger.reportError.apply(Logger, ["core"].concat(aMessageArgs));
-}
-
-function IDService() {
-  Services.obs.addObserver(this, "quit-application-granted", false);
-  Services.obs.addObserver(this, "identity-auth-complete", false);
-
-  this._store = IdentityStore;
-  this.RP = RelyingParty;
-  this.IDP = IdentityProvider;
-}
-
-IDService.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "quit-application-granted":
-        Services.obs.removeObserver(this, "quit-application-granted");
-        this.shutdown();
-        break;
-      case "identity-auth-complete":
-        if (!aSubject || !aSubject.wrappedJSObject)
-          break;
-        let subject = aSubject.wrappedJSObject;
-        log("Auth complete:", aSubject.wrappedJSObject);
-        // We have authenticated in order to provision an identity.
-        // So try again.
-        this.selectIdentity(subject.rpId, subject.identity);
-        break;
-    }
-  },
-
-  reset: function reset() {
-    // Explicitly call reset() on our RP and IDP classes.
-    // This is here to make testing easier.  When the
-    // quit-application-granted signal is emitted, reset() will be
-    // called here, on RP, on IDP, and on the store.  So you don't
-    // need to use this :)
-    this._store.reset();
-    this.RP.reset();
-    this.IDP.reset();
-  },
-
-  shutdown: function shutdown() {
-    log("shutdown");
-    Services.obs.removeObserver(this, "identity-auth-complete");
-    // try to prevent abort/crash during shutdown of mochitest-browser2...
-    try {
-      Services.obs.removeObserver(this, "quit-application-granted");
-    } catch (e) {}
-  },
-
-  /**
-   * Parse an email into username and domain if it is valid, else return null
-   */
-  parseEmail: function parseEmail(email) {
-    var match = email.match(/^([^@]+)@([^@^/]+.[a-z]+)$/);
-    if (match) {
-      return {
-        username: match[1],
-        domain: match[2]
-      };
-    }
-    return null;
-  },
-
-  /**
-   * The UX wants to add a new identity
-   * often followed by selectIdentity()
-   *
-   * @param aIdentity
-   *        (string) the email chosen for login
-   */
-  addIdentity: function addIdentity(aIdentity) {
-    if (this._store.fetchIdentity(aIdentity) === null) {
-      this._store.addIdentity(aIdentity, null, null);
-    }
-  },
-
-  /**
-   * The UX comes back and calls selectIdentity once the user has picked
-   * an identity.
-   *
-   * @param aRPId
-   *        (integer) the id of the doc object obtained in .watch() and
-   *                  passed to the UX component.
-   *
-   * @param aIdentity
-   *        (string) the email chosen for login
-   */
-  selectIdentity: function selectIdentity(aRPId, aIdentity) {
-    log("selectIdentity: RP id:", aRPId, "identity:", aIdentity);
-
-    // Get the RP that was stored when watch() was invoked.
-    let rp = this.RP._rpFlows[aRPId];
-    if (!rp) {
-      reportError("selectIdentity", "Invalid RP id: ", aRPId);
-      return;
-    }
-
-    // It's possible that we are in the process of provisioning an
-    // identity.
-    let provId = rp.provId;
-
-    let rpLoginOptions = {
-      loggedInUser: aIdentity,
-      origin: rp.origin
-    };
-    log("selectIdentity: provId:", provId, "origin:", rp.origin);
-
-    // Once we have a cert, and once the user is authenticated with the
-    // IdP, we can generate an assertion and deliver it to the doc.
-    let self = this;
-    this.RP._generateAssertion(rp.origin, aIdentity, function hadReadyAssertion(err, assertion) {
-      if (!err && assertion) {
-        self.RP._doLogin(rp, rpLoginOptions, assertion);
-        return;
-
-      }
-      // Need to provision an identity first.  Begin by discovering
-      // the user's IdP.
-      self._discoverIdentityProvider(aIdentity, function gotIDP(err, idpParams) {
-        if (err) {
-          rp.doError(err);
-          return;
-        }
-
-        // The idpParams tell us where to go to provision and authenticate
-        // the identity.
-        self.IDP._provisionIdentity(aIdentity, idpParams, provId, function gotID(err, aProvId) {
-
-          // Provision identity may have created a new provision flow
-          // for us.  To make it easier to relate provision flows with
-          // RP callers, we cross index the two here.
-          rp.provId = aProvId;
-          self.IDP._provisionFlows[aProvId].rpId = aRPId;
-
-          // At this point, we already have a cert.  If the user is also
-          // already authenticated with the IdP, then we can try again
-          // to generate an assertion and login.
-          if (err) {
-            // We are not authenticated.  If we have already tried to
-            // authenticate and failed, then this is a "hard fail" and
-            // we give up.  Otherwise we try to authenticate with the
-            // IdP.
-
-            if (self.IDP._provisionFlows[aProvId].didAuthentication) {
-              self.IDP._cleanUpProvisionFlow(aProvId);
-              self.RP._cleanUpProvisionFlow(aRPId, aProvId);
-              log("ERROR: selectIdentity: authentication hard fail");
-              rp.doError("Authentication fail.");
-              return;
-            }
-            // Try to authenticate with the IdP.  Note that we do
-            // not clean up the provision flow here.  We will continue
-            // to use it.
-            self.IDP._doAuthentication(aProvId, idpParams);
-            return;
-          }
-
-          // Provisioning flows end when a certificate has been registered.
-          // Thus IdentityProvider's registerCertificate() cleans up the
-          // current provisioning flow.  We only do this here on error.
-          self.RP._generateAssertion(rp.origin, aIdentity, function gotAssertion(err, assertion) {
-            if (err) {
-              rp.doError(err);
-              return;
-            }
-            self.RP._doLogin(rp, rpLoginOptions, assertion);
-            self.RP._cleanUpProvisionFlow(aRPId, aProvId);
-          });
-        });
-      });
-    });
-  },
-
-  // methods for chrome and add-ons
-
-  /**
-   * Discover the IdP for an identity
-   *
-   * @param aIdentity
-   *        (string) the email we're logging in with
-   *
-   * @param aCallback
-   *        (function) callback to invoke on completion
-   *                   with first-positional parameter the error.
-   */
-  _discoverIdentityProvider: function _discoverIdentityProvider(aIdentity, aCallback) {
-    // XXX bug 767610 - validate email address call
-    // When that is available, we can remove this custom parser
-    var parsedEmail = this.parseEmail(aIdentity);
-    if (parsedEmail === null) {
-      aCallback("Could not parse email: " + aIdentity);
-      return;
-    }
-    log("_discoverIdentityProvider: identity:", aIdentity, "domain:", parsedEmail.domain);
-
-    this._fetchWellKnownFile(parsedEmail.domain, function fetchedWellKnown(err, idpParams) {
-      // idpParams includes the pk, authorization url, and
-      // provisioning url.
-
-      // XXX bug 769861 follow any authority delegations
-      // if no well-known at any point in the delegation
-      // fall back to browserid.org as IdP
-      return aCallback(err, idpParams);
-    });
-  },
-
-  /**
-   * Fetch the well-known file from the domain.
-   *
-   * @param aDomain
-   *
-   * @param aScheme
-   *        (string) (optional) Protocol to use.  Default is https.
-   *                 This is necessary because we are unable to test
-   *                 https.
-   *
-   * @param aCallback
-   *
-   */
-  _fetchWellKnownFile: function _fetchWellKnownFile(aDomain, aCallback, aScheme = "https") {
-    // XXX bug 769854 make tests https and remove aScheme option
-    let url = aScheme + "://" + aDomain + "/.well-known/browserid";
-    log("_fetchWellKnownFile:", url);
-
-    // this appears to be a more successful way to get at xmlhttprequest (which supposedly will close with a window
-    let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
-                .createInstance(Ci.nsIXMLHttpRequest);
-
-    // XXX bug 769865 gracefully handle being off-line
-    // XXX bug 769866 decide on how to handle redirects
-    req.open("GET", url, true);
-    req.responseType = "json";
-    req.mozBackgroundRequest = true;
-    req.onload = function _fetchWellKnownFile_onload() {
-      if (req.status < 200 || req.status >= 400) {
-        log("_fetchWellKnownFile", url, ": server returned status:", req.status);
-        return aCallback("Error");
-      }
-      try {
-        let idpParams = req.response;
-
-        // Verify that the IdP returned a valid configuration
-        if (!(idpParams.provisioning &&
-            idpParams.authentication &&
-            idpParams["public-key"])) {
-          let errStr = "Invalid well-known file from: " + aDomain;
-          log("_fetchWellKnownFile:", errStr);
-          return aCallback(errStr);
-        }
-
-        let callbackObj = {
-          domain: aDomain,
-          idpParams,
-        };
-        log("_fetchWellKnownFile result: ", callbackObj);
-        // Yay.  Valid IdP configuration for the domain.
-        return aCallback(null, callbackObj);
-
-      } catch (err) {
-        reportError("_fetchWellKnownFile", "Bad configuration from", aDomain, err);
-        return aCallback(err.toString());
-      }
-    };
-    req.onerror = function _fetchWellKnownFile_onerror() {
-      log("_fetchWellKnownFile", "ERROR:", req.status, req.statusText);
-      log("ERROR: _fetchWellKnownFile:", err);
-      return aCallback("Error");
-    };
-    req.send(null);
-  },
-
-};
-
-this.IdentityService = new IDService();
deleted file mode 100644
--- a/toolkit/identity/IdentityProvider.jsm
+++ /dev/null
@@ -1,495 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-"use strict";
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-Cu.import("resource://gre/modules/identity/Sandbox.jsm");
-
-this.EXPORTED_SYMBOLS = ["IdentityProvider"];
-const FALLBACK_PROVIDER = "browserid.org";
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["IDP"].concat(aMessageArgs));
-}
-function reportError(...aMessageArgs) {
-  Logger.reportError.apply(Logger, ["IDP"].concat(aMessageArgs));
-}
-
-
-function IdentityProviderService() {
-  XPCOMUtils.defineLazyModuleGetter(this,
-                                    "_store",
-                                    "resource://gre/modules/identity/IdentityStore.jsm",
-                                    "IdentityStore");
-
-  this.reset();
-}
-
-IdentityProviderService.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-  _sandboxConfigured: false,
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "quit-application-granted":
-        Services.obs.removeObserver(this, "quit-application-granted");
-        this.shutdown();
-        break;
-    }
-  },
-
-  reset: function IDP_reset() {
-    // Clear the provisioning flows.  Provision flows contain an
-    // identity, idpParams (how to reach the IdP to provision and
-    // authenticate), a callback (a completion callback for when things
-    // are done), and a provisioningFrame (which is the provisioning
-    // sandbox).  Additionally, two callbacks will be attached:
-    // beginProvisioningCallback and genKeyPairCallback.
-    this._provisionFlows = {};
-
-    // Clear the authentication flows.  Authentication flows attach
-    // to provision flows.  In the process of provisioning an id, it
-    // may be necessary to authenticate with an IdP.  The authentication
-    // flow maintains the state of that authentication process.
-    this._authenticationFlows = {};
-  },
-
-  getProvisionFlow: function getProvisionFlow(aProvId, aErrBack) {
-    let provFlow = this._provisionFlows[aProvId];
-    if (provFlow) {
-      return provFlow;
-    }
-
-    let err = "No provisioning flow found with id " + aProvId;
-    log("ERROR:", err);
-    if (typeof aErrBack === "function") {
-      aErrBack(err);
-    }
-
-    return undefined;
-  },
-
-  shutdown: function RP_shutdown() {
-    this.reset();
-
-    if (this._sandboxConfigured) {
-      // Tear down message manager listening on the hidden window
-      Cu.import("resource://gre/modules/DOMIdentity.jsm");
-      DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, false);
-      this._sandboxConfigured = false;
-    }
-
-    Services.obs.removeObserver(this, "quit-application-granted");
-  },
-
-  get securityLevel() {
-    return 1;
-  },
-
-  get certDuration() {
-    switch (this.securityLevel) {
-      default:
-        return 3600;
-    }
-  },
-
-  /**
-   * Provision an Identity
-   *
-   * @param aIdentity
-   *        (string) the email we're logging in with
-   *
-   * @param aIDPParams
-   *        (object) parameters of the IdP
-   *
-   * @param aCallback
-   *        (function) callback to invoke on completion
-   *                   with first-positional parameter the error.
-   */
-  _provisionIdentity: function _provisionIdentity(aIdentity, aIDPParams, aProvId, aCallback) {
-    let provPath = aIDPParams.idpParams.provisioning;
-    let url = Services.io.newURI("https://" + aIDPParams.domain).resolve(provPath);
-    log("_provisionIdentity: identity:", aIdentity, "url:", url);
-
-    // If aProvId is not null, then we already have a flow
-    // with a sandbox.  Otherwise, get a sandbox and create a
-    // new provision flow.
-
-    if (aProvId) {
-      // Re-use an existing sandbox
-      log("_provisionIdentity: re-using sandbox in provisioning flow with id:", aProvId);
-      this._provisionFlows[aProvId].provisioningSandbox.reload();
-
-    } else {
-      this._createProvisioningSandbox(url, function createdSandbox(aSandbox) {
-        // create a provisioning flow, using the sandbox id, and
-        // stash callback associated with this provisioning workflow.
-
-        let provId = aSandbox.id;
-        this._provisionFlows[provId] = {
-          identity: aIdentity,
-          idpParams: aIDPParams,
-          securityLevel: this.securityLevel,
-          provisioningSandbox: aSandbox,
-          callback: function doCallback(aErr) {
-            aCallback(aErr, provId);
-          },
-        };
-
-        log("_provisionIdentity: Created sandbox and provisioning flow with id:", provId);
-        // XXX bug 769862 - provisioning flow should timeout after N seconds
-
-      }.bind(this));
-    }
-  },
-
-  // DOM Methods
-  /**
-   * the provisioning iframe sandbox has called navigator.id.beginProvisioning()
-   *
-   * @param aCaller
-   *        (object)  the iframe sandbox caller with all callbacks and
-   *                  other information.  Callbacks include:
-   *                  - doBeginProvisioningCallback(id, duration_s)
-   *                  - doGenKeyPairCallback(pk)
-   */
-  beginProvisioning: function beginProvisioning(aCaller) {
-    log("beginProvisioning:", aCaller.id);
-
-    // Expect a flow for this caller already to be underway.
-    let provFlow = this.getProvisionFlow(aCaller.id, aCaller.doError);
-
-    // keep the caller object around
-    provFlow.caller = aCaller;
-
-    let identity = provFlow.identity;
-
-    // Determine recommended length of cert.
-    let duration = this.certDuration;
-
-    // Make a record that we have begun provisioning.  This is required
-    // for genKeyPair.
-    provFlow.didBeginProvisioning = true;
-
-    // Let the sandbox know to invoke the callback to beginProvisioning with
-    // the identity and cert length.
-    return aCaller.doBeginProvisioningCallback(identity, duration);
-  },
-
-  /**
-   * the provisioning iframe sandbox has called
-   * navigator.id.raiseProvisioningFailure()
-   *
-   * @param aProvId
-   *        (int)  the identifier of the provisioning flow tied to that sandbox
-   * @param aReason
-   */
-  raiseProvisioningFailure: function raiseProvisioningFailure(aProvId, aReason) {
-    reportError("Provisioning failure", aReason);
-
-    // look up the provisioning caller and its callback
-    let provFlow = this.getProvisionFlow(aProvId);
-
-    // Sandbox is deleted in _cleanUpProvisionFlow in case we re-use it.
-
-    // This may be either a "soft" or "hard" fail.  If it's a
-    // soft fail, we'll flow through setAuthenticationFlow, where
-    // the provision flow data will be copied into a new auth
-    // flow.  If it's a hard fail, then the callback will be
-    // responsible for cleaning up the now defunct provision flow.
-
-    // invoke the callback with an error.
-    provFlow.callback(aReason);
-  },
-
-  /**
-   * When navigator.id.genKeyPair is called from provisioning iframe sandbox.
-   * Generates a keypair for the current user being provisioned.
-   *
-   * @param aProvId
-   *        (int)  the identifier of the provisioning caller tied to that sandbox
-   *
-   * It is an error to call genKeypair without receiving the callback for
-   * the beginProvisioning() call first.
-   */
-  genKeyPair: function genKeyPair(aProvId) {
-    // Look up the provisioning caller and make sure it's valid.
-    let provFlow = this.getProvisionFlow(aProvId);
-
-    if (!provFlow.didBeginProvisioning) {
-      let errStr = "ERROR: genKeyPair called before beginProvisioning";
-      log(errStr);
-      provFlow.callback(errStr);
-      return;
-    }
-
-    // Ok generate a keypair
-    jwcrypto.generateKeyPair(jwcrypto.ALGORITHMS.DS160, function gkpCb(err, kp) {
-      log("in gkp callback");
-      if (err) {
-        log("ERROR: genKeyPair:", err);
-        provFlow.callback(err);
-        return;
-      }
-
-      provFlow.kp = kp;
-
-      // Serialize the publicKey of the keypair and send it back to the
-      // sandbox.
-      log("genKeyPair: generated keypair for provisioning flow with id:", aProvId);
-      provFlow.caller.doGenKeyPairCallback(provFlow.kp.serializedPublicKey);
-    });
-  },
-
-  /**
-   * When navigator.id.registerCertificate is called from provisioning iframe
-   * sandbox.
-   *
-   * Sets the certificate for the user for which a certificate was requested
-   * via a preceding call to beginProvisioning (and genKeypair).
-   *
-   * @param aProvId
-   *        (integer) the identifier of the provisioning caller tied to that
-   *                  sandbox
-   *
-   * @param aCert
-   *        (String)  A JWT representing the signed certificate for the user
-   *                  being provisioned, provided by the IdP.
-   */
-  registerCertificate: function registerCertificate(aProvId, aCert) {
-    log("registerCertificate:", aProvId, aCert);
-
-    // look up provisioning caller, make sure it's valid.
-    let provFlow = this.getProvisionFlow(aProvId);
-
-    if (!provFlow.caller) {
-      reportError("registerCertificate", "No provision flow or caller");
-      return;
-    }
-    if (!provFlow.kp) {
-      let errStr = "Cannot register a certificate without a keypair";
-      reportError("registerCertificate", errStr);
-      provFlow.callback(errStr);
-      return;
-    }
-
-    // store the keypair and certificate just provided in IDStore.
-    this._store.addIdentity(provFlow.identity, provFlow.kp, aCert);
-
-    // Great success!
-    provFlow.callback(null);
-
-    // Clean up the flow.
-    this._cleanUpProvisionFlow(aProvId);
-  },
-
-  /**
-   * Begin the authentication process with an IdP
-   *
-   * @param aProvId
-   *        (int) the identifier of the provisioning flow which failed
-   *
-   * @param aCallback
-   *        (function) to invoke upon completion, with
-   *                   first-positional-param error.
-   */
-  _doAuthentication: function _doAuthentication(aProvId, aIDPParams) {
-    log("_doAuthentication: provId:", aProvId, "idpParams:", aIDPParams);
-    // create an authentication caller and its identifier AuthId
-    // stash aIdentity, idpparams, and callback in it.
-
-    // extract authentication URL from idpParams
-    let authPath = aIDPParams.idpParams.authentication;
-    let authURI = Services.io.newURI("https://" + aIDPParams.domain).resolve(authPath);
-
-    // beginAuthenticationFlow causes the "identity-auth" topic to be
-    // observed.  Since it's sending a notification to the DOM, there's
-    // no callback.  We wait for the DOM to trigger the next phase of
-    // provisioning.
-    this._beginAuthenticationFlow(aProvId, authURI);
-
-    // either we bind the AuthID to the sandbox ourselves, or UX does that,
-    // in which case we need to tell UX the AuthId.
-    // Currently, the UX creates the UI and gets the AuthId from the window
-    // and sets is with setAuthenticationFlow
-  },
-
-  /**
-   * The authentication frame has called navigator.id.beginAuthentication
-   *
-   * IMPORTANT: the aCaller is *always* non-null, even if this is called from
-   * a regular content page. We have to make sure, on every DOM call, that
-   * aCaller is an expected authentication-flow identifier. If not, we throw
-   * an error or something.
-   *
-   * @param aCaller
-   *        (object)  the authentication caller
-   *
-   */
-  beginAuthentication: function beginAuthentication(aCaller) {
-    log("beginAuthentication: caller id:", aCaller.id);
-
-    // Begin the authentication flow after having concluded a provisioning
-    // flow.  The aCaller that the DOM gives us will have the same ID as
-    // the provisioning flow we just concluded.  (see setAuthenticationFlow)
-    let authFlow = this._authenticationFlows[aCaller.id];
-    if (!authFlow) {
-      return aCaller.doError("beginAuthentication: no flow for caller id", aCaller.id);
-    }
-
-    authFlow.caller = aCaller;
-
-    let identity = this._provisionFlows[authFlow.provId].identity;
-
-    // tell the UI to start the authentication process
-    log("beginAuthentication: authFlow:", aCaller.id, "identity:", identity);
-    return authFlow.caller.doBeginAuthenticationCallback(identity);
-  },
-
-  /**
-   * The auth frame has called navigator.id.completeAuthentication
-   *
-   * @param aAuthId
-   *        (int)  the identifier of the authentication caller tied to that sandbox
-   *
-   */
-  completeAuthentication: function completeAuthentication(aAuthId) {
-    log("completeAuthentication:", aAuthId);
-
-    // look up the AuthId caller, and get its callback.
-    let authFlow = this._authenticationFlows[aAuthId];
-    if (!authFlow) {
-      reportError("completeAuthentication", "No auth flow with id", aAuthId);
-      return;
-    }
-    let provId = authFlow.provId;
-
-    // delete caller
-    delete authFlow["caller"];
-    delete this._authenticationFlows[aAuthId];
-
-    let provFlow = this.getProvisionFlow(provId);
-    provFlow.didAuthentication = true;
-    let subject = {
-      rpId: provFlow.rpId,
-      identity: provFlow.identity,
-    };
-    Services.obs.notifyObservers({ wrappedJSObject: subject }, "identity-auth-complete", aAuthId);
-  },
-
-  /**
-   * The auth frame has called navigator.id.cancelAuthentication
-   *
-   * @param aAuthId
-   *        (int)  the identifier of the authentication caller
-   *
-   */
-  cancelAuthentication: function cancelAuthentication(aAuthId) {
-    log("cancelAuthentication:", aAuthId);
-
-    // look up the AuthId caller, and get its callback.
-    let authFlow = this._authenticationFlows[aAuthId];
-    if (!authFlow) {
-      reportError("cancelAuthentication", "No auth flow with id:", aAuthId);
-      return;
-    }
-    let provId = authFlow.provId;
-
-    // delete caller
-    delete authFlow["caller"];
-    delete this._authenticationFlows[aAuthId];
-
-    let provFlow = this.getProvisionFlow(provId);
-    provFlow.didAuthentication = true;
-    Services.obs.notifyObservers(null, "identity-auth-complete", aAuthId);
-
-    // invoke callback with ERROR.
-    let errStr = "Authentication canceled by IDP";
-    log("ERROR: cancelAuthentication:", errStr);
-    provFlow.callback(errStr);
-  },
-
-  /**
-   * Called by the UI to set the ID and caller for the authentication flow after it gets its ID
-   */
-  setAuthenticationFlow(aAuthId, aProvId) {
-    // this is the transition point between the two flows,
-    // provision and authenticate.  We tell the auth flow which
-    // provisioning flow it is started from.
-    log("setAuthenticationFlow: authId:", aAuthId, "provId:", aProvId);
-    this._authenticationFlows[aAuthId] = { provId: aProvId };
-    this._provisionFlows[aProvId].authId = aAuthId;
-  },
-
-  /**
-   * Load the provisioning URL in a hidden frame to start the provisioning
-   * process.
-   */
-  _createProvisioningSandbox: function _createProvisioningSandbox(aURL, aCallback) {
-    log("_createProvisioningSandbox:", aURL);
-
-    if (!this._sandboxConfigured) {
-      // Configure message manager listening on the hidden window
-      Cu.import("resource://gre/modules/DOMIdentity.jsm");
-      DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, true);
-      this._sandboxConfigured = true;
-    }
-
-    new Sandbox(aURL, aCallback);
-  },
-
-  /**
-   * Load the authentication UI to start the authentication process.
-   */
-  _beginAuthenticationFlow: function _beginAuthenticationFlow(aProvId, aURL) {
-    log("_beginAuthenticationFlow:", aProvId, aURL);
-    let propBag = {provId: aProvId};
-
-    Services.obs.notifyObservers({wrappedJSObject:propBag}, "identity-auth", aURL);
-  },
-
-  /**
-   * Clean up a provision flow and the authentication flow and sandbox
-   * that may be attached to it.
-   */
-  _cleanUpProvisionFlow: function _cleanUpProvisionFlow(aProvId) {
-    log("_cleanUpProvisionFlow:", aProvId);
-    let prov = this._provisionFlows[aProvId];
-
-    // Clean up the sandbox, if there is one.
-    if (prov.provisioningSandbox) {
-      let sandbox = this._provisionFlows[aProvId]["provisioningSandbox"];
-      if (sandbox.free) {
-        log("_cleanUpProvisionFlow: freeing sandbox");
-        sandbox.free();
-      }
-      delete this._provisionFlows[aProvId]["provisioningSandbox"];
-    }
-
-    // Clean up a related authentication flow, if there is one.
-    if (this._authenticationFlows[prov.authId]) {
-      delete this._authenticationFlows[prov.authId];
-    }
-
-    // Finally delete the provision flow
-    delete this._provisionFlows[aProvId];
-  }
-
-};
-
-this.IdentityProvider = new IdentityProviderService();
deleted file mode 100644
--- a/toolkit/identity/IdentityStore.jsm
+++ /dev/null
@@ -1,97 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-"use strict";
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-this.EXPORTED_SYMBOLS = ["IdentityStore"];
-
-// the data store for IDService
-// written as a separate thing so it can easily be mocked
-function IDServiceStore() {
-  this.reset();
-}
-
-// Note: eventually these methods may be async, but we haven no need for this
-// for now, since we're not storing to disk.
-IDServiceStore.prototype = {
-  addIdentity: function addIdentity(aEmail, aKeyPair, aCert) {
-    this._identities[aEmail] = {keyPair: aKeyPair, cert: aCert};
-  },
-  fetchIdentity: function fetchIdentity(aEmail) {
-    return aEmail in this._identities ? this._identities[aEmail] : null;
-  },
-  removeIdentity: function removeIdentity(aEmail) {
-    let data = this._identities[aEmail];
-    delete this._identities[aEmail];
-    return data;
-  },
-  getIdentities: function getIdentities() {
-    // XXX - should clone?
-    return this._identities;
-  },
-  clearCert: function clearCert(aEmail) {
-    // XXX - should remove key from store?
-    this._identities[aEmail].cert = null;
-    this._identities[aEmail].keyPair = null;
-  },
-
-  /**
-   * set the login state for a given origin
-   *
-   * @param aOrigin
-   *        (string) a web origin
-   *
-   * @param aState
-   *        (boolean) whether or not the user is logged in
-   *
-   * @param aEmail
-   *        (email) the email address the user is logged in with,
-   *                or, if not logged in, the default email for that origin.
-   */
-  setLoginState: function setLoginState(aOrigin, aState, aEmail) {
-    if (aState && !aEmail) {
-      throw "isLoggedIn cannot be set to true without an email";
-    }
-    return this._loginStates[aOrigin] = {isLoggedIn: aState, email: aEmail};
-  },
-  getLoginState: function getLoginState(aOrigin) {
-    return aOrigin in this._loginStates ? this._loginStates[aOrigin] : null;
-  },
-  clearLoginState: function clearLoginState(aOrigin) {
-    delete this._loginStates[aOrigin];
-  },
-
-  reset: function Store_reset() {
-    // _identities associates emails with keypairs and certificates
-    this._identities = {};
-
-    // _loginStates associates. remote origins with a login status and
-    // the email the user has chosen as his or her identity when logging
-    // into that origin.
-    this._loginStates = {};
-  },
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "quit-application-granted":
-        Services.obs.removeObserver(this, "quit-application-granted");
-        this.reset();
-        break;
-    }
-  },
-};
-
-this.IdentityStore = new IDServiceStore();
deleted file mode 100644
--- a/toolkit/identity/IdentityUtils.jsm
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-// functions common to Identity.jsm and MinimalIdentity.jsm
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
-  "checkDeprecated",
-  "checkRenamed",
-  "getRandomId",
-  "objectCopy",
-  "makeMessageObject",
-];
-
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
-                                   "@mozilla.org/uuid-generator;1",
-                                   "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Logger",
-                                  "resource://gre/modules/identity/LogUtils.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["Identity"].concat(aMessageArgs));
-}
-
-function defined(item) {
-  return typeof item !== "undefined";
-}
-
-var checkDeprecated = this.checkDeprecated = function checkDeprecated(aOptions, aField) {
-  if (defined(aOptions[aField])) {
-    log("WARNING: field is deprecated:", aField);
-    return true;
-  }
-  return false;
-};
-
-this.checkRenamed = function checkRenamed(aOptions, aOldName, aNewName) {
-  if (defined(aOptions[aOldName]) &&
-      defined(aOptions[aNewName])) {
-    let err = "You cannot provide both " + aOldName + " and " + aNewName;
-    Logger.reportError(err);
-    throw new Error(err);
-  }
-
-  if (checkDeprecated(aOptions, aOldName)) {
-    aOptions[aNewName] = aOptions[aOldName];
-    delete aOptions[aOldName];
-  }
-};
-
-this.getRandomId = function getRandomId() {
-  return uuidgen.generateUUID().toString();
-};
-
-/*
- * copy source object into target, excluding private properties
- * (those whose names begin with an underscore)
- */
-this.objectCopy = function objectCopy(source, target) {
-  let desc;
-  Object.getOwnPropertyNames(source).forEach(function(name) {
-    if (name[0] !== "_") {
-      desc = Object.getOwnPropertyDescriptor(source, name);
-      Object.defineProperty(target, name, desc);
-    }
-  });
-};
-
-this.makeMessageObject = function makeMessageObject(aRpCaller) {
-  let options = {};
-
-  options.id = aRpCaller.id;
-  options.origin = aRpCaller.origin;
-
-  // Backwards compatibility with Persona beta:
-  // loggedInUser can be undefined, null, or a string
-  options.loggedInUser = aRpCaller.loggedInUser;
-
-  // Special flag for internal calls for Persona in b2g
-  options._internal = aRpCaller._internal;
-
-  Object.keys(aRpCaller).forEach(function(option) {
-    // Duplicate the callerobject, scrubbing out functions and other
-    // internal variables (like _mm, the message manager object)
-    if (!Object.hasOwnProperty(this, option)
-        && option[0] !== "_"
-        && typeof aRpCaller[option] !== "function") {
-      options[option] = aRpCaller[option];
-    }
-  });
-
-  // check validity of message structure
-  if ((typeof options.id === "undefined") ||
-      (typeof options.origin === "undefined")) {
-    let err = "id and origin required in relying-party message: " + JSON.stringify(options);
-    reportError(err);
-    throw new Error(err);
-  }
-
-  return options;
-}
-
deleted file mode 100644
--- a/toolkit/identity/MinimalIdentity.jsm
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-/*
- * This alternate implementation of IdentityService provides just the
- * channels for navigator.id, leaving the certificate storage to a
- * server-provided app.
- *
- * On b2g, the messages identity-controller-watch, -request, and
- * -logout, are observed by the component SignInToWebsite.jsm.
- */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["IdentityService"];
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
-                                  "resource://gre/modules/identity/IdentityUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "makeMessageObject",
-                                  "resource://gre/modules/identity/IdentityUtils.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["minimal core"].concat(aMessageArgs));
-}
-function reportError(...aMessageArgs) {
-  Logger.reportError.apply(Logger, ["core"].concat(aMessageArgs));
-}
-
-function IDService() {
-  Services.obs.addObserver(this, "quit-application-granted", false);
-
-  // simplify, it's one object
-  this.RP = this;
-  this.IDP = this;
-
-  // keep track of flows
-  this._rpFlows = {};
-  this._authFlows = {};
-  this._provFlows = {};
-}
-
-IDService.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "quit-application-granted":
-        this.shutdown();
-        break;
-    }
-  },
-
-  shutdown() {
-    Services.obs.removeObserver(this, "quit-application-granted");
-  },
-
-  /**
-   * Parse an email into username and domain if it is valid, else return null
-   */
-  parseEmail: function parseEmail(email) {
-    var match = email.match(/^([^@]+)@([^@^/]+.[a-z]+)$/);
-    if (match) {
-      return {
-        username: match[1],
-        domain: match[2]
-      };
-    }
-    return null;
-  },
-
-  /**
-   * Register a listener for a given windowID as a result of a call to
-   * navigator.id.watch().
-   *
-   * @param aCaller
-   *        (Object)  an object that represents the caller document, and
-   *                  is expected to have properties:
-   *                  - id (unique, e.g. uuid)
-   *                  - loggedInUser (string or null)
-   *                  - origin (string)
-   *
-   *                  and a bunch of callbacks
-   *                  - doReady()
-   *                  - doLogin()
-   *                  - doLogout()
-   *                  - doError()
-   *                  - doCancel()
-   *
-   */
-  watch: function watch(aRpCaller) {
-    // store the caller structure and notify the UI observers
-    this._rpFlows[aRpCaller.id] = aRpCaller;
-
-    log("flows:", Object.keys(this._rpFlows).join(", "));
-
-    let options = makeMessageObject(aRpCaller);
-    log("sending identity-controller-watch:", options);
-    Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-watch", null);
-  },
-
-  /*
-   * The RP has gone away; remove handles to the hidden iframe.
-   * It's probable that the frame will already have been cleaned up.
-   */
-  unwatch: function unwatch(aRpId, aTargetMM) {
-    let rp = this._rpFlows[aRpId];
-    if (!rp) {
-      return;
-    }
-
-    let options = makeMessageObject({
-      id: aRpId,
-      origin: rp.origin,
-      messageManager: aTargetMM
-    });
-    log("sending identity-controller-unwatch for id", options.id, options.origin);
-    Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-unwatch", null);
-
-    // Stop sending messages to this window
-    delete this._rpFlows[aRpId];
-  },
-
-  /**
-   * Initiate a login with user interaction as a result of a call to
-   * navigator.id.request().
-   *
-   * @param aRPId
-   *        (integer)  the id of the doc object obtained in .watch()
-   *
-   * @param aOptions
-   *        (Object)  options including privacyPolicy, termsOfService
-   */
-  request: function request(aRPId, aOptions) {
-    let rp = this._rpFlows[aRPId];
-    if (!rp) {
-      reportError("request() called before watch()");
-      return;
-    }
-
-    // Notify UX to display identity picker.
-    // Pass the doc id to UX so it can pass it back to us later.
-    let options = makeMessageObject(rp);
-    objectCopy(aOptions, options);
-    Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-request", null);
-  },
-
-  /**
-   * Invoked when a user wishes to logout of a site (for instance, when clicking
-   * on an in-content logout button).
-   *
-   * @param aRpCallerId
-   *        (integer)  the id of the doc object obtained in .watch()
-   *
-   */
-  logout: function logout(aRpCallerId) {
-    let rp = this._rpFlows[aRpCallerId];
-    if (!rp) {
-      reportError("logout() called before watch()");
-      return;
-    }
-
-    let options = makeMessageObject(rp);
-    Services.obs.notifyObservers({wrappedJSObject: options}, "identity-controller-logout", null);
-  },
-
-  childProcessShutdown: function childProcessShutdown(messageManager) {
-    Object.keys(this._rpFlows).forEach(function(key) {
-      if (this._rpFlows[key]._mm === messageManager) {
-        log("child process shutdown for rp", key, "- deleting flow");
-        delete this._rpFlows[key];
-      }
-    }, this);
-  },
-
-  /*
-   * once the UI-and-display-logic components have received
-   * notifications, they call back with direct invocation of the
-   * following functions (doLogin, doLogout, or doReady)
-   */
-
-  doLogin: function doLogin(aRpCallerId, aAssertion, aInternalParams) {
-    let rp = this._rpFlows[aRpCallerId];
-    if (!rp) {
-      log("WARNING: doLogin found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doLogin(aAssertion, aInternalParams);
-  },
-
-  doLogout: function doLogout(aRpCallerId) {
-    let rp = this._rpFlows[aRpCallerId];
-    if (!rp) {
-      log("WARNING: doLogout found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    // Logout from every site with the same origin
-    let origin = rp.origin;
-    Object.keys(this._rpFlows).forEach(function(key) {
-      let rp = this._rpFlows[key];
-      if (rp.origin === origin) {
-        rp.doLogout();
-      }
-    }.bind(this));
-  },
-
-  doReady: function doReady(aRpCallerId) {
-    let rp = this._rpFlows[aRpCallerId];
-    if (!rp) {
-      log("WARNING: doReady found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doReady();
-  },
-
-  doCancel: function doCancel(aRpCallerId) {
-    let rp = this._rpFlows[aRpCallerId];
-    if (!rp) {
-      log("WARNING: doCancel found no rp to go with callerId " + aRpCallerId);
-      return;
-    }
-
-    rp.doCancel();
-  }
-};
-
-this.IdentityService = new IDService();
deleted file mode 100644
--- a/toolkit/identity/RelyingParty.jsm
+++ /dev/null
@@ -1,367 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=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/. */
-
-"use strict";
-
-const Cu = Components.utils;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-Cu.import("resource://gre/modules/identity/IdentityStore.jsm");
-
-this.EXPORTED_SYMBOLS = ["RelyingParty"];
-
-XPCOMUtils.defineLazyModuleGetter(this, "objectCopy",
-                                  "resource://gre/modules/identity/IdentityUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["RP"].concat(aMessageArgs));
-}
-function reportError(...aMessageArgs) {
-  Logger.reportError.apply(Logger, ["RP"].concat(aMessageArgs));
-}
-
-function IdentityRelyingParty() {
-  // The store is a singleton shared among Identity, RelyingParty, and
-  // IdentityProvider.  The Identity module takes care of resetting
-  // state in the _store on shutdown.
-  this._store = IdentityStore;
-
-  this.reset();
-}
-
-IdentityRelyingParty.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "quit-application-granted":
-        Services.obs.removeObserver(this, "quit-application-granted");
-        this.shutdown();
-        break;
-
-    }
-  },
-
-  reset: function RP_reset() {
-    // Forget all documents that call in.  (These are sometimes
-    // referred to as callers.)
-    this._rpFlows = {};
-  },
-
-  shutdown: function RP_shutdown() {
-    this.reset();
-    Services.obs.removeObserver(this, "quit-application-granted");
-  },
-
-  /**
-   * Register a listener for a given windowID as a result of a call to
-   * navigator.id.watch().
-   *
-   * @param aCaller
-   *        (Object)  an object that represents the caller document, and
-   *                  is expected to have properties:
-   *                  - id (unique, e.g. uuid)
-   *                  - loggedInUser (string or null)
-   *                  - origin (string)
-   *
-   *                  and a bunch of callbacks
-   *                  - doReady()
-   *                  - doLogin()
-   *                  - doLogout()
-   *                  - doError()
-   *                  - doCancel()
-   *
-   */
-  watch: function watch(aRpCaller) {
-    this._rpFlows[aRpCaller.id] = aRpCaller;
-    let origin = aRpCaller.origin;
-    let state = this._store.getLoginState(origin) || { isLoggedIn: false, email: null };
-
-    log("watch: rpId:", aRpCaller.id,
-        "origin:", origin,
-        "loggedInUser:", aRpCaller.loggedInUser,
-        "loggedIn:", state.isLoggedIn,
-        "email:", state.email);
-
-    // If the user is already logged in, then there are three cases
-    // to deal with:
-    //
-    //   1. the email is valid and unchanged:  'ready'
-    //   2. the email is null:                 'login'; 'ready'
-    //   3. the email has changed:             'login'; 'ready'
-    if (state.isLoggedIn) {
-      if (state.email && aRpCaller.loggedInUser === state.email) {
-        this._notifyLoginStateChanged(aRpCaller.id, state.email);
-        return aRpCaller.doReady();
-
-      } else if (aRpCaller.loggedInUser === null) {
-        // Generate assertion for existing login
-        let options = {loggedInUser: state.email, origin};
-        return this._doLogin(aRpCaller, options);
-      }
-      // A loggedInUser different from state.email has been specified.
-      // Change login identity.
-
-      let options = {loggedInUser: state.email, origin};
-      return this._doLogin(aRpCaller, options);
-
-    // If the user is not logged in, there are two cases:
-    //
-    //   1. a logged in email was provided: 'ready'; 'logout'
-    //   2. not logged in, no email given:  'ready';
-
-    }
-    if (aRpCaller.loggedInUser) {
-      return this._doLogout(aRpCaller, {origin});
-    }
-    return aRpCaller.doReady();
-  },
-
-  /**
-   * A utility for watch() to set state and notify the dom
-   * on login
-   *
-   * Note that this calls _getAssertion
-   */
-  _doLogin: function _doLogin(aRpCaller, aOptions, aAssertion) {
-    log("_doLogin: rpId:", aRpCaller.id, "origin:", aOptions.origin);
-
-    let loginWithAssertion = function loginWithAssertion(assertion) {
-      this._store.setLoginState(aOptions.origin, true, aOptions.loggedInUser);
-      this._notifyLoginStateChanged(aRpCaller.id, aOptions.loggedInUser);
-      aRpCaller.doLogin(assertion);
-      aRpCaller.doReady();
-    }.bind(this);
-
-    if (aAssertion) {
-      loginWithAssertion(aAssertion);
-    } else {
-      this._getAssertion(aOptions, function gotAssertion(err, assertion) {
-        if (err) {
-          reportError("_doLogin:", "Failed to get assertion on login attempt:", err);
-          this._doLogout(aRpCaller);
-        } else {
-          loginWithAssertion(assertion);
-        }
-      }.bind(this));
-    }
-  },
-
-  /**
-   * A utility for watch() to set state and notify the dom
-   * on logout.
-   */
-  _doLogout: function _doLogout(aRpCaller, aOptions) {
-    log("_doLogout: rpId:", aRpCaller.id, "origin:", aOptions.origin);
-
-    let state = this._store.getLoginState(aOptions.origin) || {};
-
-    state.isLoggedIn = false;
-    this._notifyLoginStateChanged(aRpCaller.id, null);
-
-    aRpCaller.doLogout();
-    aRpCaller.doReady();
-  },
-
-  /**
-   * For use with login or logout, emit 'identity-login-state-changed'
-   *
-   * The notification will send the rp caller id in the properties,
-   * and the email of the user in the message.
-   *
-   * @param aRpCallerId
-   *        (integer) The id of the RP caller
-   *
-   * @param aIdentity
-   *        (string) The email of the user whose login state has changed
-   */
-  _notifyLoginStateChanged: function _notifyLoginStateChanged(aRpCallerId, aIdentity) {
-    log("_notifyLoginStateChanged: rpId:", aRpCallerId, "identity:", aIdentity);
-
-    let options = {rpId: aRpCallerId};
-    Services.obs.notifyObservers({wrappedJSObject: options},
-                                 "identity-login-state-changed",
-                                 aIdentity);
-  },
-
-  /**
-   * Initiate a login with user interaction as a result of a call to
-   * navigator.id.request().
-   *
-   * @param aRPId
-   *        (integer)  the id of the doc object obtained in .watch()
-   *
-   * @param aOptions
-   *        (Object)  options including privacyPolicy, termsOfService
-   */
-  request: function request(aRPId, aOptions) {
-    log("request: rpId:", aRPId);
-    let rp = this._rpFlows[aRPId];
-
-    // Notify UX to display identity picker.
-    // Pass the doc id to UX so it can pass it back to us later.
-    let options = {rpId: aRPId, origin: rp.origin};
-    objectCopy(aOptions, options);
-
-    // Append URLs after resolving
-    let baseURI = Services.io.newURI(rp.origin);
-    for (let optionName of ["privacyPolicy", "termsOfService"]) {
-      if (aOptions[optionName]) {
-        options[optionName] = baseURI.resolve(aOptions[optionName]);
-      }
-    }
-
-    Services.obs.notifyObservers({wrappedJSObject: options}, "identity-request", null);
-  },
-
-  /**
-   * Invoked when a user wishes to logout of a site (for instance, when clicking
-   * on an in-content logout button).
-   *
-   * @param aRpCallerId
-   *        (integer)  the id of the doc object obtained in .watch()
-   *
-   */
-  logout: function logout(aRpCallerId) {
-    log("logout: RP caller id:", aRpCallerId);
-    let rp = this._rpFlows[aRpCallerId];
-    if (rp && rp.origin) {
-      let origin = rp.origin;
-      log("logout: origin:", origin);
-      this._doLogout(rp, {origin});
-    } else {
-      log("logout: no RP found with id:", aRpCallerId);
-    }
-    // We don't delete this._rpFlows[aRpCallerId], because
-    // the user might log back in again.
-  },
-
-  getDefaultEmailForOrigin: function getDefaultEmailForOrigin(aOrigin) {
-    let identities = this.getIdentitiesForSite(aOrigin);
-    let result = identities.lastUsed || null;
-    log("getDefaultEmailForOrigin:", aOrigin, "->", result);
-    return result;
-  },
-
-  /**
-   * Return the list of identities a user may want to use to login to aOrigin.
-   */
-  getIdentitiesForSite: function getIdentitiesForSite(aOrigin) {
-    let rv = { result: [] };
-    for (let id in this._store.getIdentities()) {
-      rv.result.push(id);
-    }
-    let loginState = this._store.getLoginState(aOrigin);
-    if (loginState && loginState.email)
-      rv.lastUsed = loginState.email;
-    return rv;
-  },
-
-  /**
-   * Obtain a BrowserID assertion with the specified characteristics.
-   *
-   * @param aCallback
-   *        (Function) Callback to be called with (err, assertion) where 'err'
-   *        can be an Error or NULL, and 'assertion' can be NULL or a valid
-   *        BrowserID assertion. If no callback is provided, an exception is
-   *        thrown.
-   *
-   * @param aOptions
-   *        (Object) An object that may contain the following properties:
-   *
-   *          "audience"      : The audience for which the assertion is to be
-   *                            issued. If this property is not set an exception
-   *                            will be thrown.
-   *
-   *        Any properties not listed above will be ignored.
-   */
-  _getAssertion: function _getAssertion(aOptions, aCallback) {
-    let audience = aOptions.origin;
-    let email = aOptions.loggedInUser || this.getDefaultEmailForOrigin(audience);
-    log("_getAssertion: audience:", audience, "email:", email);
-    if (!audience) {
-      throw "audience required for _getAssertion";
-    }
-
-    // We might not have any identity info for this email
-    if (!this._store.fetchIdentity(email)) {
-      this._store.addIdentity(email, null, null);
-    }
-
-    let cert = this._store.fetchIdentity(email)["cert"];
-    if (cert) {
-      this._generateAssertion(audience, email, function generatedAssertion(err, assertion) {
-        if (err) {
-          log("ERROR: _getAssertion:", err);
-        }
-        log("_getAssertion: generated assertion:", assertion);
-        return aCallback(err, assertion);
-      });
-    }
-  },
-
-  /**
-   * Generate an assertion, including provisioning via IdP if necessary,
-   * but no user interaction, so if provisioning fails, aCallback is invoked
-   * with an error.
-   *
-   * @param aAudience
-   *        (string) web origin
-   *
-   * @param aIdentity
-   *        (string) the email we're logging in with
-   *
-   * @param aCallback
-   *        (function) callback to invoke on completion
-   *                   with first-positional parameter the error.
-   */
-  _generateAssertion: function _generateAssertion(aAudience, aIdentity, aCallback) {
-    log("_generateAssertion: audience:", aAudience, "identity:", aIdentity);
-
-    let id = this._store.fetchIdentity(aIdentity);
-    if (!(id && id.cert)) {
-      let errStr = "Cannot generate an assertion without a certificate";
-      log("ERROR: _generateAssertion:", errStr);
-      aCallback(errStr);
-      return;
-    }
-
-    let kp = id.keyPair;
-
-    if (!kp) {
-      let errStr = "Cannot generate an assertion without a keypair";
-      log("ERROR: _generateAssertion:", errStr);
-      aCallback(errStr);
-      return;
-    }
-
-    jwcrypto.generateAssertion(id.cert, kp, aAudience, aCallback);
-  },
-
-  /**
-   * Clean up references to the provisioning flow for the specified RP.
-   */
-  _cleanUpProvisionFlow: function RP_cleanUpProvisionFlow(aRPId, aProvId) {
-    let rp = this._rpFlows[aRPId];
-    if (rp) {
-      delete rp["provId"];
-    } else {
-      log("Error: Couldn't delete provision flow ", aProvId, " for RP ", aRPId);
-    }
-  },
-
-};
-
-this.RelyingParty = new IdentityRelyingParty();
deleted file mode 100644
--- a/toolkit/identity/Sandbox.jsm
+++ /dev/null
@@ -1,152 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["Sandbox"];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-const XHTML_NS = "http://www.w3.org/1999/xhtml";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "Logger",
-                                  "resource://gre/modules/identity/LogUtils.jsm");
-
-/**
- * An object that represents a sandbox in an iframe loaded with aURL. The
- * callback provided to the constructor will be invoked when the sandbox is
- * ready to be used. The callback will receive this object as its only argument.
- *
- * You must call free() when you are finished with the sandbox to explicitly
- * free up all associated resources.
- *
- * @param aURL
- *        (string) URL to load in the sandbox.
- *
- * @param aCallback
- *        (function) Callback to be invoked with a Sandbox, when ready.
- */
-this.Sandbox = function Sandbox(aURL, aCallback) {
-  // Normalize the URL so the comparison in _makeSandboxContentLoaded works
-  this._url = Services.io.newURI(aURL).spec;
-  this._log("Creating sandbox for:", this._url);
-  this._createFrame();
-  this._createSandbox(aCallback);
-};
-
-this.Sandbox.prototype = {
-
-  /**
-   * Use the outer window ID as the identifier of the sandbox.
-   */
-  get id() {
-    return this._frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
-  },
-
-  /**
-   * Reload the URL in the sandbox. This is useful to reuse a Sandbox (same
-   * id and URL).
-   */
-  reload: function Sandbox_reload(aCallback) {
-    this._log("reload:", this.id, ":", this._url);
-    this._createSandbox(function createdSandbox(aSandbox) {
-      this._log("reloaded sandbox id:", aSandbox.id);
-      aCallback(aSandbox);
-    }.bind(this));
-  },
-
-  /**
-   * Frees the sandbox and releases the iframe created to host it.
-   */
-  free: function Sandbox_free() {
-    this._log("free:", this.id);
-    this._container.removeChild(this._frame);
-    this._frame = null;
-    this._container = null;
-    this._url = null;
-  },
-
-  /**
-   * Creates an empty, hidden iframe and sets it to the _frame
-   * property of this object.
-   */
-  _createFrame: function Sandbox__createFrame() {
-    let hiddenWindow = Services.appShell.hiddenDOMWindow;
-    let doc = hiddenWindow.document;
-
-    // Insert iframe in to create docshell.
-    let frame = doc.createElementNS(XHTML_NS, "iframe");
-    frame.setAttribute("mozframetype", "content");
-    frame.sandbox = "allow-forms allow-scripts allow-same-origin";
-    frame.style.visibility = "collapse";
-    doc.documentElement.appendChild(frame);
-
-    let docShell = frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                      .getInterface(Ci.nsIWebNavigation)
-                                      .QueryInterface(Ci.nsIInterfaceRequestor)
-                                      .getInterface(Ci.nsIDocShell);
-
-    // Stop about:blank from being loaded.
-    docShell.stop(Ci.nsIWebNavigation.STOP_NETWORK);
-
-    // Disable some types of content
-    docShell.allowAuth = false;
-    docShell.allowPlugins = false;
-    docShell.allowImages = false;
-    docShell.allowMedia = false;
-    docShell.allowWindowControl = false;
-
-    // Disable stylesheet loading since the document is not visible.
-    let markupDocViewer = docShell.contentViewer;
-    markupDocViewer.authorStyleDisabled = true;
-
-    // Set instance properties.
-    this._frame = frame;
-    this._container = doc.documentElement;
-  },
-
-  _createSandbox: function Sandbox__createSandbox(aCallback) {
-    let self = this;
-    function _makeSandboxContentLoaded(event) {
-      self._log("_makeSandboxContentLoaded:", self.id,
-                event.target.location.toString());
-      if (event.target != self._frame.contentDocument) {
-        return;
-      }
-      self._frame.removeEventListener(
-        "DOMWindowCreated", _makeSandboxContentLoaded, true
-      );
-
-      aCallback(self);
-    }
-
-    this._frame.addEventListener("DOMWindowCreated",
-                                 _makeSandboxContentLoaded,
-                                 true);
-
-    // Load the iframe.
-    let webNav = this._frame.contentWindow
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIWebNavigation);
-
-    webNav.loadURI(
-      this._url,
-      Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE,
-      null, // referrer
-      null, // postData
-      null  // headers
-    );
-
-  },
-
-  _log: function Sandbox__log(...aMessageArgs) {
-    Logger.log.apply(Logger, ["sandbox"].concat(aMessageArgs));
-  },
-
-};
deleted file mode 100644
--- a/toolkit/identity/moz.build
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
-XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
-
-XPIDL_SOURCES += [
-    'nsIIdentityCryptoService.idl',
-]
-
-XPIDL_MODULE = 'identity'
-
-SOURCES += [
-    'IdentityCryptoService.cpp',
-]
-
-EXTRA_JS_MODULES.identity += [
-    'Identity.jsm',
-    'IdentityProvider.jsm',
-    'IdentityStore.jsm',
-    'IdentityUtils.jsm',
-    'jwcrypto.jsm',
-    'LogUtils.jsm',
-    'MinimalIdentity.jsm',
-    'RelyingParty.jsm',
-    'Sandbox.jsm',
-]
-
-EXTRA_PP_JS_MODULES.identity += [
-    'FirefoxAccounts.jsm',
-]
-
-FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "../../../../testing/mochitest/chrome.eslintrc.js"
-  ]
-};
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/chrome.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[DEFAULT]
-skip-if = buildapp == 'b2g' || os == 'android'
-support-files =
-  sandbox_content.html
-  sandbox_content.sjs
-  sandbox_content_alert.html
-  sandbox_content_framed.html
-  sandbox_content_perms.html
-  sandbox_content_popup.html
-  sandbox_content_redirect.html
-  sandbox_content_redirect.html^headers^
-
-[test_sandbox.xul]
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!-- Any copyright is dedicated to the Public Domain.
-   - http://creativecommons.org/publicdomain/zero/1.0/ -->
-<head>
-<meta charset="utf-8">
-<title>Page testing blocked content in the Sandbox</title>
-
-<link rel="stylesheet" src="sandbox_content.sjs?text/css"/>
-
-<script src="sandbox_content.sjs?application/javascript"></script>
-
-</head>
-
-<body>
-
-<img src="sandbox_content.sjs?image/jpeg"/>
-
-<!-- media -->
-<video src="sandbox_content.sjs?video/webm" autoplay="true"></video>
-<audio src="sandbox_content.sjs?audio/ogg" autoplay="true"></audio>
-
-<!-- plugins -->
-<embed src="sandbox_content.sjs?application/x-test"/>
-<object data="sandbox_content.sjs?application/x-test"></object>
-<applet code="sandbox_content.sjs?application/x-java-applet"></applet>
-
-<iframe src="sandbox_content.sjs?text/html"></iframe>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content.sjs
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- *  * License, v. 2.0. If a copy of the MPL was not distributed with this
- *  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function handleRequest(request, response) {
-  response.setHeader("Cache-Control", "no-cache", false);
-
-  let loadedStateKey = "sandbox_content_loaded";
-  switch(request.queryString) {
-    case "reset": {
-      setState(loadedStateKey, "");
-      response.write("reset");
-      break;
-    }
-    case "get_loaded": {
-      response.setHeader("Content-Type", "text/plain", false);
-      let loaded = getState(loadedStateKey);
-      if (loaded)
-        response.write(loaded);
-      else
-        response.write("NOTHING");
-      break;
-    }
-    default: {
-      let contentType = decodeURIComponent(request.queryString);
-      // set the Content-Type equal to the query string
-      response.setHeader("Content-Type", contentType, false);
-      // If any content is loaded, append it's content type in state
-      let loaded = getState(loadedStateKey);
-      if (loaded)
-        loaded += ",";
-      setState(loadedStateKey, loaded + contentType);
-      break;
-    }
-  }
-}
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_alert.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!-- Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/ -->
-<head>
-<meta charset="utf-8">
-<title>Page creating an alert inside the Sandbox</title>
-
-<script>
-
-alert("The user shouldn't see this");
-
-</script>
-
-</head>
-
-<body>
-
-</body>
-</html>
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_framed.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!-- Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/ -->
-<head>
-<meta charset="utf-8">
-<title>Page testing blocked content in an iframe inside the Sandbox</title>
-
-</head>
-
-<body>
-
-<iframe src="sandbox_content.html"></iframe>
-
-</body>
-
-</html>
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_perms.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Any copyright is dedicated to the Public Domain.
-     - http://creativecommons.org/publicdomain/zero/1.0/ -->
-  <head>
-    <meta charset="utf-8">
-    <title>Page testing content in the Sandbox can't escape</title>
-    <script type="application/javascript;version=1.8">
-      const TEST_BASE = "http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/"
-      const Ci = SpecialPowers.Ci;
-
-      function expectException(aFunc) {
-        try {
-          aFunc();
-        } catch (ex) {
-          return true;
-        }
-        return false;
-      }
-
-      function CcNotPresent() {
-        if (typeof Components === 'undefined')
-          return true;
-        // Components shim doesn't define Components.classes.
-        try {
-          return typeof Components.classes === 'undefined';
-        } catch (e) {
-          return false;
-        }
-      }
-
-      // Build an object with test results (true = pass)
-      let results = {
-        windowTop: window.top == window,
-
-        qiWindow: expectException(function() {
-          let isForced = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIDOMWindowUtils)
-                               .docCharsetIsForced;
-        }),
-
-        ccAccess: !!CcNotPresent(),
-      };
-
-      let resultsJSON = JSON.stringify(results);
-
-      // Send the results to the mochitest server so the test file can retrieve them.
-      let stateURL = TEST_BASE + "sandbox_content.sjs"
-      let xhr = new XMLHttpRequest();
-      xhr.open("GET", stateURL + "?" + encodeURIComponent(resultsJSON), true);
-      xhr.onload = function() {
-        if (xhr.status != 200) {
-          dump("Failed sending results\n");
-        }
-      };
-      xhr.send();
-
-    </script>
-  </head>
-
-  <body>
-
-  </body>
-</html>
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_popup.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!-- Any copyright is dedicated to the Public Domain.
-   - http://creativecommons.org/publicdomain/zero/1.0/ -->
-<head>
-<meta charset="utf-8">
-<title>Page creating an popup inside the Sandbox</title>
-
-<script>
-
-var strWindowFeatures = "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes";
-
-var uri = "data:text/html,";
-uri += encodeURI("<body onload='setTimeout(window.close, 1000)'>");
-
-var win = window.open(uri, "sandbox_popup", strWindowFeatures);
-
-</script>
-
-</head>
-
-<body>
-
-</body>
-</html>
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_redirect.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!-- Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/ -->
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/sandbox_content_redirect.html^headers^
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP 302 Found
-Location: http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/sandbox_content.html
deleted file mode 100644
--- a/toolkit/identity/tests/chrome/test_sandbox.xul
+++ /dev/null
@@ -1,324 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
-<!-- Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/ -->
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=762993
--->
-<window title="Mozilla Bug 762993"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="run_next_test();">
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
-  <!-- test results are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml">
-  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=762993"
-     target="_blank">Mozilla Bug 762993</a>
-  </body>
-
-  <!-- test code goes here -->
-  <script type="application/javascript;version=1.8">
-  <![CDATA[
-
-  /** Test for Bug 762993 **/
-
-"use strict";
-
-SimpleTest.expectAssertions(1);
-
-SimpleTest.waitForExplicitFinish();
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
-
-const TEST_URL_1 = "https://example.com/";
-// No trailing slash plus port to test normalization
-const TEST_URL_2 = "https://example.com:443";
-
-const TEST_BASE = "http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/"
-const STATE_URL = TEST_BASE + "sandbox_content.sjs"
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-Services.prefs.setBoolPref("toolkit.identity.debug", true);
-
-XPCOMUtils.defineLazyModuleGetter(this, "Sandbox",
-                                  "resource://gre/modules/identity/Sandbox.jsm");
-
-function check_sandbox(aSandbox, aURL) {
-  ok(aSandbox.id > 0, "valid ID");
-  is(aSandbox._url, aURL, "matching URL (with normalization)");
-  isnot(aSandbox._frame, null, "frame");
-  isnot(aSandbox._container, null, "container");
-  let docPrincipal = aSandbox._frame.contentDocument.nodePrincipal;
-  is(secMan.isSystemPrincipal(docPrincipal), false,
-     "principal must not be system");
-}
-
-/**
- * Free the sandbox and make sure all properties that are not booleans,
- * functions or numbers were freed.
- */
-function free_and_check_sandbox(aSandbox) {
-  SimpleTest.executeSoon(function() {
-    aSandbox.free();
-
-    for(let prop in aSandbox) {
-      // Don't trigger the "id" getter when the frame is supposed to be freed already
-      if (prop == "id")
-        continue;
-      let propType = typeof(aSandbox[prop]);
-      if (propType == "boolean" || propType == "function" || propType == "number")
-        continue;
-      is(aSandbox[prop], null, "freed " + prop);
-    }
-    run_next_test();
-  });
-}
-
-function reset_server_state() {
-  // Now reset the server state
-  let resetReq = new XMLHttpRequest();
-  resetReq.open("GET", STATE_URL + "?reset", false);
-  resetReq.send();
-}
-
-function test_creation() {
-  new Sandbox(TEST_URL_1, function sandboxCB(aSandbox) {
-    check_sandbox(aSandbox, TEST_URL_1);
-    free_and_check_sandbox(aSandbox);
-  });
-}
-
-function test_reload() {
-  new Sandbox(TEST_URL_1, function sandboxCB(aSandbox) {
-    check_sandbox(aSandbox, TEST_URL_1);
-    let originalId = aSandbox.id;
-
-    aSandbox.reload(function sandboxReloadCB(aSandbox) {
-      check_sandbox(aSandbox, TEST_URL_1);
-      is(aSandbox.id, originalId, "Sandbox ID should be the same after reload");
-      free_and_check_sandbox(aSandbox);
-    });
-  });
-}
-
-function test_url_normalization() {
-  new Sandbox(TEST_URL_2, function sandboxCB(aSandbox) {
-    // TEST_URL_2 should be normalized into the form of TEST_URL_1
-    check_sandbox(aSandbox, TEST_URL_1);
-    free_and_check_sandbox(aSandbox);
-  });
-}
-
-/**
- * Check with the server's state to see what content was loaded then reset it.
- */
-function check_loaded_content(aSandbox, aNothingShouldLoad, aCallback) {
-
-  let xhr = new XMLHttpRequest();
-  xhr.open("GET", STATE_URL + "?get_loaded", true);
-  xhr.onload = function() {
-    let res = xhr.responseText;
-    is(xhr.status, 200, "Check successful response");
-
-    if (aNothingShouldLoad) {
-      is(res, "NOTHING", "Check that nothing was loaded on the server");
-    } else {
-      let allowedTypes = [ "application/javascript", "text/html", "application/x-test" ];
-      let loadedTypes = res == "NOTHING" ? [] : res.split(",");
-
-      for (let loadedType of loadedTypes) {
-        isnot(allowedTypes.indexOf(loadedType), -1, "Check that " + loadedType + " was expected to load"); // TODO
-      }
-
-      isnot(loadedTypes.indexOf("application/javascript"), -1, "Check JS was loaded");
-      isnot(loadedTypes.indexOf("text/html"), -1, "Check iframe was loaded");
-      is(loadedTypes.indexOf("video/webm"), -1, "Check webm was not loaded");
-      is(loadedTypes.indexOf("audio/ogg"), -1, "Check ogg was not loaded");
-
-      // Check that no plugin tags have a type other than TYPE_NULL (failed load)
-      // --
-      // Checking if a channel was opened is not sufficient for plugin tags --
-      // An object tag may still be allowed to load a sub-document, but not a
-      // plugin, so it will open a channel but then abort when it gets a
-      // plugin-type.
-      let doc = aSandbox._frame.contentDocument;
-      let nullType = Components.interfaces.nsIObjectLoadingContent.TYPE_NULL;
-      for (let tag of doc.querySelectorAll("embed, object, applet")) {
-        tag instanceof Components.interfaces.nsIObjectLoadingContent;
-        is(tag.displayedType, nullType, "Check that plugin did not load content");
-      }
-    }
-
-    reset_server_state();
-
-    aCallback();
-  };
-  xhr.send();
-}
-
-/**
- * Helper to check that only certain content is loaded on creation and during reload.
- */
-function check_disabled_content(aSandboxURL, aNothingShouldLoad = false) {
-  new Sandbox(aSandboxURL, function sandboxCB(aSandbox) {
-    check_sandbox(aSandbox, aSandboxURL);
-    let originalId = aSandbox.id;
-
-    setTimeout(function() {
-      check_loaded_content(aSandbox, aNothingShouldLoad, function checkFinished() {
-
-        info("reload the sandbox content");
-        aSandbox.reload(function sandboxReloadCB(aSandbox) {
-          check_sandbox(aSandbox, aSandboxURL);
-          is(aSandbox.id, originalId, "Sandbox ID should be the same after reload");
-
-          setTimeout(function() {
-            check_loaded_content(aSandbox, aNothingShouldLoad, function reloadCheckFinished() {
-              free_and_check_sandbox(aSandbox);
-            });
-          }, 5000);
-        });
-      });
-    }, 5000);
-  });
-}
-
-function test_disabled_content() {
-  let url = TEST_BASE + "sandbox_content.html";
-  check_disabled_content(url);
-}
-
-// Same as test above but with content in an iframe.
-function test_disabled_content_framed() {
-  let url = TEST_BASE + "sandbox_content_framed.html";
-  check_disabled_content(url);
-}
-
-function test_redirect() {
-  let url = TEST_BASE + "sandbox_content_redirect.html";
-  check_disabled_content(url);
-}
-
-function WindowObserver(aCallback) {
-  this.observe = function(aSubject, aTopic, aData) {
-    if (aTopic != "domwindowopened") {
-      return;
-    }
-    Services.ww.unregisterNotification(this);
-
-    let domWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
-    ok(!domWin, "No window should be opened");
-    SimpleTest.executeSoon(function() {
-      info("Closing opened window");
-      domWin.close();
-      aCallback();
-    });
-  }
-}
-
-// Can the sandbox call window.alert() or popup other UI?
-function test_alert() {
-  let alertURL = TEST_BASE + "sandbox_content_alert.html";
-
-  new Sandbox(alertURL, function sandboxCB(aSandbox) {
-    check_sandbox(aSandbox, alertURL);
-    setTimeout(function() {
-
-      let win = Services.wm.getMostRecentWindow(null);
-      isnot(win.document.documentElement.getAttribute("id"), "commonDialog",
-                 "Make sure most recent window is not a dialog");
-      if (win.document.documentElement.getAttribute("id") == "commonDialog") {
-        // If a dialog did open, close it so we don't interfere with future tests
-        win.close()
-      }
-
-      free_and_check_sandbox(aSandbox);
-    }, 1000);
-  });
-}
-
-// Can the sandboxed page open a popup with window.open?
-function test_popup() {
-  let alertURL = TEST_BASE + "sandbox_content_popup.html";
-  let theSandbox;
-  function continueTest() {
-    // avoid double-free
-    if (!theSandbox)
-      return;
-    free_and_check_sandbox(theSandbox);
-    theSandbox = null;
-  }
-  let winObs = new WindowObserver(continueTest);
-  Services.ww.registerNotification(winObs);
-  new Sandbox(alertURL, function sandboxCB(aSandbox) {
-    theSandbox = aSandbox;
-    check_sandbox(aSandbox, alertURL);
-    // Wait 5 seconds to see if the window is going to open.
-    setTimeout(function() {
-      Services.ww.unregisterNotification(winObs);
-      continueTest();
-    }, 5000);
-  });
-}
-
-// Loading a page with a bad cert
-function test_bad_cert() {
-  let url = TEST_BASE + "sandbox_content.sjs?text/html";
-  url = url.replace("http://mochi.test:8888", "https://untrusted.example.com");
-  check_disabled_content(url, /*nothingShouldLoad=*/true);
-}
-
-// Loading a page to check window.top and other permissions.
-function test_frame_perms() {
-  let url = TEST_BASE + "sandbox_content_perms.html";
-  new Sandbox(url, function sandboxCB(aSandbox) {
-    check_sandbox(aSandbox, url);
-
-    // Give the content time to load
-    setTimeout(function() {
-      let xhr = new XMLHttpRequest();
-      xhr.open("GET", STATE_URL + "?get_loaded", true);
-      xhr.responseType = "json";
-      xhr.onload = function() {
-        is(xhr.status, 200, "Check successful response");
-        is(typeof(xhr.response), "object", "Check response is object");
-        is(Object.keys(xhr.response).length, 3, "Check the number of perm. tests");
-        for (let test in xhr.response) {
-          ok(xhr.response[test], "Check result of " + test);
-        }
-
-        reset_server_state();
-        free_and_check_sandbox(aSandbox);
-      };
-      xhr.send();
-    }, 3000);
-  });
-}
-
-let TESTS = [test_creation, test_reload, test_url_normalization];
-TESTS.push(test_disabled_content, test_disabled_content_framed);
-TESTS.push(test_alert, test_popup, test_bad_cert);
-TESTS.push(test_redirect, test_frame_perms);
-
-function run_next_test() {
-  if (TESTS.length) {
-    let test = TESTS.shift();
-    info(test.name);
-    test();
-  } else {
-    Services.prefs.clearUserPref("toolkit.identity.debug");
-    SimpleTest.finish();
-  }
-}
-
-  ]]>
-  </script>
-</window>
deleted file mode 100644
--- a/toolkit/identity/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "../../../../testing/xpcshell/xpcshell.eslintrc.js"
-  ]
-};
deleted file mode 100644
--- a/toolkit/identity/tests/unit/data/idp_1/.well-known/browserid
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "public-key": {"algorithm":"RS","n":"65718905405105134410187227495885391609221288015566078542117409373192106382993306537273677557482085204736975067567111831005921322991127165013340443563713385983456311886801211241492470711576322130577278575529202840052753612576061450560588102139907846854501252327551303482213505265853706269864950437458242988327","e":"65537"},
-    "authentication": "/browserid/sign_in.html",
-    "provisioning": "/browserid/provision.html"
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/data/idp_invalid_1/.well-known/browserid
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "public-key": {"algorithm":"RS","n":"65718905405105134410187227495885391609221288015566078542117409373192106382993306537273677557482085204736975067567111831005921322991127165013340443563713385983456311886801211241492470711576322130577278575529202840052753612576061450560588102139907846854501252327551303482213505265853706269864950437458242988327","e":"65537"},
-    "authentication": "/browserid/sign_in.html",
-    // missing "provisioning"
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/head_identity.js
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-var Cr = Components.results;
-
-Cu.import("resource://testing-common/httpd.js");
-
-// XXX until bug 937114 is fixed
-Cu.importGlobalProperties(["atob"]);
-
-// The following boilerplate makes sure that XPCOM calls
-// that use the profile directory work.
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "IdentityStore",
-                                  "resource://gre/modules/identity/IdentityStore.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this,
-                                  "Logger",
-                                  "resource://gre/modules/identity/LogUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this,
-                                   "uuidGenerator",
-                                   "@mozilla.org/uuid-generator;1",
-                                   "nsIUUIDGenerator");
-
-const TEST_MESSAGE_MANAGER = "Mr McFeeley";
-const TEST_URL = "https://myfavoritebacon.com";
-const TEST_URL2 = "https://myfavoritebaconinacan.com";
-const TEST_USER = "user@mozilla.com";
-const TEST_PRIVKEY = "fake-privkey";
-const TEST_CERT = "fake-cert";
-const TEST_ASSERTION = "fake-assertion";
-const TEST_IDPPARAMS = {
-  domain: "myfavoriteflan.com",
-  authentication: "/foo/authenticate.html",
-  provisioning: "/foo/provision.html"
-};
-
-// The following are utility functions for Identity testing
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["test"].concat(aMessageArgs));
-}
-
-function get_idstore() {
-  return IdentityStore;
-}
-
-function partial(fn) {
-  let args = Array.prototype.slice.call(arguments, 1);
-  return function() {
-    return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
-  };
-}
-
-function uuid() {
-  return uuidGenerator.generateUUID().toString();
-}
-
-function base64UrlDecode(s) {
-  s = s.replace(/-/g, "+");
-  s = s.replace(/_/g, "/");
-
-  // Replace padding if it was stripped by the sender.
-  // See http://tools.ietf.org/html/rfc4648#section-4
-  switch (s.length % 4) {
-    case 0:
-      break; // No pad chars in this case
-    case 2:
-      s += "==";
-      break; // Two pad chars
-    case 3:
-      s += "=";
-      break; // One pad char
-    default:
-      throw new InputException("Illegal base64url string!");
-  }
-
-  // With correct padding restored, apply the standard base64 decoder
-  return atob(s);
-}
-
-// create a mock "doc" object, which the Identity Service
-// uses as a pointer back into the doc object
-function mock_doc(aIdentity, aOrigin, aDoFunc) {
-  let mockedDoc = {};
-  mockedDoc.id = uuid();
-  mockedDoc.loggedInUser = aIdentity;
-  mockedDoc.origin = aOrigin;
-  mockedDoc["do"] = aDoFunc;
-  mockedDoc._mm = TEST_MESSAGE_MANAGER;
-  mockedDoc.doReady = partial(aDoFunc, "ready");
-  mockedDoc.doLogin = partial(aDoFunc, "login");
-  mockedDoc.doLogout = partial(aDoFunc, "logout");
-  mockedDoc.doError = partial(aDoFunc, "error");
-  mockedDoc.doCancel = partial(aDoFunc, "cancel");
-  mockedDoc.doCoffee = partial(aDoFunc, "coffee");
-  mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown");
-
-  mockedDoc.RP = mockedDoc;
-
-  return mockedDoc;
-}
-
-function mock_fxa_rp(aIdentity, aOrigin, aDoFunc) {
-  let mockedDoc = {};
-  mockedDoc.id = uuid();
-  mockedDoc.emailHint = aIdentity;
-  mockedDoc.origin = aOrigin;
-  mockedDoc.wantIssuer = "firefox-accounts";
-  mockedDoc._mm = TEST_MESSAGE_MANAGER;
-
-  mockedDoc.doReady = partial(aDoFunc, "ready");
-  mockedDoc.doLogin = partial(aDoFunc, "login");
-  mockedDoc.doLogout = partial(aDoFunc, "logout");
-  mockedDoc.doError = partial(aDoFunc, "error");
-  mockedDoc.doCancel = partial(aDoFunc, "cancel");
-  mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown");
-
-  mockedDoc.RP = mockedDoc;
-
-  return mockedDoc;
-}
-
-// mimicking callback funtionality for ease of testing
-// this observer auto-removes itself after the observe function
-// is called, so this is meant to observe only ONE event.
-function makeObserver(aObserveTopic, aObserveFunc) {
-  let observer = {
-    // nsISupports provides type management in C++
-    // nsIObserver is to be an observer
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-    observe(aSubject, aTopic, aData) {
-      if (aTopic == aObserveTopic) {
-        aObserveFunc(aSubject, aTopic, aData);
-        Services.obs.removeObserver(observer, aObserveTopic);
-      }
-    }
-  };
-
-  Services.obs.addObserver(observer, aObserveTopic, false);
-}
-
-// set up the ID service with an identity with keypair and all
-// when ready, invoke callback with the identity
-function setup_test_identity(identity, cert, cb) {
-  // set up the store so that we're supposed to be logged in
-  let store = get_idstore();
-
-  function keyGenerated(err, kpo) {
-    store.addIdentity(identity, kpo, cert);
-    cb();
-  }
-
-  jwcrypto.generateKeyPair("DS160", keyGenerated);
-}
-
-// takes a list of functions and returns a function that
-// when called the first time, calls the first func,
-// then the next time the second, etc.
-function call_sequentially() {
-  let numCalls = 0;
-  let funcs = arguments;
-
-  return function() {
-    if (!funcs[numCalls]) {
-      let argString = Array.prototype.slice.call(arguments).join(",");
-      do_throw("Too many calls: " + argString);
-      return;
-    }
-    funcs[numCalls].apply(funcs[numCalls], arguments);
-    numCalls += 1;
-  };
-}
-
-/*
- * Setup a provisioning workflow with appropriate callbacks
- *
- * identity is the email we're provisioning.
- *
- * afterSetupCallback is required.
- *
- * doneProvisioningCallback is optional, if the caller
- * wants to be notified when the whole provisioning workflow is done
- *
- * frameCallbacks is optional, contains the callbacks that the sandbox
- * frame would provide in response to DOM calls.
- */
-function setup_provisioning(identity, afterSetupCallback, doneProvisioningCallback, callerCallbacks) {
-  IDService.reset();
-
-  let provId = uuid();
-  IDService.IDP._provisionFlows[provId] = {
-    identity,
-    idpParams: TEST_IDPPARAMS,
-    callback(err) {
-      if (doneProvisioningCallback)
-        doneProvisioningCallback(err);
-    },
-    sandbox: {
-      // Emulate the free() method on the iframe sandbox
-      free() {}
-    }
-  };
-
-  let caller = {};
-  caller.id = provId;
-  caller.doBeginProvisioningCallback = function(id, duration_s) {
-    if (callerCallbacks && callerCallbacks.beginProvisioningCallback)
-      callerCallbacks.beginProvisioningCallback(id, duration_s);
-  };
-  caller.doGenKeyPairCallback = function(pk) {
-    if (callerCallbacks && callerCallbacks.genKeyPairCallback)
-      callerCallbacks.genKeyPairCallback(pk);
-  };
-
-  afterSetupCallback(caller);
-}
-
-// Switch debug messages on by default
-var initialPrefDebugValue = false;
-try {
-  initialPrefDebugValue = Services.prefs.getBoolPref("toolkit.identity.debug");
-} catch (noPref) {}
-Services.prefs.setBoolPref("toolkit.identity.debug", true);
-
-// Switch on firefox accounts
-var initialPrefFXAValue = false;
-try {
-  initialPrefFXAValue = Services.prefs.getBoolPref("identity.fxaccounts.enabled");
-} catch (noPref) {}
-Services.prefs.setBoolPref("identity.fxaccounts.enabled", true);
-
-do_register_cleanup(function() {
-  log("restoring prefs to their initial values");
-  Services.prefs.setBoolPref("toolkit.identity.debug", initialPrefDebugValue);
-  Services.prefs.setBoolPref("identity.fxaccounts.enabled", initialPrefFXAValue);
-
-  // Pre-emptively shut down to clear resources.
-  if (typeof IdentityService !== "undefined") {
-    IdentityService.shutdown();
-  } else if (typeof IDService !== "undefined") {
-    IDService.shutdown();
-  }
-});
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_authentication.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
-                                  "resource://gre/modules/identity/jwcrypto.jsm");
-
-function test_begin_authentication_flow() {
-  do_test_pending();
-  let _provId = null;
-
-  // set up a watch, to be consistent
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {});
-  IDService.RP.watch(mockedDoc);
-
-  // The identity-auth notification is sent up to the UX from the
-  // _doAuthentication function.  Be ready to receive it and call
-  // beginAuthentication
-  makeObserver("identity-auth", function(aSubject, aTopic, aData) {
-    do_check_neq(aSubject, null);
-
-    do_check_eq(aSubject.wrappedJSObject.provId, _provId);
-
-    do_test_finished();
-    run_next_test();
-  });
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      _provId = caller.id;
-      IDService.IDP.beginProvisioning(caller);
-    }, function() {},
-    {
-      beginProvisioningCallback(email, duration_s) {
-
-        // let's say this user needs to authenticate
-        IDService.IDP._doAuthentication(_provId, {idpParams:TEST_IDPPARAMS});
-      }
-    }
-  );
-}
-
-function test_complete_authentication_flow() {
-  do_test_pending();
-  let _provId = null;
-  let _authId = null;
-  let id = TEST_USER;
-
-  let callbacksFired = false;
-  let loginStateChanged = false;
-  let identityAuthComplete = false;
-
-  // The result of authentication should be a successful login
-  IDService.reset();
-
-  setup_test_identity(id, TEST_CERT, function() {
-    // set it up so we're supposed to be logged in to TEST_URL
-
-    get_idstore().setLoginState(TEST_URL, true, id);
-
-    // When we authenticate, our ready callback will be fired.
-    // At the same time, a separate topic will be sent up to the
-    // the observer in the UI.  The test is complete when both
-    // events have occurred.
-    let mockedDoc = mock_doc(id, TEST_URL, call_sequentially(
-      function(action, params) {
-        do_check_eq(action, "ready");
-        do_check_eq(params, undefined);
-
-        // if notification already received by observer, test is done
-        callbacksFired = true;
-        if (loginStateChanged && identityAuthComplete) {
-          do_test_finished();
-          run_next_test();
-        }
-      }
-    ));
-
-    makeObserver("identity-auth-complete", function(aSubject, aTopic, aData) {
-      identityAuthComplete = true;
-      do_test_finished();
-      run_next_test();
-    });
-
-    makeObserver("identity-login-state-changed", function(aSubject, aTopic, aData) {
-      do_check_neq(aSubject, null);
-
-      do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
-      do_check_eq(aData, id);
-
-      // if callbacks in caller doc already fired, test is done.
-      loginStateChanged = true;
-      if (callbacksFired && identityAuthComplete) {
-        do_test_finished();
-        run_next_test();
-      }
-    });
-
-    IDService.RP.watch(mockedDoc);
-
-    // Create a provisioning flow for our auth flow to attach to
-    setup_provisioning(
-      TEST_USER,
-      function(provFlow) {
-        _provId = provFlow.id;
-
-        IDService.IDP.beginProvisioning(provFlow);
-      }, function() {},
-      {
-        beginProvisioningCallback(email, duration_s) {
-          // let's say this user needs to authenticate
-          IDService.IDP._doAuthentication(_provId, {idpParams:TEST_IDPPARAMS});
-
-          // test_begin_authentication_flow verifies that the right
-          // message is sent to the UI.  So that works.  Moving on,
-          // the UI calls setAuthenticationFlow ...
-          _authId = uuid();
-          IDService.IDP.setAuthenticationFlow(_authId, _provId);
-
-          // ... then the UI calls beginAuthentication ...
-          authCaller.id = _authId;
-          IDService.IDP._provisionFlows[_provId].caller = authCaller;
-          IDService.IDP.beginAuthentication(authCaller);
-        }
-      }
-    );
-  });
-
-  // A mock calling context
-  let authCaller = {
-    doBeginAuthenticationCallback: function doBeginAuthenticationCallback(identity) {
-      do_check_eq(identity, TEST_USER);
-      // completeAuthentication will emit "identity-auth-complete"
-      IDService.IDP.completeAuthentication(_authId);
-    },
-
-    doError(err) {
-      log("OW! My doError callback hurts!", err);
-    },
-  };
-
-}
-
-var TESTS = [];
-
-TESTS.push(test_begin_authentication_flow);
-TESTS.push(test_complete_authentication_flow);
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_firefox_accounts.js
+++ /dev/null
@@ -1,268 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/DOMIdentity.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "FirefoxAccounts",
-                                  "resource://gre/modules/identity/FirefoxAccounts.jsm");
-
-// Make the profile dir available; this is necessary so that
-// services/fxaccounts/FxAccounts.jsm can read and write its signed-in user
-// data.
-do_get_profile();
-
-function MockFXAManager() {
-  this.signedInUser = true;
-}
-MockFXAManager.prototype = {
-  getAssertion(audience) {
-    let result = this.signedInUser ? TEST_ASSERTION : null;
-    return Promise.resolve(result);
-  },
-
-  signOut() {
-    this.signedInUser = false;
-    return Promise.resolve(null);
-  },
-
-  signIn(user) {
-    this.signedInUser = user;
-    return Promise.resolve(user);
-  },
-}
-
-var originalManager = FirefoxAccounts.fxAccountsManager;
-FirefoxAccounts.fxAccountsManager = new MockFXAManager();
-do_register_cleanup(() => {
-  log("restoring fxaccountsmanager");
-  FirefoxAccounts.fxAccountsManager = originalManager;
-});
-
-function withNobodySignedIn() {
-  return FirefoxAccounts.fxAccountsManager.signOut();
-}
-
-function withSomebodySignedIn() {
-  return FirefoxAccounts.fxAccountsManager.signIn("Pertelote");
-}
-
-function test_overall() {
-  do_check_neq(FirefoxAccounts, null);
-  run_next_test();
-}
-
-function test_mock() {
-  do_test_pending();
-
-  withSomebodySignedIn().then(() => {
-    FirefoxAccounts.fxAccountsManager.getAssertion().then(assertion => {
-      do_check_eq(assertion, TEST_ASSERTION);
-      do_test_finished();
-      run_next_test();
-    });
-  });
-}
-
-function test_watch_signed_in() {
-  do_test_pending();
-
-  let received = [];
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, data) {
-    received.push([method, data]);
-
-    if (method == "ready") {
-      // confirm that we were signed in and then ready was called
-      do_check_eq(received.length, 2);
-      do_check_eq(received[0][0], "login");
-      do_check_eq(received[0][1], TEST_ASSERTION);
-      do_check_eq(received[1][0], "ready");
-      do_test_finished();
-      run_next_test();
-    }
-  });
-
-  withSomebodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-}
-
-function test_watch_signed_out() {
-  do_test_pending();
-
-  let received = [];
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, function(method) {
-    received.push(method);
-
-    if (method == "ready") {
-      // confirm that we were signed out and then ready was called
-      do_check_eq(received.length, 2);
-      do_check_eq(received[0], "logout");
-      do_check_eq(received[1], "ready");
-
-      do_test_finished();
-      run_next_test();
-    }
-  });
-
-  withNobodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-}
-
-function test_request() {
-  do_test_pending();
-
-  let received = [];
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, data) {
-    received.push([method, data]);
-
-    // On watch(), we are signed out.  Then we call request().
-    if (received.length === 2) {
-      do_check_eq(received[0][0], "logout");
-      do_check_eq(received[1][0], "ready");
-
-      // Pretend request() showed ux and the user signed in
-      withSomebodySignedIn().then(() => {
-        FirefoxAccounts.RP.request(mockedRP.id);
-      });
-    }
-
-    if (received.length === 3) {
-      do_check_eq(received[2][0], "login");
-      do_check_eq(received[2][1], TEST_ASSERTION);
-
-      do_test_finished();
-      run_next_test();
-    }
-  });
-
-  // First, call watch() with nobody signed in
-  withNobodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-}
-
-function test_logout() {
-  do_test_pending();
-
-  let received = [];
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, function(method) {
-    received.push(method);
-
-    // At first, watch() signs us in automatically.  Then we sign out.
-    if (received.length === 2) {
-      do_check_eq(received[0], "login");
-      do_check_eq(received[1], "ready");
-
-      FirefoxAccounts.RP.logout(mockedRP.id);
-    }
-
-    if (received.length === 3) {
-      do_check_eq(received[2], "logout");
-      do_test_finished();
-      run_next_test();
-    }
-  });
-
-  // First, call watch()
-  withSomebodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-}
-
-function test_error() {
-  do_test_pending();
-
-  // Mock the fxAccountsManager so that getAssertion rejects its promise and
-  // triggers our onerror handler.  (This is the method that's used internally
-  // by FirefoxAccounts.RP.request().)
-  let originalGetAssertion = FirefoxAccounts.fxAccountsManager.getAssertion;
-  FirefoxAccounts.fxAccountsManager.getAssertion = function(audience) {
-    return Promise.reject(new Error("barf!"));
-  };
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, message) {
-    // We will immediately receive an error, due to watch()'s attempt
-    // to getAssertion().
-    do_check_eq(method, "error");
-    do_check_true(/barf/.test(message));
-
-    // Put things back the way they were
-    FirefoxAccounts.fxAccountsManager.getAssertion = originalGetAssertion;
-
-    do_test_finished();
-    run_next_test();
-  });
-
-  // First, call watch()
-  withSomebodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-}
-
-function test_child_process_shutdown() {
-  do_test_pending();
-  let rpCount = FirefoxAccounts.RP._rpFlows.size;
-
-  makeObserver("identity-child-process-shutdown", (aTopic, aSubject, aData) => {
-    // Last of all, the shutdown observer message will be fired.
-    // This takes place after the RP has a chance to delete flows
-    // and clean up.
-    do_check_eq(FirefoxAccounts.RP._rpFlows.size, rpCount);
-    do_test_finished();
-    run_next_test();
-  });
-
-  let mockedRP = mock_fxa_rp(null, TEST_URL, (method) => {
-    // We should enter this function for 'ready' and 'child-process-shutdown'.
-    // After we have a chance to do our thing, the shutdown observer message
-    // will fire and be caught by the function above.
-    do_check_eq(FirefoxAccounts.RP._rpFlows.size, rpCount + 1);
-    switch (method) {
-      case "ready":
-        DOMIdentity._childProcessShutdown("my message manager");
-        break;
-
-      case "child-process-shutdown":
-        // We have to call this explicitly because there's no real
-        // dom window here.
-        FirefoxAccounts.RP.childProcessShutdown(mockedRP._mm);
-        break;
-
-      default:
-        break;
-    }
-  });
-
-  mockedRP._mm = "my message manager";
-  withSomebodySignedIn().then(() => {
-    FirefoxAccounts.RP.watch(mockedRP);
-  });
-
-  // fake a dom window context
-  DOMIdentity.newContext(mockedRP, mockedRP._mm);
-}
-
-var TESTS = [
-  test_overall,
-  test_mock,
-  test_watch_signed_in,
-  test_watch_signed_out,
-  test_request,
-  test_logout,
-  test_error,
-  test_child_process_shutdown,
-];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_identity.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-function test_overall() {
-  do_check_neq(IDService, null);
-  run_next_test();
-}
-
-function test_mock_doc() {
-  do_test_pending();
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {
-    do_check_eq(action, "coffee");
-    do_test_finished();
-    run_next_test();
-  });
-
-  mockedDoc.doCoffee();
-}
-
-function test_add_identity() {
-  IDService.reset();
-
-  IDService.addIdentity(TEST_USER);
-
-  let identities = IDService.RP.getIdentitiesForSite(TEST_URL);
-  do_check_eq(identities.result.length, 1);
-  do_check_eq(identities.result[0], TEST_USER);
-
-  run_next_test();
-}
-
-function test_select_identity() {
-  do_test_pending();
-
-  IDService.reset();
-
-  let id = "ishtar@mockmyid.com";
-  setup_test_identity(id, TEST_CERT, function() {
-    let gotAssertion = false;
-    let mockedDoc = mock_doc(null, TEST_URL, call_sequentially(
-      function(action, params) {
-        // ready emitted from first watch() call
-        do_check_eq(action, "ready");
-        do_check_null(params);
-      },
-      // first the login call
-      function(action, params) {
-        do_check_eq(action, "login");
-        do_check_neq(params, null);
-
-        // XXX - check that the assertion is for the right email
-
-        gotAssertion = true;
-      },
-      // then the ready call
-      function(action, params) {
-        do_check_eq(action, "ready");
-        do_check_null(params);
-
-        // we should have gotten the assertion already
-        do_check_true(gotAssertion);
-
-        do_test_finished();
-        run_next_test();
-      }));
-
-    // register the callbacks
-    IDService.RP.watch(mockedDoc);
-
-    // register the request UX observer
-    makeObserver("identity-request", function(aSubject, aTopic, aData) {
-      // do the select identity
-      // we expect this to succeed right away because of test_identity
-      // so we don't mock network requests or otherwise
-      IDService.selectIdentity(aSubject.wrappedJSObject.rpId, id);
-    });
-
-    // do the request
-    IDService.RP.request(mockedDoc.id, {});
-  });
-}
-
-function test_parse_good_email() {
-  var parsed = IDService.parseEmail("prime-minister@jed.gov");
-  do_check_eq(parsed.username, "prime-minister");
-  do_check_eq(parsed.domain, "jed.gov");
-  run_next_test();
-}
-
-function test_parse_bogus_emails() {
-  do_check_eq(null, IDService.parseEmail("@evil.org"));
-  do_check_eq(null, IDService.parseEmail("foo@bar@baz.com"));
-  do_check_eq(null, IDService.parseEmail("you@wellsfargo.com/accounts/transfer?to=dolske&amt=all"));
-  run_next_test();
-}
-
-var TESTS = [test_overall, test_mock_doc];
-
-TESTS.push(test_add_identity);
-TESTS.push(test_select_identity);
-TESTS.push(test_parse_good_email);
-TESTS.push(test_parse_bogus_emails);
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_identity_utils.js
+++ /dev/null
@@ -1,46 +0,0 @@
-
-"use strict";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/IdentityUtils.jsm");
-
-function test_check_deprecated() {
-  let options = {
-    id: 123,
-    loggedInEmail: "jed@foo.com",
-    pies: 42
-  };
-
-  do_check_true(checkDeprecated(options, "loggedInEmail"));
-  do_check_false(checkDeprecated(options, "flans"));
-
-  run_next_test();
-}
-
-function test_check_renamed() {
-  let options = {
-    id: 123,
-    loggedInEmail: "jed@foo.com",
-    pies: 42
-  };
-
-  checkRenamed(options, "loggedInEmail", "loggedInUser");
-
-  // It moves loggedInEmail to loggedInUser
-  do_check_false(!!options.loggedInEmail);
-  do_check_eq(options.loggedInUser, "jed@foo.com");
-
-  run_next_test();
-}
-
-var TESTS = [
-  test_check_deprecated,
-  test_check_renamed
-];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_load_modules.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const modules = [
-  "Identity.jsm",
-  "IdentityProvider.jsm",
-  "IdentityStore.jsm",
-  "jwcrypto.jsm",
-  "RelyingParty.jsm",
-  "Sandbox.jsm",
-];
-
-function run_test() {
-  for (let m of modules) {
-    let resource = "resource://gre/modules/identity/" + m;
-    Components.utils.import(resource, {});
-    do_print("loaded " + resource);
-  }
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_log_utils.js
+++ /dev/null
@@ -1,74 +0,0 @@
-
-"use strict";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-
-function toggle_debug() {
-  do_test_pending();
-
-  function Wrapper() {
-    this.init();
-  }
-  Wrapper.prototype = {
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
-
-    observe: function observe(aSubject, aTopic, aData) {
-      if (aTopic === "nsPref:changed") {
-        // race condition?
-        do_check_eq(Logger._debug, true);
-        do_test_finished();
-        run_next_test();
-      }
-    },
-
-    init() {
-      Services.prefs.addObserver("toolkit.identity.debug", this, false);
-    }
-  };
-
-  new Wrapper();
-  Services.prefs.setBoolPref("toolkit.identity.debug", true);
-}
-
-// test that things don't break
-
-function logAlias(...args) {
-  Logger.log.apply(Logger, ["log alias"].concat(args));
-}
-function reportErrorAlias(...args) {
-  Logger.reportError.apply(Logger, ["report error alias"].concat(args));
-}
-
-function test_log() {
-  Logger.log("log test", "I like pie");
-  do_test_finished();
-  run_next_test();
-}
-
-function test_reportError() {
-  Logger.reportError("log test", "We are out of pies!!!");
-  do_test_finished();
-  run_next_test();
-}
-
-function test_wrappers() {
-  logAlias("I like potatoes");
-  do_test_finished();
-  reportErrorAlias("Too much red bull");
-}
-
-var TESTS = [
-// XXX fix me
-//    toggle_debug,
-    test_log,
-    test_reportError,
-    test_wrappers,
-];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_minimalidentity.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "MinimalIDService",
-                                  "resource://gre/modules/identity/MinimalIdentity.jsm",
-                                  "IdentityService");
-
-Cu.import("resource://gre/modules/identity/LogUtils.jsm");
-Cu.import("resource://gre/modules/DOMIdentity.jsm");
-
-function log(...aMessageArgs) {
-  Logger.log.apply(Logger, ["test_minimalidentity"].concat(aMessageArgs));
-}
-
-function test_overall() {
-  do_check_neq(MinimalIDService, null);
-  run_next_test();
-}
-
-function test_mock_doc() {
-  do_test_pending();
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {
-    do_check_eq(action, "coffee");
-    do_test_finished();
-    run_next_test();
-  });
-
-  mockedDoc.doCoffee();
-}
-
-/*
- * Test that the "identity-controller-watch" signal is emitted correctly
- */
-function test_watch() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-watch", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
-    do_test_finished();
-    run_next_test();
-   });
-
-  MinimalIDService.RP.watch(mockedDoc);
-}
-
-/*
- * Test that the "identity-controller-request" signal is emitted correctly
- */
-function test_request() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-request", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
-    do_test_finished();
-    run_next_test();
-  });
-
-  MinimalIDService.RP.watch(mockedDoc);
-  MinimalIDService.RP.request(mockedDoc.id, {});
-}
-
-/*
- * Test that the forceAuthentication flag can be sent
- */
-function test_request_forceAuthentication() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-request", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
-    do_check_eq(aSubject.wrappedJSObject.forceAuthentication, true);
-    do_test_finished();
-    run_next_test();
-   });
-
-  MinimalIDService.RP.watch(mockedDoc);
-  MinimalIDService.RP.request(mockedDoc.id, {forceAuthentication: true});
-}
-
-/*
- * Test that the issuer can be forced
- */
-function test_request_forceIssuer() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-request", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.origin, TEST_URL);
-    do_check_eq(aSubject.wrappedJSObject.issuer, "https://jed.gov");
-    do_test_finished();
-    run_next_test();
-   });
-
-  MinimalIDService.RP.watch(mockedDoc);
-  MinimalIDService.RP.request(mockedDoc.id, {issuer: "https://jed.gov"});
-}
-
-/*
- * Test that the "identity-controller-logout" signal is emitted correctly
- */
-function test_logout() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-logout", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.id, mockedDoc.id);
-    do_test_finished();
-    run_next_test();
-  });
-
-  MinimalIDService.RP.watch(mockedDoc);
-  MinimalIDService.RP.logout(mockedDoc.id, {});
-}
-
-/*
- * Test that logout() before watch() fails gently
- */
-
-function test_logoutBeforeWatch() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-logout", function() {
-    do_throw("How can we logout when watch was not called?");
-  });
-
-  MinimalIDService.RP.logout(mockedDoc.id, {});
-  do_test_finished();
-  run_next_test();
-}
-
-/*
- * Test that request() before watch() fails gently
- */
-
-function test_requestBeforeWatch() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-  makeObserver("identity-controller-request", function() {
-    do_throw("How can we request when watch was not called?");
-  });
-
-  MinimalIDService.RP.request(mockedDoc.id, {});
-  do_test_finished();
-  run_next_test();
-}
-
-/*
- * Test that internal unwatch() before watch() fails gently
- */
-
-function test_unwatchBeforeWatch() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL);
-
-  MinimalIDService.RP.unwatch(mockedDoc.id, {});
-  do_test_finished();
-  run_next_test();
-}
-
-/*
- * Test that the RP flow is cleaned up on child process shutdown
- */
-
-function test_childProcessShutdown() {
-  do_test_pending();
-  let UNIQUE_MESSAGE_MANAGER = "i am a beautiful snowflake";
-  let initialRPCount = Object.keys(MinimalIDService.RP._rpFlows).length;
-
-  let mockedDoc = mock_doc(null, TEST_URL, (action, params) => {
-    if (action == "child-process-shutdown") {
-      // since there's no actual dom window connection, we have to
-      // do this bit manually here.
-      MinimalIDService.RP.childProcessShutdown(UNIQUE_MESSAGE_MANAGER);
-    }
-  });
-  mockedDoc._mm = UNIQUE_MESSAGE_MANAGER;
-
-  makeObserver("identity-controller-watch", function(aSubject, aTopic, aData) {
-    DOMIdentity._childProcessShutdown(UNIQUE_MESSAGE_MANAGER);
-  });
-
-  makeObserver("identity-child-process-shutdown", (aTopic, aSubject, aData) => {
-    do_check_eq(Object.keys(MinimalIDService.RP._rpFlows).length, initialRPCount);
-    do_test_finished();
-    run_next_test();
-  });
-
-  // fake a dom window context
-  DOMIdentity.newContext(mockedDoc, UNIQUE_MESSAGE_MANAGER);
-
-  MinimalIDService.RP.watch(mockedDoc);
-}
-
-var TESTS = [
-  test_overall,
-  test_mock_doc,
-  test_watch,
-  test_request,
-  test_request_forceAuthentication,
-  test_request_forceIssuer,
-  test_logout,
-  test_logoutBeforeWatch,
-  test_requestBeforeWatch,
-  test_unwatchBeforeWatch,
-  test_childProcessShutdown,
-];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_observer_topics.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * By their nature, these tests duplicate some of the functionality of
- * other tests for Identity, RelyingParty, and IdentityProvider.
- *
- * In particular, "identity-auth-complete" and
- * "identity-login-state-changed" are tested in test_authentication.js
- */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-function test_smoke() {
-  do_check_neq(IDService, null);
-  run_next_test();
-}
-
-function test_identity_request() {
-  // In response to navigator.id.request(), initiate a login with user
-  // interaction by notifying observers of 'identity-request'
-
-  do_test_pending();
-
-  IDService.reset();
-
-  let id = "landru@mockmyid.com";
-  setup_test_identity(id, TEST_CERT, function() {
-    // deliberately adding a trailing final slash on the domain
-    // to test path composition
-    let mockedDoc = mock_doc(null, "http://jed.gov/", function() {});
-
-    // by calling watch() we create an rp flow.
-    IDService.RP.watch(mockedDoc);
-
-    // register the request UX observer
-    makeObserver("identity-request", function(aSubject, aTopic, aData) {
-      do_check_eq(aTopic, "identity-request");
-      do_check_eq(aData, null);
-
-      // check that all the URLs are properly resolved
-      let subj = aSubject.wrappedJSObject;
-      do_check_eq(subj.privacyPolicy, "http://jed.gov/pp.html");
-      do_check_eq(subj.termsOfService, "http://jed.gov/tos.html");
-
-      do_test_finished();
-      run_next_test();
-    });
-
-    let requestOptions = {
-      privacyPolicy: "/pp.html",
-      termsOfService: "/tos.html"
-    };
-    IDService.RP.request(mockedDoc.id, requestOptions);
-  });
-
-}
-
-function test_identity_auth() {
-  // see test_authentication.js for "identity-auth-complete"
-  // and "identity-login-state-changed"
-
-  do_test_pending();
-  let _provId = "bogus";
-
-  // Simulate what would be returned by IDService._fetchWellKnownFile
-  // for a given domain.
-  let idpParams = {
-    domain: "myfavoriteflan.com",
-    idpParams: {
-      authentication: "/foo/authenticate.html",
-      provisioning: "/foo/provision.html"
-    }
-  };
-
-  // Create an RP flow
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {});
-  IDService.RP.watch(mockedDoc);
-
-  // The identity-auth notification is sent up to the UX from the
-  // _doAuthentication function.  Be ready to receive it and call
-  // beginAuthentication
-  makeObserver("identity-auth", function(aSubject, aTopic, aData) {
-    do_check_neq(aSubject, null);
-    do_check_eq(aTopic, "identity-auth");
-    do_check_eq(aData, "https://myfavoriteflan.com/foo/authenticate.html");
-
-    do_check_eq(aSubject.wrappedJSObject.provId, _provId);
-    do_test_finished();
-    run_next_test();
-  });
-
-  // Even though our provisioning flow id is bogus, IdentityProvider
-  // won't look at it until farther along in the authentication
-  // process.  So this test can pass with a fake provId.
-  IDService.IDP._doAuthentication(_provId, idpParams);
-}
-
-var TESTS = [
-    test_smoke,
-    test_identity_request,
-    test_identity_auth,
-  ];
-
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_provisioning.js
+++ /dev/null
@@ -1,242 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://gre/modules/identity/IdentityProvider.jsm");
-
-function check_provision_flow_done(provId) {
-  do_check_null(IdentityProvider._provisionFlows[provId]);
-}
-
-function test_begin_provisioning() {
-  do_test_pending();
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      // call .beginProvisioning()
-      IdentityProvider.beginProvisioning(caller);
-    }, function() {},
-    {
-      beginProvisioningCallback(email, duration_s) {
-        do_check_eq(email, TEST_USER);
-        do_check_true(duration_s > 0);
-        do_check_true(duration_s <= (24 * 3600));
-
-        do_test_finished();
-        run_next_test();
-      }
-    });
-}
-
-function test_raise_provisioning_failure() {
-  do_test_pending();
-  let _callerId = null;
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      // call .beginProvisioning()
-      _callerId = caller.id;
-      IdentityProvider.beginProvisioning(caller);
-    }, function(err) {
-      // this should be invoked with a populated error
-      do_check_neq(err, null);
-      do_check_true(err.indexOf("can't authenticate this email") > -1);
-
-      do_test_finished();
-      run_next_test();
-    },
-    {
-      beginProvisioningCallback(email, duration_s) {
-        // raise the failure as if we can't provision this email
-        IdentityProvider.raiseProvisioningFailure(_callerId, "can't authenticate this email");
-      }
-    });
-}
-
-function test_genkeypair_before_begin_provisioning() {
-  do_test_pending();
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      // call genKeyPair without beginProvisioning
-      IdentityProvider.genKeyPair(caller.id);
-    },
-    // expect this to be called with an error
-    function(err) {
-      do_check_neq(err, null);
-
-      do_test_finished();
-      run_next_test();
-    },
-    {
-      // this should not be called at all!
-      genKeyPairCallback(pk) {
-        // a test that will surely fail because we shouldn't be here.
-        do_check_true(false);
-
-        do_test_finished();
-        run_next_test();
-      }
-    }
-  );
-}
-
-function test_genkeypair() {
-  do_test_pending();
-  let _callerId = null;
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      _callerId = caller.id;
-      IdentityProvider.beginProvisioning(caller);
-    },
-    function(err) {
-      // should not be called!
-      do_check_true(false);
-
-      do_test_finished();
-      run_next_test();
-    },
-    {
-      beginProvisioningCallback(email, time_s) {
-        IdentityProvider.genKeyPair(_callerId);
-      },
-      genKeyPairCallback(kp) {
-        do_check_neq(kp, null);
-
-        // yay!
-        do_test_finished();
-        run_next_test();
-      }
-    }
-  );
-}
-
-// we've already ensured that genkeypair can't be called
-// before beginProvisioning, so this test should be enough
-// to ensure full sequential call of the 3 APIs.
-function test_register_certificate_before_genkeypair() {
-  do_test_pending();
-  let _callerID = null;
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      // do the right thing for beginProvisioning
-      _callerID = caller.id;
-      IdentityProvider.beginProvisioning(caller);
-    },
-    // expect this to be called with an error
-    function(err) {
-      do_check_neq(err, null);
-
-      do_test_finished();
-      run_next_test();
-    },
-    {
-      beginProvisioningCallback(email, duration_s) {
-        // now we try to register cert but no keygen has been done
-        IdentityProvider.registerCertificate(_callerID, "fake-cert");
-      }
-    }
-  );
-}
-
-function test_register_certificate() {
-  do_test_pending();
-  let _callerId = null;
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      _callerId = caller.id;
-      IdentityProvider.beginProvisioning(caller);
-    },
-    function(err) {
-      // we should be cool!
-      do_check_null(err);
-
-      // check that the cert is there
-      let identity = get_idstore().fetchIdentity(TEST_USER);
-      do_check_neq(identity, null);
-      do_check_eq(identity.cert, "fake-cert-42");
-
-      do_execute_soon(function check_done() {
-        // cleanup will happen after the callback is called
-        check_provision_flow_done(_callerId);
-
-        do_test_finished();
-        run_next_test();
-      });
-    },
-    {
-      beginProvisioningCallback(email, duration_s) {
-        IdentityProvider.genKeyPair(_callerId);
-      },
-      genKeyPairCallback(pk) {
-        IdentityProvider.registerCertificate(_callerId, "fake-cert-42");
-      }
-    }
-  );
-}
-
-
-function test_get_assertion_after_provision() {
-  do_test_pending();
-  let _callerId = null;
-
-  setup_provisioning(
-    TEST_USER,
-    function(caller) {
-      _callerId = caller.id;
-      IdentityProvider.beginProvisioning(caller);
-    },
-    function(err) {
-      // we should be cool!
-      do_check_null(err);
-
-      // check that the cert is there
-      let identity = get_idstore().fetchIdentity(TEST_USER);
-      do_check_neq(identity, null);
-      do_check_eq(identity.cert, "fake-cert-42");
-
-      do_execute_soon(function check_done() {
-        // cleanup will happen after the callback is called
-        check_provision_flow_done(_callerId);
-
-        do_test_finished();
-        run_next_test();
-      });
-    },
-    {
-      beginProvisioningCallback(email, duration_s) {
-        IdentityProvider.genKeyPair(_callerId);
-      },
-      genKeyPairCallback(pk) {
-        IdentityProvider.registerCertificate(_callerId, "fake-cert-42");
-      }
-    }
-  );
-
-}
-
-var TESTS = [];
-
-TESTS.push(test_begin_provisioning);
-TESTS.push(test_raise_provisioning_failure);
-TESTS.push(test_genkeypair_before_begin_provisioning);
-TESTS.push(test_genkeypair);
-TESTS.push(test_register_certificate_before_genkeypair);
-TESTS.push(test_register_certificate);
-TESTS.push(test_get_assertion_after_provision);
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_relying_party.js
+++ /dev/null
@@ -1,255 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "RelyingParty",
-                                  "resource://gre/modules/identity/RelyingParty.jsm");
-
-function resetState() {
-  get_idstore().reset();
-  RelyingParty.reset();
-}
-
-function test_watch_loggedin_ready() {
-  do_test_pending();
-
-  resetState();
-
-  let id = TEST_USER;
-  setup_test_identity(id, TEST_CERT, function() {
-    let store = get_idstore();
-
-    // set it up so we're supposed to be logged in to TEST_URL
-    store.setLoginState(TEST_URL, true, id);
-    RelyingParty.watch(mock_doc(id, TEST_URL, function(action, params) {
-      do_check_eq(action, "ready");
-      do_check_eq(params, undefined);
-
-      do_test_finished();
-      run_next_test();
-    }));
-  });
-}
-
-function test_watch_loggedin_login() {
-  do_test_pending();
-
-  resetState();
-
-  let id = TEST_USER;
-  setup_test_identity(id, TEST_CERT, function() {
-    let store = get_idstore();
-
-    // set it up so we're supposed to be logged in to TEST_URL
-    store.setLoginState(TEST_URL, true, id);
-
-    // check for first a login() call, then a ready() call
-    RelyingParty.watch(mock_doc(null, TEST_URL, call_sequentially(
-      function(action, params) {
-        do_check_eq(action, "login");
-        do_check_neq(params, null);
-      },
-      function(action, params) {
-        do_check_eq(action, "ready");
-        do_check_null(params);
-
-        do_test_finished();
-        run_next_test();
-      }
-    )));
-  });
-}
-
-function test_watch_loggedin_logout() {
-  do_test_pending();
-
-  resetState();
-
-  let id = TEST_USER;
-  let other_id = "otherid@foo.com";
-  setup_test_identity(other_id, TEST_CERT, function() {
-    setup_test_identity(id, TEST_CERT, function() {
-      let store = get_idstore();
-
-      // set it up so we're supposed to be logged in to TEST_URL
-      // with id, not other_id
-      store.setLoginState(TEST_URL, true, id);
-
-      // this should cause a login with an assertion for id,
-      // not for other_id
-      RelyingParty.watch(mock_doc(other_id, TEST_URL, call_sequentially(
-        function(action, params) {
-          do_check_eq(action, "login");
-          do_check_neq(params, null);
-        },
-        function(action, params) {
-          do_check_eq(action, "ready");
-          do_check_null(params);
-
-          do_test_finished();
-          run_next_test();
-        }
-      )));
-    });
-  });
-}
-
-function test_watch_notloggedin_ready() {
-  do_test_pending();
-
-  resetState();
-
-  RelyingParty.watch(mock_doc(null, TEST_URL, function(action, params) {
-    do_check_eq(action, "ready");
-    do_check_eq(params, undefined);
-
-    do_test_finished();
-    run_next_test();
-  }));
-}
-
-function test_watch_notloggedin_logout() {
-  do_test_pending();
-
-  resetState();
-
-  RelyingParty.watch(mock_doc(TEST_USER, TEST_URL, call_sequentially(
-    function(action, params) {
-      do_check_eq(action, "logout");
-      do_check_eq(params, undefined);
-
-      let store = get_idstore();
-      do_check_null(store.getLoginState(TEST_URL));
-    },
-    function(action, params) {
-      do_check_eq(action, "ready");
-      do_check_eq(params, undefined);
-      do_test_finished();
-      run_next_test();
-    }
-  )));
-}
-
-function test_request() {
-  do_test_pending();
-
-  // set up a watch, to be consistent
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {
-    // this isn't going to be called for now
-    // XXX but it is called - is that bad?
-  });
-
-  RelyingParty.watch(mockedDoc);
-
-  // be ready for the UX identity-request notification
-  makeObserver("identity-request", function(aSubject, aTopic, aData) {
-    do_check_neq(aSubject, null);
-
-    do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
-
-    do_test_finished();
-    run_next_test();
-  });
-
-  RelyingParty.request(mockedDoc.id, {});
-}
-
-/*
- * ensure the forceAuthentication param can be passed through
- */
-function test_request_forceAuthentication() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {});
-
-  RelyingParty.watch(mockedDoc);
-
-  makeObserver("identity-request", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.forceAuthentication, true);
-    do_test_finished();
-    run_next_test();
-  });
-
-  RelyingParty.request(mockedDoc.id, {forceAuthentication: true});
-}
-
-/*
- * ensure the issuer can be forced
- */
-function test_request_forceIssuer() {
-  do_test_pending();
-
-  let mockedDoc = mock_doc(null, TEST_URL, function(action, params) {});
-
-  RelyingParty.watch(mockedDoc);
-
-  makeObserver("identity-request", function(aSubject, aTopic, aData) {
-    do_check_eq(aSubject.wrappedJSObject.rpId, mockedDoc.id);
-    do_check_eq(aSubject.wrappedJSObject.issuer, "https://ozten.co.uk");
-    do_test_finished();
-    run_next_test();
-  });
-
-  RelyingParty.request(mockedDoc.id, {issuer: "https://ozten.co.uk"});
-}
-function test_logout() {
-  do_test_pending();
-
-  resetState();
-
-  let id = TEST_USER;
-  setup_test_identity(id, TEST_CERT, function() {
-    let store = get_idstore();
-
-    // set it up so we're supposed to be logged in to TEST_URL
-    store.setLoginState(TEST_URL, true, id);
-
-    let doLogout;
-    let mockedDoc = mock_doc(id, TEST_URL, call_sequentially(
-      function(action, params) {
-        do_check_eq(action, "ready");
-        do_check_eq(params, undefined);
-
-        do_timeout(100, doLogout);
-      },
-      function(action, params) {
-        do_check_eq(action, "logout");
-        do_check_eq(params, undefined);
-      },
-      function(action, params) {
-        do_check_eq(action, "ready");
-        do_check_eq(params, undefined);
-
-        do_test_finished();
-        run_next_test();
-      }));
-
-    doLogout = function() {
-      RelyingParty.logout(mockedDoc.id);
-      do_check_false(store.getLoginState(TEST_URL).isLoggedIn);
-      do_check_eq(store.getLoginState(TEST_URL).email, TEST_USER);
-    };
-
-    RelyingParty.watch(mockedDoc);
-  });
-}
-
-var TESTS = [
-  test_watch_loggedin_ready,
-  test_watch_loggedin_login,
-  test_watch_loggedin_logout,
-  test_watch_notloggedin_ready,
-  test_watch_notloggedin_logout,
-  test_request,
-  test_request_forceAuthentication,
-  test_request_forceIssuer,
-  test_logout,
-];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_store.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-function test_id_store() {
-  // XXX - this is ugly, peaking in like this into IDService
-  // probably should instantiate our own.
-  var store = get_idstore();
-
-  // try adding an identity
-  store.addIdentity(TEST_USER, TEST_PRIVKEY, TEST_CERT);
-  do_check_neq(store.getIdentities()[TEST_USER], null);
-  do_check_eq(store.getIdentities()[TEST_USER].cert, TEST_CERT);
-
-  // does fetch identity work?
-  do_check_neq(store.fetchIdentity(TEST_USER), null);
-  do_check_eq(store.fetchIdentity(TEST_USER).cert, TEST_CERT);
-
-  // clear the cert should keep the identity but not the cert
-  store.clearCert(TEST_USER);
-  do_check_neq(store.getIdentities()[TEST_USER], null);
-  do_check_null(store.getIdentities()[TEST_USER].cert);
-
-  // remove it should remove everything
-  store.removeIdentity(TEST_USER);
-  do_check_eq(store.getIdentities()[TEST_USER], undefined);
-
-  // act like we're logged in to TEST_URL
-  store.setLoginState(TEST_URL, true, TEST_USER);
-  do_check_neq(store.getLoginState(TEST_URL), null);
-  do_check_true(store.getLoginState(TEST_URL).isLoggedIn);
-  do_check_eq(store.getLoginState(TEST_URL).email, TEST_USER);
-
-  // log out
-  store.setLoginState(TEST_URL, false, TEST_USER);
-  do_check_neq(store.getLoginState(TEST_URL), null);
-  do_check_false(store.getLoginState(TEST_URL).isLoggedIn);
-
-  // email is still set
-  do_check_eq(store.getLoginState(TEST_URL).email, TEST_USER);
-
-  // not logged into other site
-  do_check_null(store.getLoginState(TEST_URL2));
-
-  // clear login state
-  store.clearLoginState(TEST_URL);
-  do_check_null(store.getLoginState(TEST_URL));
-  do_check_null(store.getLoginState(TEST_URL2));
-
-  run_next_test();
-}
-
-var TESTS = [test_id_store, ];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/test_well-known.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "IDService",
-                                  "resource://gre/modules/identity/Identity.jsm",
-                                  "IdentityService");
-
-const WELL_KNOWN_PATH = "/.well-known/browserid";
-
-var SERVER_PORT = 8080;
-
-// valid IDP
-function test_well_known_1() {
-  do_test_pending();
-
-  let server = new HttpServer();
-  server.registerFile(WELL_KNOWN_PATH, do_get_file("data/idp_1" + WELL_KNOWN_PATH));
-  server.start(SERVER_PORT);
-  let hostPort = "localhost:" + SERVER_PORT;
-
-  function check_well_known(aErr, aCallbackObj) {
-    do_check_null(aErr);
-    do_check_eq(aCallbackObj.domain, hostPort);
-    let idpParams = aCallbackObj.idpParams;
-    do_check_eq(idpParams["public-key"].algorithm, "RS");
-    do_check_eq(idpParams.authentication, "/browserid/sign_in.html");
-    do_check_eq(idpParams.provisioning, "/browserid/provision.html");
-
-    do_test_finished();
-    server.stop(run_next_test);
-  }
-
-  IDService._fetchWellKnownFile(hostPort, check_well_known, "http");
-}
-
-// valid domain, non-exixtent browserid file
-function test_well_known_404() {
-  do_test_pending();
-
-  let server = new HttpServer();
-  // Don't register the well-known file
-  // Change ports to avoid HTTP caching
-  SERVER_PORT++;
-  server.start(SERVER_PORT);
-
-  let hostPort = "localhost:" + SERVER_PORT;
-
-  function check_well_known_404(aErr, aCallbackObj) {
-    do_check_eq("Error", aErr);
-    do_check_eq(undefined, aCallbackObj);
-    do_test_finished();
-    server.stop(run_next_test);
-  }
-
-  IDService._fetchWellKnownFile(hostPort, check_well_known_404, "http");
-}
-
-// valid domain, invalid browserid file (no "provisioning" member)
-function test_well_known_invalid_1() {
-  do_test_pending();
-
-  let server = new HttpServer();
-  server.registerFile(WELL_KNOWN_PATH, do_get_file("data/idp_invalid_1" + WELL_KNOWN_PATH));
-  // Change ports to avoid HTTP caching
-  SERVER_PORT++;
-  server.start(SERVER_PORT);
-
-  let hostPort = "localhost:" + SERVER_PORT;
-
-  function check_well_known_invalid_1(aErr, aCallbackObj) {
-    // check for an error message
-    do_check_true(aErr && aErr.length > 0);
-    do_check_eq(undefined, aCallbackObj);
-    do_test_finished();
-    server.stop(run_next_test);
-  }
-
-  IDService._fetchWellKnownFile(hostPort, check_well_known_invalid_1, "http");
-}
-
-var TESTS = [test_well_known_1, test_well_known_404, test_well_known_invalid_1];
-
-TESTS.forEach(add_test);
-
-function run_test() {
-  run_next_test();
-}
deleted file mode 100644
--- a/toolkit/identity/tests/unit/xpcshell.ini
+++ /dev/null
@@ -1,23 +0,0 @@
-[DEFAULT]
-head = head_identity.js
-skip-if = (appname != "b2g" || toolkit == 'gonk')
-support-files =
-  data/idp_1/.well-known/browserid
-  data/idp_invalid_1/.well-known/browserid
-
-# Test load modules first so syntax failures are caught early.
-[test_load_modules.js]
-[test_minimalidentity.js]
-[test_firefox_accounts.js]
-
-[test_identity_utils.js]
-[test_log_utils.js]
-[test_authentication.js]
-[test_crypto_service.js]
-[test_identity.js]
-[test_jwcrypto.js]
-[test_observer_topics.js]
-[test_provisioning.js]
-[test_relying_party.js]
-[test_store.js]
-[test_well-known.js]
--- a/toolkit/moz.build
+++ b/toolkit/moz.build
@@ -3,17 +3,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/.
 
 DIRS += [
     'components',
     'content',
     'forgetaboutsite',
-    'identity',
     'locales',
     'modules',
     'mozapps/downloads',
     'mozapps/extensions',
     'mozapps/handling',
     'mozapps/preferences',
     'pluginproblem',
     'profile',
--- a/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm
+++ b/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm
@@ -933,21 +933,21 @@ Object.defineProperty(this, "isAddonPart
     }
 
     if (blocklist && blocklist.indexOf(aAddon.id) > -1) {
       return false;
     }
 
     let policy = RolloutPolicy[policyId];
 
+    if (aAddon.mpcOptedOut == true) {
+      return false;
+    }
+
     if (policy.alladdons) {
-      if (aAddon.mpcOptedOut == true) {
-        return false;
-      }
-
       return true;
     }
 
     if (policy.webextensions && aAddon.type == "webextension") {
       return true;
     }
 
     if (policy.mpc && aAddon.multiprocessCompatible) {
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -101,18 +101,16 @@
   "hawkclient.js": ["HawkClient"],
   "hawkrequest.js": ["HAWKAuthenticatedRESTRequest", "deriveHawkCredentials"],
   "HelperApps.jsm": ["App", "HelperApps"],
   "history.js": ["HistoryEngine", "HistoryRec"],
   "history.jsm": ["HistoryEntry", "DumpHistory"],
   "Http.jsm": ["httpRequest", "percentEncode"],
   "httpd.js": ["HTTP_400", "HTTP_401", "HTTP_402", "HTTP_403", "HTTP_404", "HTTP_405", "HTTP_406", "HTTP_407", "HTTP_408", "HTTP_409", "HTTP_410", "HTTP_411", "HTTP_412", "HTTP_413", "HTTP_414", "HTTP_415", "HTTP_417", "HTTP_500", "HTTP_501", "HTTP_502", "HTTP_503", "HTTP_504", "HTTP_505", "HttpError", "HttpServer"],
   "identity.js": ["IdentityManager"],
-  "Identity.jsm": ["IdentityService"],
-  "IdentityUtils.jsm": ["checkDeprecated", "checkRenamed", "getRandomId", "objectCopy", "makeMessageObject"],
   "import_module.jsm": ["MODULE_IMPORTED", "MODULE_URI", "SUBMODULE_IMPORTED", "same_scope", "SUBMODULE_IMPORTED_TO_SCOPE"],
   "import_sub_module.jsm": ["SUBMODULE_IMPORTED", "test_obj"],
   "InlineSpellChecker.jsm": ["InlineSpellChecker", "SpellCheckHelper"],
   "JNI.jsm": ["JNI", "android_log"],
   "jpakeclient.js": ["JPAKEClient", "SendCredentialsController"],
   "Jsbeautify.jsm": ["jsBeautify"],
   "jsdebugger.jsm": ["addDebuggerToGlobal"],
   "json2.js": ["JSON"],
@@ -134,17 +132,16 @@
   "lz4_internal.js": ["Primitives"],
   "main.js": ["Weave"],
   "MatchPattern.jsm": ["MatchPattern", "MatchGlobs", "MatchURLFilters"],
   "mcc_iso3166_table.jsm": ["MCC_ISO3166_TABLE"],
   "message.js": ["Command", "Message", "MessageOrigin", "Response"],
   "Messaging.jsm": ["sendMessageToJava", "Messaging"],
   "microformat-shiv.js": ["Microformats"],
   "MigrationUtils.jsm": ["MigrationUtils", "MigratorPrototype"],
-  "MinimalIdentity.jsm": ["IdentityService"],
   "mozelement.js": ["Elem", "Selector", "ID", "Link", "XPath", "Name", "Lookup", "MozMillElement", "MozMillCheckBox", "MozMillRadio", "MozMillDropList", "MozMillTextBox", "subclasses"],
   "mozmill.js": ["controller", "utils", "elementslib", "os", "getBrowserController", "newBrowserController", "getAddonsController", "getPreferencesController", "newMail3PaneController", "getMail3PaneController", "wm", "platform", "getAddrbkController", "getMsgComposeController", "getDownloadsController", "Application", "findElement", "getPlacesController", "isMac", "isLinux", "isWindows", "firePythonCallback", "getAddons"],
   "msgbroker.js": ["addListener", "addObject", "removeListener", "sendMessage", "log", "pass", "fail"],
   "MulticastDNSAndroid.jsm": ["MulticastDNS"],
   "NativeMessaging.jsm": ["HostManifestManager", "NativeApp"],
   "NetworkPrioritizer.jsm": ["trackBrowserWindow"],
   "NotificationDB.jsm": [],
   "nsFormAutoCompleteResult.jsm": ["FormAutoCompleteResult"],
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -100,16 +100,17 @@ class nsDefaultComparator <nsDocLoader::
   PLDHashTable::MatchEntryStub,
   PLDHashTable::MoveEntryStub,
   nsDocLoader::RequestInfoHashClearEntry,
   nsDocLoader::RequestInfoHashInitEntry
 };
 
 nsDocLoader::nsDocLoader()
   : mParent(nullptr),
+    mProgressStateFlags(0),
     mCurrentSelfProgress(0),
     mMaxSelfProgress(0),
     mCurrentTotalProgress(0),
     mMaxTotalProgress(0),
     mRequestInfoHash(&sRequestInfoHashOps, sizeof(nsRequestInfo)),
     mCompletedTotalProgress(0),
     mIsLoadingDocument(false),
     mIsRestoringDocument(false),
--- a/uriloader/prefetch/nsPrefetchService.cpp
+++ b/uriloader/prefetch/nsPrefetchService.cpp
@@ -151,17 +151,23 @@ nsPrefetchNode::OpenChannel()
     if (httpChannel) {
         httpChannel->SetReferrerWithPolicy(mReferrerURI, referrerPolicy);
         httpChannel->SetRequestHeader(
             NS_LITERAL_CSTRING("X-Moz"),
             NS_LITERAL_CSTRING("prefetch"),
             false);
     }
 
-    return mChannel->AsyncOpen2(this);
+    rv = mChannel->AsyncOpen2(this);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      // Drop the ref to the channel, because we don't want to end up with
+      // cycles through it.
+      mChannel = nullptr;
+    }
+    return rv;
 }
 
 nsresult
 nsPrefetchNode::CancelChannel(nsresult error)
 {
     mChannel->Cancel(error);
     mChannel = nullptr;
 
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -21,28 +21,37 @@
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/CompositeTimelineMarker.h"
 
 using namespace mozilla;
 
 static bool sShowPreviousPage = true;
 
 nsView::nsView(nsViewManager* aViewManager, nsViewVisibility aVisibility)
+  : mViewManager(aViewManager)
+  , mParent(nullptr)
+  , mNextSibling(nullptr)
+  , mFirstChild(nullptr)
+  , mFrame(nullptr)
+  , mDirtyRegion(nullptr)
+  , mZIndex(0)
+  , mVis(aVisibility)
+  , mPosX(0)
+  , mPosY(0)
+  , mVFlags(0)
+  , mWidgetIsTopLevel(false)
+  , mForcedRepaint(false)
+  , mNeedsWindowPropertiesSync(false)
 {
   MOZ_COUNT_CTOR(nsView);
 
-  mVis = aVisibility;
   // Views should be transparent by default. Not being transparent is
   // a promise that the view will paint all its pixels opaquely. Views
   // should make this promise explicitly by calling
   // SetViewContentTransparency.
-  mVFlags = 0;
-  mViewManager = aViewManager;
-  mDirtyRegion = nullptr;
-  mWidgetIsTopLevel = false;
 
   static bool sShowPreviousPageInitialized = false;
   if (!sShowPreviousPageInitialized) {
     Preferences::AddBoolVarCache(&sShowPreviousPage, "layout.show_previous_page", true);
     sShowPreviousPageInitialized = true;
   }
 }
 
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -56,17 +56,19 @@ enum nsViewVisibility {
 class nsView final : public nsIWidgetListener
 {
 public:
   friend class nsViewManager;
 
   typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
   typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
+  void operator delete(void* ptr) {
+    ::operator delete(ptr);
+  }
 
   /**
    * Get the view manager which "owns" the view.
    * This method might require some expensive traversal work in the future. If you can get the
    * view manager from somewhere else, do that instead.
    * @result the view manager
    */
   nsViewManager* GetViewManager() const { return mViewManager; }
--- a/view/nsViewManager.cpp
+++ b/view/nsViewManager.cpp
@@ -52,30 +52,31 @@ using namespace mozilla::layers;
 
 #undef DEBUG_MOUSE_LOCATION
 
 // Weakly held references to all of the view managers
 nsTArray<nsViewManager*>* nsViewManager::gViewManagers = nullptr;
 uint32_t nsViewManager::gLastUserEventTime = 0;
 
 nsViewManager::nsViewManager()
-  : mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
+  : mPresShell(nullptr)
+  , mDelayedResize(NSCOORD_NONE, NSCOORD_NONE)
+  , mRootView(nullptr)
+  , mRootViewManager(this)
+  , mRefreshDisableCount(0)
+  , mPainting(false)
+  , mRecursiveRefreshPending(false)
+  , mHasPendingWidgetGeometryChanges(false)
 {
-  mRootViewManager = this;
   if (gViewManagers == nullptr) {
     // Create an array to hold a list of view managers
     gViewManagers = new nsTArray<nsViewManager*>;
   }
  
   gViewManagers->AppendElement(this);
-
-  // NOTE:  we use a zeroing operator new, so all data members are
-  // assumed to be cleared here.
-  mHasPendingWidgetGeometryChanges = false;
-  mRecursiveRefreshPending = false;
 }
 
 nsViewManager::~nsViewManager()
 {
   if (mRootView) {
     // Destroy any remaining views
     mRootView->Destroy();
     mRootView = nullptr;
--- a/view/nsViewManager.h
+++ b/view/nsViewManager.h
@@ -25,18 +25,16 @@ class nsViewManager final
 {
   ~nsViewManager();
 public:
   friend class nsView;
 
   typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
   typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
 
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
   NS_INLINE_DECL_REFCOUNTING(nsViewManager)
 
   nsViewManager();
 
   /**
    * Initialize the ViewManager
    * Note: this instance does not hold a reference to the presshell
    * because it holds a reference to this instance.
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -344,33 +344,33 @@ nsBaseWidget::OnRenderingDeviceReset(uin
   // If the existing compositor does not use acceleration, and this widget
   // should not be accelerated, then there's no point in resetting.
   //
   // Note that if this widget should be accelerated, but instead has a basic
   // compositor, we still reset just in case we're now in the position to get
   // accelerated layers again.
   RefPtr<ClientLayerManager> clm = mLayerManager->AsClientLayerManager();
   if (!ComputeShouldAccelerate() &&
-      clm->GetTextureFactoryIdentifier().mParentBackend != LayersBackend::LAYERS_BASIC)
+      clm->GetCompositorBackendType() == LayersBackend::LAYERS_BASIC)
   {
     return;
   }
 
   // Recreate the compositor.
   TextureFactoryIdentifier identifier;
   if (!mCompositorSession->Reset(backendHints, aSeqNo, &identifier)) {
     // No action was taken, so we don't have to do anything.
     return;
   }
 
   // Invalidate all layers.
   FrameLayerBuilder::InvalidateAllLayers(mLayerManager);
 
   // Update the texture factory identifier.
-  clm->UpdateTextureFactoryIdentifier(identifier);
+  clm->UpdateTextureFactoryIdentifier(identifier, aSeqNo);
   ImageBridgeChild::IdentifyCompositorTextureHost(identifier);
   gfx::VRManagerChild::IdentifyTextureHost(identifier);
 }
 
 void
 nsBaseWidget::FreeShutdownObserver()
 {
   if (mShutdownObserver) {
@@ -1346,17 +1346,17 @@ void nsBaseWidget::CreateCompositor(int 
       NS_WARNING("Failed to create an OMT compositor.");
       DestroyCompositor();
       mLayerManager = nullptr;
       return;
     }
 
     lf->SetShadowManager(shadowManager);
     if (ClientLayerManager* clm = lm->AsClientLayerManager()) {
-      clm->UpdateTextureFactoryIdentifier(textureFactoryIdentifier);
+      clm->UpdateTextureFactoryIdentifier(textureFactoryIdentifier, 0);
     }
     // Some popup or transparent widgets may use a different backend than the
     // compositors used with ImageBridge and VR (and more generally web content).
     if (WidgetTypeSupportsAcceleration()) {
       ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
       gfx::VRManagerChild::IdentifyTextureHost(textureFactoryIdentifier);
     }
   }
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -32,16 +32,19 @@ namespace js {
 struct Class;
 } // namespace js
 
 namespace mozilla {
 
 class JSGCThingParticipant: public nsCycleCollectionParticipant
 {
 public:
+  constexpr JSGCThingParticipant()
+    : nsCycleCollectionParticipant(false) {}
+
   NS_IMETHOD_(void) Root(void*) override
   {
     MOZ_ASSERT(false, "Don't call Root on GC things");
   }
 
   NS_IMETHOD_(void) Unlink(void*) override
   {
     MOZ_ASSERT(false, "Don't call Unlink on GC things, as they may be dead");
@@ -61,17 +64,17 @@ public:
     override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(JSGCThingParticipant)
 };
 
 class JSZoneParticipant : public nsCycleCollectionParticipant
 {
 public:
-  constexpr JSZoneParticipant(): nsCycleCollectionParticipant()
+  constexpr JSZoneParticipant(): nsCycleCollectionParticipant(false)
   {
   }
 
   NS_IMETHOD_(void) Root(void*) override
   {
     MOZ_ASSERT(false, "Don't call Root on GC things");
   }
 
--- a/xpcom/base/nsAgg.h
+++ b/xpcom/base/nsAgg.h
@@ -73,16 +73,19 @@ private:                                
                                                                             \
 public:                                                                     \
 
 #define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class)                   \
 class NS_CYCLE_COLLECTION_INNERCLASS                                        \
  : public nsXPCOMCycleCollectionParticipant                                 \
 {                                                                           \
 public:                                                                     \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)    \
+    : nsXPCOMCycleCollectionParticipant(aSkip) {}                           \
+                                                                            \
   NS_IMETHOD_(void) Unlink(void *p) override;                               \
   NS_IMETHOD TraverseNative(void *p, nsCycleCollectionTraversalCallback &cb)\
     override;                                                               \
   NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(_class)                        \
   NS_IMETHOD_(void) DeleteCycleCollectable(void* p) override                \
   {                                                                         \
     NS_CYCLE_COLLECTION_CLASSNAME(_class)::                                 \
       Downcast(static_cast<nsISupports*>(p))->DeleteCycleCollectable();     \
--- a/xpcom/base/nsCycleCollectionParticipant.h
+++ b/xpcom/base/nsCycleCollectionParticipant.h
@@ -108,22 +108,16 @@ private:
 };
 
 /**
  * Participant implementation classes
  */
 class NS_NO_VTABLE nsCycleCollectionParticipant
 {
 public:
-  constexpr nsCycleCollectionParticipant()
-    : mMightSkip(false)
-    , mTraverseShouldTrace(false)
-  {
-  }
-
   constexpr explicit nsCycleCollectionParticipant(bool aSkip,
                                                   bool aTraverseShouldTrace = false)
     : mMightSkip(aSkip)
     , mTraverseShouldTrace(aTraverseShouldTrace)
   {
   }
 
   NS_IMETHOD TraverseNative(void* aPtr, nsCycleCollectionTraversalCallback& aCb) = 0;
@@ -243,37 +237,29 @@ protected:
 private:
   const bool mMightSkip;
   const bool mTraverseShouldTrace;
 };
 
 class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
 {
 public:
-  constexpr nsScriptObjectTracer()
-    : nsCycleCollectionParticipant(false, true)
-  {
-  }
   constexpr explicit nsScriptObjectTracer(bool aSkip)
     : nsCycleCollectionParticipant(aSkip, true)
   {
   }
 
   NS_IMETHOD_(void) Trace(void* aPtr, const TraceCallbacks& aCb,
                           void* aClosure) override = 0;
 
 };
 
 class NS_NO_VTABLE nsXPCOMCycleCollectionParticipant : public nsScriptObjectTracer
 {
 public:
-  constexpr nsXPCOMCycleCollectionParticipant()
-    : nsScriptObjectTracer(false)
-  {
-  }
   constexpr explicit nsXPCOMCycleCollectionParticipant(bool aSkip)
     : nsScriptObjectTracer(aSkip)
   {
   }
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID)
 
   NS_IMETHOD_(void) Root(void* aPtr) override;
@@ -624,33 +610,38 @@ public:                                 
 #else
 #define NOT_INHERITED_CANT_OVERRIDE
 #endif
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base)                \
 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
  : public nsXPCOMCycleCollectionParticipant                                    \
 {                                                                              \
+public:                                                                        \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)       \
+    : nsXPCOMCycleCollectionParticipant(aSkip) {}                              \
+private:                                                                       \
   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                           \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
 };                                                                             \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                    \
 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;           \
   NOT_INHERITED_CANT_OVERRIDE
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS(_class)                                 \
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
 
 // Cycle collector helper for ambiguous classes that can sometimes be skipped.
 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base)        \
 class NS_CYCLE_COLLECTION_INNERCLASS                                             \
  : public nsXPCOMCycleCollectionParticipant                                      \
 {                                                                                \
 public:                                                                          \
-  constexpr NS_CYCLE_COLLECTION_INNERCLASS ()                                    \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true)          \
+    /* Ignore aSkip: we always want skippability. */                             \
   : nsXPCOMCycleCollectionParticipant(true) {}                                   \
 private:                                                                         \
   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                             \
   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override;        \
   NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override;                           \
   NS_IMETHOD_(bool) CanSkipThisReal(void *p) override;                           \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                         \
 };                                                                               \
@@ -660,30 +651,35 @@ NOT_INHERITED_CANT_OVERRIDE
 
 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class)                       \
         NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class)
 
 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base)          \
 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
  : public nsXPCOMCycleCollectionParticipant                                            \
 {                                                                                      \
+public:                                                                                \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)               \
+  : nsXPCOMCycleCollectionParticipant(aSkip) {}                                        \
+private:                                                                               \
   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                                   \
   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override;  \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
 };                                                                                     \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class)                                            \
 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; \
 NOT_INHERITED_CANT_OVERRIDE
 
 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base)   \
 class NS_CYCLE_COLLECTION_INNERCLASS                                                      \
  : public nsXPCOMCycleCollectionParticipant                                               \
 {                                                                                         \
 public:                                                                                   \
-  constexpr NS_CYCLE_COLLECTION_INNERCLASS ()                                             \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true)                   \
+    /* Ignore aSkip: we always want skippability. */                                      \
   : nsXPCOMCycleCollectionParticipant(true) {}                                            \
 private:                                                                                  \
   NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base)                                      \
   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override;     \
   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override;                 \
   NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override;                                    \
   NS_IMETHOD_(bool) CanSkipThisReal(void *p) override;                                    \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                                  \
@@ -695,16 +691,21 @@ NOT_INHERITED_CANT_OVERRIDE
 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class)  \
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
 
 #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class,       \
                                                                          _base_class)  \
 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                                   \
 {                                                                                      \
+public:                                                                                \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = true)                \
+    /* Ignore aSkip: we always want skippability. */                                   \
+    : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (true) {}                             \
+private:                                                                               \
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)                   \
   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure) override;  \
   NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed) override;              \
   NS_IMETHOD_(bool) CanSkipInCCReal(void *p) override;                                 \
   NS_IMETHOD_(bool) CanSkipThisReal(void *p) override;                                 \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
 }; \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class)  \
@@ -729,39 +730,49 @@ public:                                 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
   NS_IMETHOD_(void) Unlink(void *p) override;
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class)          \
 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
 {                                                                              \
 public:                                                                        \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)       \
+    : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {}                    \
+private:                                                                       \
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)           \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
 };                                                                             \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class)                          \
 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
 
 #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class,             \
                                                            _base_class)        \
 class NS_CYCLE_COLLECTION_INNERCLASS                                           \
  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                           \
 {                                                                              \
 public:                                                                        \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)       \
+    : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {}                    \
+private:                                                                       \
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                       \
 };                                                                             \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class)                          \
 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
 
 #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class,                 \
                                                                _base_class)            \
 class NS_CYCLE_COLLECTION_INNERCLASS                                                   \
  : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class)                                   \
 {                                                                                      \
+public:                                                                                \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)               \
+    : NS_CYCLE_COLLECTION_CLASSNAME(_base_class) (aSkip) {}                            \
+private:                                                                               \
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class)                   \
   NS_IMETHOD_(void) Trace(void *p, const TraceCallbacks &cb, void *closure)            \
     override;                                                                          \
   NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class)                               \
 };                                                                                     \
 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL_INHERITED(_class)                                  \
 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
 
@@ -791,16 +802,20 @@ static NS_CYCLE_COLLECTION_INNERCLASS NS
 #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class)                          \
   void DeleteCycleCollectable(void)                                            \
   {                                                                            \
     delete this;                                                               \
   }                                                                            \
   class NS_CYCLE_COLLECTION_INNERCLASS                                         \
    : public nsCycleCollectionParticipant                                       \
   {                                                                            \
+public:                                                                        \
+  constexpr explicit NS_CYCLE_COLLECTION_INNERCLASS (bool aSkip = false)       \
+    : nsCycleCollectionParticipant(aSkip) {}                                   \
+private:                                                                       \
     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class)                         \
     static constexpr nsCycleCollectionParticipant* GetParticipant()            \